我正在测试一些内在操作的行为。当我注意到 _mm_mfence() 从用户空间发出加载指令时,我感到很惊讶,但它不计入 L1 数据缓存 - 未命中、命中或填充缓冲区命中。我正在使用 papi 的本机事件,例如 MEM_INST_RETIRED 和 MEM_LOAD_RETIRED 来读取性能计数器。这段代码:
for(int i=0; i < 1000000; i++){
_mm_mfence();
}
计数 ALL_LOADS: 737030, L1_HIT: 99, L1_MISS: 10, FB_HIT: 25。没有 mfence 时,读取计数器的开销是这样的:ALL_LOADS: 125, L1_HIT: 94, L1_MISS: 11, FB_HIT: 24
我查了一下,sfence 和 lfence 没有这个影响。我正在使用 -O3 进行编译。从编译的文件中我猜它调用了 __builtin_ia32_mfence 函数,但我找不到太多关于它的内容。
我大致了解 _mm_mfence() 的作用以及我们为什么使用它,但现在的问题更多是关于它是如何工作的。如果有人可以解释或提供任何相关文章来理解这种行为,那就太好了。