_mm_lfence() 时间开销是不确定的?

_mm_lfence() time overhead is non deterministic?

我正在尝试确定读取元素所需的时间以确保它是缓存命中或缓存未命中。为了让阅读有序,我使用 _mm_lfence() 函数。我得到了意想不到的结果,在检查后我发现 lfence 函数的开销不是确定性的。 所以我正在执行一个程序,在一个循环中测量这个开销,例如 100 000 次迭代。我得到一次迭代超过 1000 个时钟周期的结果,下一次是 200 个。 lfence 函数开销之间存在这种差异的原因是什么?如果它如此不可靠,我如何正确判断缓存命中和缓存未命中的延迟?我试图使用与此 post 中相同的方法:

给出不可靠结果的代码是这样的:

for(int i=0; i < arr_size; i++){
  _mm_mfence();
  _mm_lfence();
   t1 = __rdtsc();
  _mm_lfence();
  _mm_lfence();
   t2 = __rdtsc();
  _mm_lfence();

   arr[i] = t2-t1;
}

arr中的值在不同的范围内变化,arr_size是100 000。

I get results of more than 1000 clock cycle for one iteration and next time it's 200.

听起来您的 CPU 在前几次迭代后从闲置时钟速度上升到正常时钟速度。

请记住,RDTSC 计数 参考 周期(固定频率,等于或接近 [=41 的最大非涡轮频率=]), 不是核心时钟周期。 (idle/turbo / 随便什么)。较旧的 CPU 具有 RDTSC 计数内核时钟周期,但多年来 CPU 供应商已经拥有固定的 RDTSC 频率,使其对 clock_gettime() 很有用,并宣传了这一事实 with the invariant_tsc CPUID feature bit. See also Get CPU cycle count?

如果您真的想使用 RDTSC 而不是性能计数器,请禁用 Turbo 并使用预热循环让您的 CPU 达到最大频率。


有些库可让您对硬件性能计数器进行编程,并设置权限以便您可以 运行 rdpmc 在用户 space 中。这实际上比 rdtsc 的开销更低。有关在用户 space.

中访问性能计数器的方法的摘要,请参阅

我还找到了一篇关于向 Linux perf (PAPI) 添加 user-space rdpmc 支持的论文:ftp://ftp.cs.uoregon.edu/pub/malony/ESPT/Papers/espt-paper-1.pdf。 IDK 是否将其纳入主线 kernel/perf 代码。