C++ 指针追踪基准:读取+;写入(CLFLUSH)比读取(CLFLUSH)快
我试图理解使用CLFLUSH对性能的影响。为此,我编写了一个小型指针跟踪基准测试。我取一个C++ 指针追踪基准:读取+;写入(CLFLUSH)比读取(CLFLUSH)快,c++,performance,caching,cpu,C++,Performance,Caching,Cpu,我试图理解使用CLFLUSH对性能的影响。为此,我编写了一个小型指针跟踪基准测试。我取一个std::vector,其中第一个元素是下一个条目的偏移量,第二个元素是有效负载。我从条目0转到下一个条目,依此类推,直到到达开头。在路上,我计算所有有效载荷的总和 另外,我有两个参数:如果write==1,则在读取有效负载后修改它(从而使缓存线无效)。如果clflush==1,则在转到下一个元素之前执行clflush 向量的大小等于一级缓存的大小(32 KiB) 以下是我的结果: write clfl
std::vector
,其中第一个元素是下一个条目的偏移量,第二个元素是有效负载。我从条目0转到下一个条目,依此类推,直到到达开头。在路上,我计算所有有效载荷的总和
另外,我有两个参数:如果write==1
,则在读取有效负载后修改它(从而使缓存线无效)。如果clflush==1
,则在转到下一个元素之前执行clflush
向量的大小等于一级缓存的大小(32 KiB)
以下是我的结果:
write clflush runtime
0 0 5324060
0 1 298751237
1 0 4366570
1 1 180303091
我确实理解为什么使用clflush的运行比不使用clflush的运行慢。但是为什么读写比写快,为什么脏缓存线比干净缓存线看起来更快
作为参考,您可以找到我的基准测试,我使用
g++-4.8-std=c++11-lrt-O3编译了它这可能不是一个答案,但我认为您看到的效果不是真实的。以下是我在Haswell i7-4770上使用不同编译器运行您的测试程序时看到的情况:
nate@haswell:~/stack$ chase-g481-orig
write clflush runtime
0 0 3238411
0 1 55916728
1 0 3220700
1 1 88299263
nate@haswell:~/stack$ chase-icpc-orig
write clflush runtime
0 0 3226673
0 1 53840185
1 0 4858013
1 1 88143220
nate@haswell:~/stack$ chase-clang-orig
write clflush runtime
0 0 13521595
0 1 54542441
1 0 3394006
1 1 88344640
他们之间有很多不同,但没有一个和你看到的相符。我还在一个沙桥E5-1620上运行,发现了与这些类似的结果(与您的结果不匹配),尽管那台机器上较旧版本的clang++没有在无写无刷新的情况下崩溃
首先,您的程序试图使用整个一级缓存有点尴尬。如果您完全控制了系统(启动时保留CPU),这可能是合理的,但似乎会引入混淆效应。如果您的目标是了解这种效果,而不是查看缓存在满容量时的行为,那么我建议将总大小更改为缓存大小的1/2
我认为最有可能的解释是,不同的编译器正在将clflush提升到函数中的不同位置,而其中一些编译器并没有完成您希望它执行的操作。在这个级别上工作时,要说服编译器做您想做的事情可能非常困难。由于clflush内在函数实际上不会改变结果,因此优化器规则通常会破坏您的意图
我试图查看生成的程序集(objdump-d-C chase),但在获取方向时遇到了问题。所有内容都直接内联到main中,因此它不像查看chase()函数来查看发生了什么那样简单。使用-g编译(用于调试)并将-S(用于源代码)添加到objdump命令有帮助,但仍然很复杂。我试图阻止编译器内联失败
如果是我,我会切换到C并使用-fno内联函数编译,然后检查是否仍然得到相同的效果。然后剖析chase()函数,直到了解发生了什么。然后使用gcc-S输出程序集,修改它,直到其顺序正确,然后查看效果是否仍然存在
还值得注意的是,根据《英特尔体系结构参考手册》,clflush不是串行化指令。即使程序集是按照您认为应该的顺序进行的,处理器也可以公平地执行前后的指令。考虑到你追逐的方式,我认为窗口不够宽,不足以成为一个因素,但谁知道呢。可以通过添加mfence来强制序列化
另一种可能是clflush在特定处理器上的行为异常。您可以切换使用“wbinvd”使所有缓存无效的核心选项。这是一条很难执行的指令,因为它是“私有的”,需要由内核执行。你必须写一个ioctl来做这件事
祝你好运 嗨,内森,谢谢你详细的回答,很抱歉我的回复迟了。重新排序的CLFLUSH是一个重要的问题-我错过了一个SFENCE。尽管如此,理解性能影响仍然相当困难。对于我们的项目,我们已经切换到不同的基准,以实现我们所需要的。