我试图确定读取一个元素,以确保它是一个高速缓存命中或高速缓存未命中所需的时间。阅读是为了我用_mm_lfence()函数。我得到了意想不到的结果和检查后,我看到lfence的开销将是不确定的。所以我执行,在例如100 000迭代的循环测量这种开销的计划。我得到了一个迭代超过1000个时钟周期的结果,并在下一次的200有什么可以lfence功能开销之间的这种差异的一个原因,如果是这样不可靠的我怎么能判断缓存命中的延时和缓存未命中正确?我试图用同样的方法,因为在这个岗位:Memory latency measurement with time stamp counter
给出不可靠的结果的代码是这样的:
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。
我得到了一个迭代,并在下一次的200超过1000个时钟周期的结果。
听起来像是你的CPU从怠速到正常的时钟速度前几个迭代后憋足了。
请记住,RDTSC计数基准周期(固定频率,等于或接近CPU的最大非涡轮频率),而不是核心时钟周期。 (空闲/涡轮/其它)。较老的CPU有RDTSC计数内核时钟周期,但多年来却CPU厂商已经有了固定的频率RDTSC使之成为clock_gettime()
有用的,通告的这个事实with the invariant_tsc
CPUID feature bit。参见Get CPU cycle count?
如果你真的想使用RDTSC而不是性能计数器,禁止涡轮增压和使用热身圈让你的CPU的最大频率。
有迹象表明,让你的程序的硬件性能计数器,并设置权限,因此您可以在用户空间运行rdpmc
库。这实际上比rdtsc
较低的开销。见What will be the exact code to get count of last level cache misses on Intel Kaby Lake architecture的方式来访问用户空间Perf Counters的一个总结。
我还发现了一篇关于增加用户空间rdpmc
支持到Linux perf
(PAPI):ftp://ftp.cs.uoregon.edu/pub/malony/ESPT/Papers/espt-paper-1.pdf。 IDK如果这使它成为主线内核/ PERF代码或没有。
实用的答案:改用rdtscp RDTSC的(以及编译器的障碍,我不知道你是否会发现版将有一个),并删除您rdtscp的实例之间的lfences。这不会是完美的,但这应该降低误差。 Here is a slightly dated post that should be useful.
比你更想知道:指令排序和投机是很难推论。 Lfence是一个非常沉重的,复杂的锤子。它还后核弹的猜测,但它本身可以推测(有趣)执行。对于一些更详细的看看这个blogpost。