为什么转置 512x512 矩阵比转置 513x513 矩阵慢得多?

2024-01-22

在对不同大小的方阵进行一些实验后,出现了一个模式。总是,转置大小矩阵2^n比转置某一尺寸慢2^n+1。对于较小的值n,差别并不大。

然而,超过 512 的值就会出现很大的差异。(至少对我来说)

免责声明:我知道由于元素的双重交换,该函数实际上并未转置矩阵,但这没有什么区别。

遵循代码:

#define SAMPLES 1000
#define MATSIZE 512

#include <time.h>
#include <iostream>
int mat[MATSIZE][MATSIZE];

void transpose()
{
   for ( int i = 0 ; i < MATSIZE ; i++ )
   for ( int j = 0 ; j < MATSIZE ; j++ )
   {
       int aux = mat[i][j];
       mat[i][j] = mat[j][i];
       mat[j][i] = aux;
   }
}

int main()
{
   //initialize matrix
   for ( int i = 0 ; i < MATSIZE ; i++ )
   for ( int j = 0 ; j < MATSIZE ; j++ )
       mat[i][j] = i+j;

   int t = clock();
   for ( int i = 0 ; i < SAMPLES ; i++ )
       transpose();
   int elapsed = clock() - t;

   std::cout << "Average for a matrix of " << MATSIZE << ": " << elapsed / SAMPLES;
}

改变MATSIZE让我们改变大小(废话!)。我在ideone上发布了两个版本:

  • size 512- 平均的2.46 ms - http://ideone.com/1PV7m http://ideone.com/1PV7m
  • size 513- 平均的0.75 ms - http://ideone.com/NShpo http://ideone.com/NShpo

在我的环境(MSVS 2010,全面优化)中,差异类似:

  • size 512- 平均的2.19 ms
  • size 513- 平均的0.57 ms

为什么会发生这种情况?


解释来自 Agner Fog 在用 C++ 优化软件 http://www.agner.org/optimize/optimizing_cpp.pdf它减少了数据在缓存中的访问和存储方式。

有关条款和详细信息,请参阅关于缓存的 wiki 条目 http://en.wikipedia.org/wiki/L2_cache,我要在这里缩小范围。

缓存的组织方式为sets and lines。一次仅使用一组,可以使用其中包含的任何行。一条线可以镜像的内存乘以线数即可得出缓存大小。

对于特定的内存地址,我们可以使用以下公式计算哪个集合应该镜像它:

set = ( address / lineSize ) % numberOfsets

这种公式理想地给出了集合之间的均匀分布,因为每个内存地址都有可能被读取(我说过ideally).

很明显,可能会发生重叠。如果发生高速缓存未命中,则会在高速缓存中读取内存并替换旧值。请记住,每组都有许多行,其中最近最少使用的行将被新读取的内存覆盖。

我将尝试遵循阿格纳的例子:

假设每组有 4 行,每行保存 64 字节。我们首先尝试读取地址0x2710,进入集合28。然后我们还尝试读取地址0x2F00, 0x3700, 0x3F00 and 0x4700。所有这些都属于同一组。读之前0x4700,集合中的所有行都将被占用。读取该内存会逐出集合中的现有行,即最初保留的行0x2710。问题在于我们读取的地址是(对于本例)0x800分开。这是关键的一步(同样,对于这个例子)。

临界步幅也可以计算:

criticalStride = numberOfSets * lineSize

变量间隔criticalStride或者多个部分竞争相同的高速缓存线。

这是理论部分。接下来是解释(也是阿格纳,我正在密切关注以避免犯错误):

假设一个 64x64 的矩阵(记住,效果根据缓存而变化),具有 8kb 缓存,每组 4 行 * 行大小为 64 字节。每行可以容纳矩阵中的 8 个元素(64 位int).

关键步幅为 2048 字节,对应于矩阵的 4 行(在内存中是连续的)。

假设我们正在处理第 28 行。我们尝试获取该行的元素并将它们与第 28 列中的元素交换。该行的前 8 个元素组成一个缓存行,但它们将进入 8 个不同的缓存行。缓存第 28 列中的行。请记住,关键步长是相隔 4 行(一列中的 4 个连续元素)。

当列中到达元素 16 时(每组 4 条高速缓存行且相隔 4 行 = 麻烦),ex-0 元素将从高速缓存中逐出。当我们到达列的末尾时,所有先前的缓存行都将丢失,并且需要在访问下一个元素时重新加载(整行被覆盖)。

大小不是关键步幅的倍数会搞乱这个完美的场景对于灾难,由于我们不再处理垂直方向上相隔很远的元素,因此缓存重新加载的次数大大减少。

另一项免责声明- 我刚刚明白了这个解释,希望我能解释清楚,但我可能是错的。无论如何,我正在等待来自的回复(或确认)神秘的 https://stackoverflow.com/users/922184/mysticial. :)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么转置 512x512 矩阵比转置 513x513 矩阵慢得多? 的相关文章

  • R 数据结构的运算效率

    我想知道是否有任何关于操作效率的文档R 特别是那些与数据操作相关的 例如 我认为向数据框添加列是有效的 因为我猜您只是向链接列表添加一个元素 我想添加行会更慢 因为向量保存在数组中C level你必须分配一个新的长度数组n 1并将所有元素复
  • 为什么libc++的shared_ptr实现使用完整内存屏障而不是宽松内存屏障?

    在boost的实现中shared ptr 它用放松内存排序以增加其引用计数 https github com boostorg smart ptr blob master include boost smart ptr detail sp
  • 为什么大多数 C 开发人员使用 Define 而不是 const? [复制]

    这个问题在这里已经有答案了 在许多程序中 define与常量具有相同的用途 例如 define FIELD WIDTH 10 const int fieldWidth 10 我通常认为第一种形式优于另一种形式 它依赖于预处理器来处理基本上是
  • C++:重写已弃用的虚拟方法时出现弃用警告

    我有一个纯虚拟类 它有一个纯虚拟方法 应该是const 但不幸的是不是 该接口位于库中 并且该类由单独项目中的其他几个类继承 我正在尝试使用这个方法const不会破坏兼容性 至少在一段时间内 但我找不到在非常量方法重载时产生警告的方法 以下
  • 对齐 GridView 中的行值

    我需要在 asp net 3 5 中右对齐 gridview 列中的值 我怎样才能做到这一点
  • 如何识别 WPF 文本框中的 ValidationError 工具提示位置

    我添加了一个箭头来指示工具提示中的文本框 当文本框远离屏幕边缘时 这非常有效 但是当它靠近屏幕边缘时 工具提示位置发生变化 箭头显示在左侧 Here is the Image Correct as expected since TextBo
  • Qt 创建布局并动态添加小部件到布局

    我正在尝试在 MainWindow 类中动态创建布局 我有四个框架 它们是用网格布局对象放置的 每个框架都包含一个自定义的 ClockWidget 我希望 ClockWidget 对象在调整主窗口大小时相应地调整大小 因此我需要将它们添加到
  • 将数据打印到文件

    我已经超载了 lt lt 运算符 使其写入文件并写入控制台 我已经为同一个函数创建了 8 个线程 并且我想输出 hello hi 如果我在无限循环中运行这个线程例程 文件中的o p是 hello hi hello hi hello hi e
  • 无法将类型“System.IO.Stream”隐式转换为“Java.IO.InputStream”

    我提到了一些类似的问题 但没有一个涉及IO 当我使用时 我在java中使用了相同的代码Eclipse 那次就成功了 但现在我尝试在中使用这段代码Mono for Android C 它不起作用 我正在尝试运行此代码来创建一个InputStr
  • C# 中条件编译符号的编译时检查(参见示例)?

    在 C C 中你可以这样做 define IN USE 1 define NOT IN USE 1 define USING system 1 system 1 IN USE 进而 define MY SYSTEM IN USE if US
  • 尚未处理时调用 Form 的 Invoke 时出现 ObjectDisposeException

    我们得到一个ObjectDisposedException从一个电话到Invoke在尚未处理的表格上 这是一些演示该问题的示例代码 public partial class Form2 Form void Form2 Load object
  • 将代码拆分为标头/源文件

    我从 Asio 的示例页面中获取了以下代码 class tcp connection public boost enable shared from this
  • 是否可以有一个 out ParameterExpression?

    我想定义一个 Lambda 表达式out范围 有可能做到吗 下面是我尝试过的 C Net 4 0 控制台应用程序的代码片段 正如您在 procedure25 中看到的 我可以使用 lambda 表达式来定义具有输出参数的委托 但是 当我想使
  • 如何清除 APC 缓存而不使 Apache 崩溃?

    如果 APC 存储大量条目 清除它们会导致 httpd 崩溃 如果 apc clear cache user 花费的时间超过 phps max execution time 调用 apc clear cache 的脚本 将在之前被 php
  • 结构体指针的动态数组

    我必须使用以下代码块来完成学校作业 严格不进行任何修改 typedef struct char firstName char lastName int id float mark pStudentRecord pStudentRecord
  • strcmp 给出分段错误[重复]

    这个问题在这里已经有答案了 这是我的代码给出分段错误 include
  • 带重定向标准流的 C# + telnet 进程立即退出

    我正在尝试用 C 做一个 脚本化 telnet 项目 有点类似于Tcl期望 http expect nist gov 我需要为其启动 telnet 进程并重定向 和处理 其 stdin stdout 流 问题是 生成的 telnet 进程在
  • Googletest:如何异步运行测试?

    考虑到一个包含数千个测试的大型项目 其中一些测试需要几分钟才能完成 如果按顺序执行 整套测试需要一个多小时才能完成 通过并行执行测试可以减少测试时间 据我所知 没有办法直接从 googletest mock 做到这一点 就像 async选项
  • 使用 Crypto++ 获取 ECDSA 签名

    我必须使用 Crypto 在变量中获取 ECDSA 签名 我在启动 SignMessage 后尝试获取它 但签名为空 我怎样才能得到它 你看过 Crypto wiki 吗 上面有很多东西椭圆曲线数字签名算法 http www cryptop
  • 匿名结构体作为返回类型

    下面的代码编译得很好VC 19 00 23506 http rextester com GMUP11493 标志 Wall WX Za 与VC 19 10 25109 0 标志 Wall WX Za permissive 这可以在以下位置检

随机推荐

  • Flutter:使用导航器推送到新屏幕时保留 BottomNavigationBar

    在iOS中 我们有一个UITabBar控制器 https developer apple com documentation uikit uitabbarcontroller当我们推送到新的 ViewController 时 它会永久保留在
  • 如何使用 Google Cloud Pub/Sub 进行 Junit 测试

    我在我的系统中使用Google Cloud Pub Sub的push pub sub 我想构建我的CI测试代码 但我不知道如何去做 例如 一些代码是这样的 final Pubsub pubsub PubsubUtils getClient
  • Clang:将函数的 AST 从原始文件写入新文件

    我是 Clang 的新手 正在尝试通过 libtooling 分析 AST 我想找到一个特定的函数 并将其 AST 从原始源文件移动到新文件 我已经知道如何通过 MatchFinder 找到该函数 现在 我想知道如何将其 AST 写入新文件
  • 在 Gstreamer 上流式传输 MP4 视频文件

    我第一次使用 gstreamer 并尝试使用 Gstreamer RTP 和 UDP 将 MP4 视频文件从服务器流式传输到客户端 我尝试使用的命令行 在服务器端 gst launch 1 0 v filesrc location file
  • 确定图像中的文本和图形区域

    我不知道我是否应该在这里发布这个问题 但如果有人知道请回答一下 用于确定图像中哪个区域是文本 哪个区域是图形的算法是什么 意味着如何分离这些区域 图或图 大多数 OCR 软件 例如Ocropus http code google com p
  • iOS 7 访问企业应用程序中的 UUID 值(不适用于 AppStore)

    Apple 自 iOS7 起已弃用且无法使用该属性 uniqueIdentifier 其他属性 identifierForVendor and advertisingIdentifier有一个大问题 他们在卸载并重新安装应用程序后更改了值
  • 视图和 $this 中的 Cakephp 助手

    我正在尝试确定在视图中使用助手的最佳标准是否应该 echo form gt input or echo this gt Form gt input 在 CakePHP 手册 1 2 版中 Helper 类是通过 helper 对象直接访问的
  • Scala Nil 相当于 Set

    是否有相当于Nil for Set在斯卡拉 我尝试使用Nil作为一个值Set 但我得到了一个错误 预期是因为类型Nil is List Thanks Set empty是那个集合吗 虽然你无法直接获取它 但事实证明它只是Set伴生对象 显然
  • 一个通用 Google Analytics(分析)代码中包含多个属性

    我正在尝试在我的网站中嵌入基于新的 Universal Analytics 方法的 GA 代码 我想要实现的是将数据从一个页面发送到多个属性 因此 我检查了有关新通用 GA 代码的官方 GA 文档 特别是有关 使用多 个跟踪对象 的部分 h
  • R 根据另一列的因子水平创建新的值列[重复]

    这个问题在这里已经有答案了 我正在尝试根据另一列的值创建一个新的值列 如果 iucnStatus 列中的值为 LC 或 NT 我希望新列 受威胁 中的值为 Not Threatened 如果 iucnStatus 中的值为 VU EN CR
  • 我可以在 Subversion 中关闭自动合并吗?

    我们正在考虑从版本控制系统的签出 编辑 签入风格转向 Subversion 在评估过程中我们发现 当您在 TortoiseSVN 可能还有任何 Subversion 客户端 中执行更新操作时 如果存储库中需要应用于您正在编辑的文件的更改不会
  • 在运行时更改类类型

    我有两个课程 我们称它们为A and B 两者都继承自一个共同的超类 C 假设我需要建立一个List of Cs 我的问题是 根据收到的数据C的构造函数我需要放一个A or B列表内的对象 有没有办法从内部做到这一点C的构造函数 或者 我该
  • 如何从 Gradle 启用 Eclipselink 的静态编织

    我想为 Gradle 中的 JPA 类启用 Eclipselink 的静态编织 Eclipselink 文档解释了如何在 Ant 任务中执行此操作
  • 使用EChart.JS绘制水平目标线

    我想使用 EChart JS 绘制一条水平目标线 显示折线图 条形图和饼图上的阈值限制 https ecomfe github io echarts doc public en index html https ecomfe github
  • 构建iOS自定义通用框架,其中包括其他框架

    我正在尝试构建一个社交媒体集成框架 以便开发人员可以导入此框架 调用此框架中的 API 并在他们的应用程序中进行社交媒体操作 而不必导入和处理多个 SDK 及其代码 如下这个写得很精彩的教程 https github com jverkoe
  • 定期执行 PHP 脚本的最佳方法?

    如果我可以完全访问服务器 我可能会找到一种方法来做到这一点 但问题是它只是一个托管服务 除了FTP访问 我想定期运行 PHP 脚本来检查过时 损坏的内容 聚合新内容 删除未使用的文件等 但是该脚本可以采取长达 60 秒执行 由于内容聚合 我
  • 如何在闪亮的仪表板中以特定时间间隔将新行重新绑定到数据表?

    我正在创建一个有 2 个输出的闪亮应用程序datatableoutput and plotoutput 我有2个变量st and et在将初始化为值的数据框中 我需要向具有以下逻辑的现有数据框添加新行1 新st值是之前的值et 2 新et值
  • 亚马逊 S3 CORS 错误

    当我的应用程序通过 amazon S3 上的 Javascript 请求文件时 我收到了权限被拒绝的错误 我设置了一个 CORS 文件 它似乎在大多数情况下都可以工作 但会间歇性地失败 我总是可以通过清除浏览器缓存来解决这个问题 关于这可能
  • 将 DataFrame 保存为 cvs 时 Spark 2.0 DataSourceRegister 配置错误

    我正在尝试将数据帧保存到 Spark 2 0 Scala 2 11 中的 cvs 从 Spark 1 6 迁移代码的过程 sparkSession sql SELECT FROM myTable coalesce 1 write forma
  • 为什么转置 512x512 矩阵比转置 513x513 矩阵慢得多?

    在对不同大小的方阵进行一些实验后 出现了一个模式 总是 转置大小矩阵2 n比转置某一尺寸慢2 n 1 对于较小的值n 差别并不大 然而 超过 512 的值就会出现很大的差异 至少对我来说 免责声明 我知道由于元素的双重交换 该函数实际上并未