c - _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。
解决方案
我在一次迭代中得到超过 1000 个时钟周期的结果,下一次是 200 个。
听起来您的 CPU 在前几次迭代后从空闲加速到正常时钟速度。
请记住,RDTSC 计算参考周期(固定频率,等于或接近 CPU 的最大非涡轮频率),而不是核心时钟周期。(怠速/涡轮增压/其他)。较旧的 CPU 具有 RDTSC 计数核心时钟周期,但多年来 CPU 供应商已经拥有固定的 RDTSC 频率,使其有用,并通过CPUID 功能位clock_gettime()
宣传这一事实。另请参阅获取 CPU 周期数?invariant_tsc
如果您真的想使用 RDTSC 而不是性能计数器,请禁用 turbo 并使用预热循环使 CPU 达到其最大频率。
有一些库可以让您对硬件性能计数器进行编程,并设置权限以便您可以rdpmc
在用户空间中运行。这实际上比rdtsc
. 有关在用户空间中访问性能计数器的方法的摘要,请参阅在英特尔 Kaby Lake 架构上获取最后一级缓存未命中计数的确切代码是什么。
我还发现了一篇关于向rdpmc
Linux perf
(PAPI) 添加用户空间支持的论文:ftp: //ftp.cs.uoregon.edu/pub/malony/ESPT/Papers/espt-paper-1.pdf。IDK 是否将其纳入主线内核/性能代码。
推荐阅读
- python - DataFrame 按组计算具有条件的总股票收益
- javascript - Angular Firestore 权限不足
- python - Holoviews 中的水平滚动条
- nestjs - Nest JS - 尝试在 RolesGuard 中获取用户上下文时返回未定义
- quickfixj - QuickFIX/J :设置 StartTime/EndTime 以便会话永久运行
- flutter - 无法从本地 Web 服务器获取数据
- flutter - 如何在颤动中向grpc移动客户端添加拦截器
- java - 我可以在运行时查询 lambda 函数的生命周期吗?
- javascript - 如何获取当前设置的 CSS 样式?
- python - 获取日期范围内每小时的数据