7

我正在测试一些内在操作的行为。当我注意到 _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() 的作用以及我们为什么使用它,但现在的问题更多是关于它是如何工作的。如果有人可以解释或提供任何相关文章来理解这种行为,那就太好了。

4

1 回答 1

3

_mm_mfence()从体系结构上讲,只编译为mfence 指令,它不是加载或存储

不过,它解码的一个或多个微指令可能在微架构上运行在加载端口上并被计为一个负载。

你用的是什么CPU?如果是 Skylake,我假设您已经更新了微码,因此mfence成本比 Agner Fog 的表格中列出的要高。(并且它阻止了非内存 uops 的乱lfence执行mfence, 例如

于 2019-02-25T23:50:29.317 回答