使用TSC(时间戳计数器)计算时间

时间:2012-12-24 06:31:34

标签: c linux performance linux-kernel multiprocessing

我试图通过Linux内核模块以非常高的精度测量Linux内核中某些代码所花费的时间。

为此,我尝试了 rdtscl(),它给出了代码中使用的时钟滴答数,如下所示:

unsigned long ini, end;
rdtscl(ini);
//some code...
rdtscl(end);
printk("time taken=%lu ticks",end-ini);

正如我所说http://en.wikipedia.org/wiki/Time_Stamp_Counter所说的那样, TSC是自Pentium 以来所有x86处理器上都存在的64位寄存器。那么,如果我有双核处理器,这个计数器是否会存在于两个核心中,或者只有一个,因为它只有一个处理器而是双核心?

第二个问题是:我有Intel Xeon i3处理器,它有4个处理器,每个处理器有2个核心。然后,测量时钟滴答,将给出单个处理器的滴答或添加所有4个处理器?

4 个答案:

答案 0 :(得分:3)

如果没有时钟滴答,那么你的代码就会出现严重问题。您是否自己编写rdtscl [或从某个不是很好的来源的地方复制它?]

顺便说一句,现代英特尔(和AMD)处理器可能会有“恒定的TSC”,因此停止,睡眠,运行速度较慢的处理器仍将以与其他处理器相同的速率剔除 - 它可能不要同步,但这是另一回事。

尝试只运行一个从计数器打印值的循环 - 只需RDTSC指令本身需要大约30-50个时钟周期,所以你应该看到它在移动。

编辑:这是我的rdtsc功能:

void rdtscl(unsigned long long *ll)
{
    unsigned int lo, hi;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));                        
    *ll = ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );  
}

alernatitvely,作为返回值的函数:

unsigned long long rdtscl(void)
{
    unsigned int lo, hi;
    __asm__ __volatile__ ("rdtsc" : "=a"(lo), "=d"(hi));                        
    return ( (unsigned long long)lo)|( ((unsigned long long)hi)<<32 );  
}

我注意到你的代码没有传递你的unsigned long的指针,这让我怀疑你实际上并没有将时间戳计数器BACK传递给调用者,而只是保留它碰巧具有的任何值 - 这可能是这两个值都是一样的。

答案 1 :(得分:2)

所有核心都有自己的TSC;它基本上计算周期 - 但要注意 - TSC时钟可能不同步!如果您的代码开始在一个核心上运行并迁移到第二个核心,这在一般情况下肯定是可能的,那么您的计数将是错误的!

答案 2 :(得分:2)

同一篇WikiPedia文章对TSC的问题进行了如下所述,

With the advent of multi-core/hyper-threaded CPUs, systems with multiple CPUs, and 
hibernating operating systems, the TSC cannot be relied on to provide accurate results 
— unless great care is taken to correct the possible flaws: rate of tick and whether 
all cores (processors) have identical values in their time-keeping registers. **There 
is no promise that the timestamp counters of multiple CPUs on a single motherboard will 
be synchronized**. In such cases, programmers can only get reliable results by locking 
their code to a single CPU. Even then, the CPU speed may change due to power-saving 
measures taken by the OS or BIOS, or the system may be hibernated and later resumed 
(resetting the time stamp counter). In those latter cases, to stay relevant, the 
counter must be recalibrated periodically (according to the time resolution your 
application requires).

意味着现代CPU可以改变其CPU时钟速率以节省可能影响TSC值的功率。此外,在内核可能执行HALT并停止处理器直到收到外部中断的情况下,TSC永远不会增加。

the second question is that i have intel xeon i3 processor which has 4 processors & 
each having 2 cores then measuring the clock ticks will give the ticks of single 
processor or addition of all 4 processors..?

这可能导致这样的情况:进程可以在一个处理器上读取时间,移动到第二个处理器并且比在第一个处理器上读取的时间更早地遇到时间,这导致TSC成为不稳定的时间源。

答案 3 :(得分:1)

这里提到的一些事情是准确的,就像TSC由于CPU中的S状态而不是时间的度量。但我认为即使在多核环境中,TSC也可用于相对测序。有一个名为TSCInvariant的标志,在Intel CPU&gt; = nehalem arch中设置为true。在这些CPU中,TSC在所有内核上以恒定速率变化。因此,如果将上下文切换到不同的核心,您将永远不会返回TSC计数。

在Ubuntu中你可以做sudo apt-get install cpuid

cpuid | grep TscInvariant在桌面上验证它。

相关问题