首页 > 解决方案 > _mm_lfence() 时间开销是不确定的?

问题描述

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

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

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。

标签: cperformancex86intrinsicsrdtsc

解决方案


我在一次迭代中得到超过 1000 个时钟周期的结果,下一次是 200 个。

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

请记住,RDTSC 计算参考周期(固定频率,等于或接近 CPU 的最大非涡轮频率),而不是核心时钟周期。(怠速/涡轮增压/其他)。较旧的 CPU 具有 RDTSC 计数核心时钟周期,但多年来 CPU 供应商已经拥有固定的 RDTSC 频率,使其有用,并通过CPUID 功能位clock_gettime()宣传这一事实。另请参阅获取 CPU 周期数?invariant_tsc

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


有一些库可以让您对硬件性能计数器进行编程,并设置权限以便您可以rdpmc在用户空间中运行。这实际上比rdtsc. 有关在用户空间中访问性能计数器的方法的摘要,请参阅在英特尔 Kaby Lake 架构上获取最后一级缓存未命中计数的确切代码是什么。

我还发现了一篇关于向rdpmcLinux perf(PAPI) 添加用户空间支持的论文:ftp: //ftp.cs.uoregon.edu/pub/malony/ESPT/Papers/espt-paper-1.pdf。IDK 是否将其纳入主线内核/性能代码。


推荐阅读