首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在配置文件引导的优化之后,嵌套for循环速度更快,但缓存丢失率更高

在配置文件引导的优化之后,嵌套for循环速度更快,但缓存丢失率更高
EN

Stack Overflow用户
提问于 2014-04-09 20:44:14
回答 1查看 465关注 0票数 5

我有一个程序,它的核心是一个二维数组,其形式是

代码语言:javascript
复制
std::vector<std::vector< int > > grid

有一个简单的双for循环,有点像这样:

代码语言:javascript
复制
for(int i=1; i<N-1; ++i)
    for(int j=1; j<N-1; ++j)
        sum += grid[i][j-1] + grid[i][j+1] + grid[i-1][j] + grid[i+1][j] + grid[i][j]*some_float;

对于g++ -O3,它运行得相当快,但是对于进一步的优化,我使用了Cache分析,发现L1缓存丢失了大约37%,而LL则是33%,考虑到计算的随机性,这是一个很大但也不令人惊讶的结果。所以我做了一个配置文件引导的优化,a la。

代码语言:javascript
复制
g++ -fprofile-generate -O3 ...
./program
g++ -fprofile-use -O3 ...

程序运行速度大约快48%!但令人费解的是:缓存丢失率甚至增加了!L1数据缓存丢失率现在是40%,LL相同。

这怎么可能呢?循环中没有条件项可以对预测进行优化,而且缓存丢失率甚至更高。但速度更快。

编辑:好的,这是sscce:http://pastebin.com/fLgskdQG。在不同的运行时与N一起玩。编译通过

代码语言:javascript
复制
g++ -O3 -std=c++11 -sscce.cpp

gcc 4.8.1在linux下。

配置文件引导的优化与上述命令。g++ -g开关和valgrind --tool=callgrind --simulate-cache=yes ./sscce完成了考勤的工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-04-10 13:42:51

我只注意到在使用或不使用PGO生成的汇编代码之间只有一个显著的差异。如果没有PGO,sum变量将从寄存器溢出到内存,每次内循环迭代一次。从理论上讲,将变量写入内存并将其加载回内存可能会显著降低内存的速度。幸运的是,现代处理器通过存储到负载转发优化了它,这样就不会太慢了。尽管如此,英特尔的优化手册不建议将浮点变量泄漏到内存中,特别是当它们是通过长延迟运算计算时,比如浮点乘法。

这里真正令人费解的是为什么GCC需要PGO来避免将寄存器溢出到内存中。这是足够的未使用的浮点寄存器,即使没有PGO编译器可以获得所有必要的信息,以适当优化从单个源文件.

这些不必要的加载/存储操作不仅解释了PGO代码速度更快的原因,还解释了为什么它会增加缓存丢失的百分比。如果没有PGO寄存器,则始终会溢出到内存中的相同位置,因此这种额外的内存访问会增加内存访问次数和缓存命中次数,而不会更改缓存丢失数。使用PGO,我们有较少的内存访问,但相同数量的缓存未命中,因此它们的百分比增加。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22973535

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档