我正在尝试确定读取元素所需的时间,以确保它是缓存命中或缓存未命中。为了阅读,我使用_mm_lfence()函数。我得到了意外的结果,检查后我发现lfence函数的开销不是确定性的。 因此,我正在执行一个程序,该程序在例如10万次迭代的循环中测量此开销。我得到一个迭代超过1000个时钟周期的结果,而下一次迭代则得到200个时钟周期。在函数功能开销之间存在如此大差异的原因是什么?如果如此不可靠,我如何正确判断缓存命中和缓存未命中的延迟呢?我正在尝试使用与本文相同的方法:Memory latency measurement with time stamp counter
给出不可靠结果的代码是这样的:
//this is the fuction exists into the app.js
const index = require('./serverSide/router/index');
initRoutes() {
app.use('/admin', index);
app.use('/', (req, res) => {
res.sendFile(__dirname + './src/index.html');
});
app.use(function (req, res, next) {
const err = new Error('Not Found');
err.status = 404;
next(err);
});
}
//and this is into the class Router
class Router {
constructor(router) {
console.log('/**Routing**/');
router.get('/', this.result());
}
result(req, res) {
console.log("works");
}
}
module.exports = Router;
arr中的值在不同范围内变化,arr_size为100000。
答案 0 :(得分:3)
我得到一个循环超过1000个时钟周期的结果,而下一次是200个。
在前几次迭代之后,像CPU这样的声音就会从空闲状态提高到正常时钟速度。
请记住, RDTSC计数 reference 个周期(固定频率,等于或接近CPU的最大非涡轮频率),非核心时钟周期< / strong>。 (怠速/涡轮/等等)。较旧的CPU具有RDTSC计数核心时钟周期,但是多年来,CPU供应商已经将RDTSC频率固定为使其对clock_gettime()
有用,并对此事实with the invariant_tsc
CPUID feature bit进行了广告宣传。另请参见Get CPU cycle count?
如果您确实要使用RDTSC而不是性能计数器,请禁用Turbo并使用预热循环将CPU置于其最大频率。
有些库可让您对HW性能计数器进行编程,并设置权限,以便可以在用户空间中运行rdpmc
。实际上,其开销比rdtsc
低。有关在用户空间中访问性能计数器的方式的概述,请参见What will be the exact code to get count of last level cache misses on Intel Kaby Lake architecture。
我还找到了一篇有关向Linux rdpmc
(PAPI)添加用户空间perf
支持的论文:ftp://ftp.cs.uoregon.edu/pub/malony/ESPT/Papers/espt-paper-1.pdf。 IDK是否使它成为主流内核/性能代码。
答案 1 :(得分:-1)
实用答案:使用rdtscp而不是rdtsc(以及编译器障碍,我不确定您是否会找到该版本),并在rdtscp实例之间放下栅栏。它不是完美的,但这应该减少错误。 Here is a slightly dated post that should be useful.
比您想了解的还要多:很难对指令的顺序和推测进行推理。 Lfence是一把非常沉重,复杂的锤子。它也会在此之后引起猜测,但它本身可以推测地执行(有趣)。有关更多详细信息,请查看此blogpost。