- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我一直在努力理解如何编写缓存友好的代码。因此,作为第一步,我试图了解数组行优先访问和列优先访问之间的性能差异。
所以我创建了一个大小为 512×512 的 int 数组,因此总大小为 1MB。我的一级缓存32KB,二级缓存256KB,三级缓存3MB。所以我的数组适合 L3 缓存。
我简单地计算了行主序和列主序的数组元素之和,并比较了它们的速度。一直以来,专栏主要顺序略快。我预计行主要订单会比其他订单更快(可能快几倍)。
我认为问题可能是由于数组的尺寸太小,所以我制作了另一个尺寸为 8192×8192 (256 MB) 的数组。结果还是一样。
下面是我使用的代码片段:
#include "time.h"
#include <stdio.h>
#define S 512
#define M S
#define N S
int main() {
// Summing in the row major order
int x = 0;
int iter = 25000;
int i, j;
int k[M][N];
int sum = 0;
clock_t start, end;
start = clock();
while(x < iter) {
for (i = 0; i < M; i++) {
for(j = 0; j < N; j++) {
sum += k[i][j];
}
}
x++;
}
end = clock();
printf("%i\n", end-start);
// Summing in the column major order
x = 0;
sum = 0;
int h[M][N];
start = clock();
while(x < iter) {
for (j = 0; j < N; j++) {
for(i = 0; i < M; i++){
sum += k[i][j];
}
}
x++;
}
end = clock();
printf("%i\n", end-start);
}
问题:有人可以告诉我我的错误是什么以及为什么我得到这个结果吗?
最佳答案
我真的不知道您为什么会出现这种行为,但让我澄清一些事情。
考虑缓存时至少要考虑两件事:缓存大小和缓存行大小。例如,我的 Intel i7 920 处理器有一个 256KB 的 L2 高速缓存,行大小为 64 字节。如果您的数据适合缓存,那么您访问它的顺序就无关紧要了。将代码优化为缓存友好的所有问题必须针对两件事:如果可能的话,将对内存的访问分成 block ,以便 block 适合缓存。用那个 block 做所有可能的计算,然后带下一个 block ,用它做计算等等。另一件事(您正在尝试做的事情)是以连续的方式访问内存。当您从内存中请求数据时(比如说一个 int - 4 字节),整个 cache line 都会被带到缓存中(在我的例子中是 64 字节:即 16 个相邻的整数(包括您请求)被带到缓存)。这是播放行顺序与列顺序的对比。使用行顺序,每 16 个内存请求有 1 个缓存未命中,使用列顺序,每个请求都会有一个缓存未命中(但前提是您的数据不适合缓存;如果您的数据适合缓存,那么您会得到与行顺序相同的比率,因为你仍然有缓存中的行,从你请求行中的第一个元素时开始;当然,关联性可以发挥作用,即使不是所有缓存都被填充,也可以重写缓存行与您的数据)。
关于你的问题,正如我所说,当数据适合缓存时,访问顺序并不重要,但是当你进行第二次求和时,数据已经在缓存中从你做第一个总和的时候开始,所以这就是它更快的原因。如果你先做列顺序求和,你应该看到行顺序求和变得更快,因为它是在之后完成的。但是,当数据足够大时,您不应该得到相同的行为。尝试以下操作:在两个总和之间,对另一个大数据做一些事情以使整个缓存无效。
编辑
I see a 3-4x speedup for row major (although I expected >8x speedup. any idea why?). [..] it would be great if you could tell me why speedup is only 3x
不是说以“正确的方式”访问矩阵并没有太大改善,更像是以“错误的方式”访问矩阵并没有那么大的伤害,如果这有任何意义的话。
虽然我无法为您提供具体而准确的答案,但我可以告诉您的是,现代处理器具有非常复杂且极其高效的缓存模型。它们非常强大,例如,在许多常见情况下,它们可以掩盖缓存级别,使您看起来像是拥有一个大的一级缓存而不是三级缓存(从从适合 L2 的尺码到只适合 L3 的尺码)。在较旧的处理器(比方说 10 岁)中运行您的代码,您可能会看到预期的加速。然而,现代处理器具有对缓存未命中有很大帮助的机制。桌面处理器的设计理念是快速运行“错误代码”,因此在改进“错误代码”性能方面进行了大量投资,因为绝大多数桌面应用程序不是由了解分支问题或缓存模型的人编写的。这与高性能市场相反,在高性能市场中,专用处理器会使错误代码受到很大伤害,因为它们实现了处理“错误代码”(或根本不实现)的弱机制。这些机制占用大量晶体管,因此会增加功耗和产生的热量,但它们值得在大多数代码都是“错误代码”的台式机处理器中实现。
关于c - 了解如何编写缓存友好的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20835357/
为了我们公司的 SEO 需求,我们需要通过 301 将一些 SEO URL 更改为另一个 URL。 示例: /seo/keywords-1-2-3/ 到 /seo/mynew301page-1-2-3
使已经开发的 Vue 应用程序对 SEO 友好的最简单方法是什么(搜索引擎可以读取所有标题元标记)。 我已经研究过 NUXT,我将不得不再次重新构建整个过程,而且除了 SSR(服务器端渲染)部分之外,
我正在使用 Azure 数据库进行一些数据库管理,我需要执行查询,例如删除数据库中的所有约束。 sp_MSForEachTable 在使用 Azure 数据库时不可用,因此我正在采用不同的方法来实现此
在我的研究中,我发现了 2 种方法。 两者都需要修改 Global.Asax 中的 Application_BeginRequest 过程,您可以在其中运行代码来进行实际的 URL 映射(我的数据库
例如我有这个字符串: make no@ sen# `se ! 我会像这样生成 url make-no-sen-se! 我有这个: var value = $('.titleVal').val(
我有一个网站,我想开始使用友好的 URL。 所以不是: http://server.com/company.php?id=12 我可以使用: http://server.com/company/ste
我正在用 pandas 编写一些数据分析管道。我一直在使用的数据框中的一列是由自定义编写的类的对象组成的,每个类都用一个字符串初始化,我用正则表达式从中读取各种信息并存储在对象的属性中。子类结构类似于
这个问题已经存在: C++ create new windows command [closed] 关闭 4 年前。 我正在尝试创建一个 C++ 控制台应用程序并创建新命令。 我想做的事的例子:在终
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 这个问题似乎与 help center 中定义的范围内的编程无关。 . 关闭 8 年前。 Improve
我一直在尝试为 prestashop 中的产品创建第二个 url 重写选项.在 SEO 和 URL 部分的标准 Prestashop 安装中,我得到了以下产品 url 构建: {category:/}
我在使用重写引擎通过友好的 url 实现我的目标时遇到了一些问题。 基本上我有以下结构:- 索引.php - 吃下 - index.php 我在主索引中的链接是这样的:下载/index.php?dow
我真的不喜欢在链接中使用选择/选项元素: 但是他们已经找到了作为一种选择进入设计师组合的方式,并尽我所能劝阻他们不要使用它们,我知道如果没有谷歌的力量,我会输掉这场战斗,而且“这对 SEO 不利”。
dispose: function() { var disposer; while (disposer = this._disposers.shift()) { // expected
我将 Heroku 应用程序上的自定义域更改为新域。现在我将创建一个新的 Heroku 应用程序,它的唯一目的是重定向到第一个应用程序。 我在 Google Webmasters 中读到我应该像这样进
我有一个类。这个类有2个字段。 我有一个整数数组。我的任务是重载友好的“+”运算符,以便可以将数组中的字段值与数组元素的值相加。 例如: class Test { public: double
这个问题在这里已经有了答案: Encode URL in JavaScript (22 个答案) 关闭 9 年前。 您好,我有这个 URL(顶部),我正在尝试与“pinterest”一起使用,他们会
jQuery 模式对话框 seo 友好吗?如果不是,我们可以进行哪些更改,以便爬虫可以轻松读取模态对话框中的内容? 提前致谢。 编辑:抱歉忘记提及模式中的内容来自服务器端。所以它也使用 ajax。 最
这是我的 main.js 文件: jQuery(function($) { $('LI.tree-item-name').has('ul').click(function() { if (
static func randomShape() -> Shape { // Find out count of possible shapes var maxValue = 0
我正在构建一个通过 index.php 运行所有代码的网站。 例如 index.php?controller=something&id=01234。 我想使用 PHP 创建友好的 URL,所以我这样做
我是一名优秀的程序员,十分优秀!