linux – 为什么clock_gettime(CLOCK_REALTIME,..)的调用延迟变
我正在尝试time_gettime(CLOCK_REALTIME,…)调用多长时间. “回到当天”我曾经在循环的顶部称它为一次,因为它是一个相当昂贵的电话.但是现在,我希望通过vDSO和一些时钟改进,它可能不会那么慢. 我编写了一些测试代码,使用__rdtscp来重复调用clock_gettime(rdtscp调用绕过一个调用clock_gettime的循环并将结果添加到一起,这样编译器就不会进行太多的优化). 如果我快速连续调用clock_gettime(),则时间长度从大约45k时钟周期下降到500个周期.其中一些我认为可能是第一次调用必须加载vDSO代码(仍然没有完全对我有意义),但如何需要一些调用来获得500我根本无法解释,这种行为似乎无论我如何测试它都是恒定的:
但是,如果我在调用clock_gettime之间休眠(一秒或十分,无关紧要),它只会达到约4.7k周期的稳定状态: 这里睡10秒钟:
这里睡1秒钟:
缓存行为似乎无法描述这一点(在桌面系统上没有做太多任何事情).我应该为clock_gettime的调用预算多少钱?为什么呼叫变得越来越快?为什么睡一小段时间这么重要? tl; dr我试图理解调用clock_gettime所花费的时间(CLOCK_REALTIME,…)不明白为什么它在快速连续调用时运行得更快而不是在调用之间的第二次调用. 更新:这是proc 0上的cpuinfo
这是重新创建的测试代码:
最佳答案
第一次调用clock_gettime时,页面上会发生页面错误,其中包含该函数的指令.在我的系统上,这是一个软页面错误,需要几千个周期来处理(最多10,000个周期).我的CPU运行在3.4GHz.我认为您的CPU运行频率要低得多,因此在系统上处理页面错误会花费更多时间.但这里的重点是,对clock_gettime的第一次调用将比后来的调用花费更多的时间,这正是你所观察到的.
代码显示的第二个主要影响是由于指令缓存未命中而导致的重大停顿.您可能看起来只调用两个函数,即now和printf,但这些函数调用其他函数,它们都在L1指令缓存上竞争.总的来说,它取决于所有这些功能在物理地址空间中的对齐方式.当休眠时间为零秒时,由于指令高速缓存未命中而导致的停止时间实际上相对较小(您可以使用ICACHE.IFETCH_STALL性能计数器来测量它).但是,当睡眠时间大于零秒时,此停顿时间变得非常大,因为OS将调度一些其他线程在同一核心上运行,并且该线程会有不同的指令和数据.这解释了为什么当你睡觉时,clock_gettime需要更多的时间来执行. 现在关于第二次和以后的测量.从问题:
我在我的系统上观察到第二次测量不一定比后来的测量更大.我相信你的系统也是如此.事实上,当您睡眠10秒或1秒时,情况似乎就是这样.在外部循环中,两个函数现在和printf包含数千个动态指令,它们也访问L1数据高速缓存.您在第二次和后续测量之间看到的可变性是可重现的.所以它是功能本身所固有的.请注意,rdtscp指令本身的执行时间可能会有4个周期.另见this. 实际上,当期望的精度最多为一百万个周期时,clock_gettime很有用.否则,它可能会产生误导. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |