为什么_mm_mfence()会产生ALL_LOADS perf事件的计数?

问题描述 投票:6回答:1

我正在测试一些内在操作的行为。当我注意到_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()的作用以及我们使用它的原因,但现在问题更多的是它是如何工作的。如果有人能够解释或给出任何相关文章来理解这种行为,那将是很棒的。

c x86 intrinsics perf papi
1个回答
3
投票

_mm_mfence()编译成mfence指令,这不是装载或存储,从架构上讲

但是,它解码到的一个或多个uop可能会在一个加载端口上进行微体系结构运行并被计为负载。

你用的CPU是什么?如果Skylake,我认为你已经更新了微码,所以mfence的费用高于Agner Fog的表格。 (并且它阻止了非内存uops的无序执行,如lfence。请参阅Are loads and stores the only instructions that gets reordered?显然在Skylake没有为mfence执行此操作之前的一些Intel CPU。)

© www.soinside.com 2019 - 2024. All rights reserved.