2012-07-20 72 views
0

我正在测试库中几个函数的延迟。为了做到这一点,我在进入和退出时使用rdtsc(),我跟踪得到的rdtsc值,运行最小值,最大值和调用次数(以获得平均值)。当我看到输出的图形时,我会看到大约100个左右的周期的平均值,但大约20000个周期的峰值或类似的干扰(似乎比简单的分支误预测,功能中的3或4个分支差得多)。我跑cachegrind,我得到这样的输出:Valgrind输出和rdtsc不一致...为什么会这样呢?

==14038== 
==14038== I refs:  2,260,149,383 
==14038== I1 misses:   10,408 
==14038== LLi misses:   3,978 
==14038== I1 miss rate:   0.00% 
==14038== LLi miss rate:   0.00% 
==14038== 
==14038== D refs:  1,100,962,403 (773,471,444 rd + 327,490,959 wr) 
==14038== D1 misses:   26,419 ( 13,447 rd +  12,972 wr) 
==14038== LLd misses:   15,446 (  5,701 rd +  9,745 wr) 
==14038== D1 miss rate:   0.0% (  0.0%  +   0.0% ) 
==14038== LLd miss rate:   0.0% (  0.0%  +   0.0% ) 
==14038== 
==14038== LL refs:    36,827 ( 23,855 rd +  12,972 wr) 
==14038== LL misses:   19,424 (  9,679 rd +  9,745 wr) 
==14038== LL miss rate:   0.0% (  0.0%  +   0.0% ) 
==14038== 
==14038== Branches:  327,248,773 (297,539,058 cond + 29,709,715 ind) 
==14038== Mispredicts:   980,262 ( 978,639 cond +  1,623 ind) 
==14038== Mispred rate:   0.2% (  0.3%  +   0.0% ) 

在错误预测和分支命中率如此之低,这让我不知道是怎么回事on..how是我可能看到的数量级上的高延迟的测量20K周期如此频繁?我可以研究哪些更多的东西来解决这个谜团?会是什么呢?

事实上,一些令人震惊的是,RDTSC测量一个仅仅包装是这样的:

if(memberVarBool_) 
{ 
    memberVarPtr->smallFuncWithThreeIntAssignsAndstdmax; 
} 

这家伙给我看了很多的“25”个周期的东西这是有道理的,但也有很多oultier病例约2000个周期!

更新:我只是切换到使用gettimeofday来测量延迟纳秒,希望避免特定于rdtsc的问题,仍然看到相同的东西......有没有一种方法,我可以避免抢占和外部或过程的影响,在我的meaurements?

+0

您是否正在实时操作系统上运行?有很多事情会影响你的过程。 – Chad 2012-07-20 20:25:25

+0

你的进程是否被抢占或系统调用? – PlasmaHH 2012-07-20 20:26:12

+0

@Chad,我会尝试运行ulimit -r99 ..但我想排除实际的低效率或代码本身的问题。 – 2012-07-20 20:35:32

回答

1

如何确保操作系统不会在两次调用rdtsc()之间调度另一个任务/进程?如何防止在两次调用rdtsc()之间发生硬件中断?

这两种情况都会导致两次读数之间的差异出现尖峰。

+0

运行ulimit -r 99有助于防止这种情况发生吗?或者我怎么能够认为这个或避免这个? – 2012-07-20 20:38:27

0

如果您保留原始样本,您可以绘制它们并忽略异常值,或采取中位数而不是平均值/平均值。顺便说一句,以及抢占 - rdtsc可能误报时间间隔的另一个原因是您的线程移动核心:每个核心都有自己的TSC寄存器,并且在许多盒子上,它们在任何时间点都不会同步到相同的值。将进程固定到特定的核心可以提供帮助。你可能需要root来禁用硬件中断,我不确定它是如何在用户进程上下文中完成的。

另外,仅仅因为一些名义上返回纳秒并不意味着它这样做在实践中:很多这样的功能跳成千上万的百万纳秒有些慢打勾驱动程序;重复调用该函数将返回相同的值,直到它再次跳转。

+0

有趣的是,这是什么关于同样的价值,直到它再次跳转?在做纳秒时,我观察到了很多重复的值!和非常具体的数量,如1000.我看着maxes,因为我担心他们似乎很频繁(根据“时间数据”,我开始质疑...)... ulimit -r 99保证没有抢占?有什么方法可以在我可以研究的非常低的延迟时间内测量“用户时间”? – 2012-07-20 23:11:16

+0

@PalaceChan:这正是问题所在 - 如果你在一个紧密循环中调用OS定时函数,你会倾向于获得多次完全相同的值,然后它会跳过实际更新周期的倍数(通常乘数是1,但如果有一些线程抢占,硬件中断等,它可能会更多)。如果你真的需要知道分支预测错误,高速缓存线等的成本,最大值是很重要的 - 人们通常认为它们对整个程序的吞吐量无关紧要,但也许你会这样做;-)。 – 2012-07-21 20:52:43

+0

'ulimit -r'本身无法提供帮助...您需要设置您的操作系统以获得实时支持,并且还要求应用程序请求具有更高的优先级。重新使用“用户时间” - 你的意思是通常意义上的“不是系统调用时间”?无论如何,我不知道有什么特别好的解决方案。 – 2012-07-21 21:01:04