【问题标题】:Time calculation with TSC (Time Stamp Counter)使用 TSC(时间戳计数器)计算时间
【发布时间】:2012-12-24 06:31:34
【问题描述】:

我正在尝试通过 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个处理器的加法?

【问题讨论】:

  • 时钟滴答与运行的核心有关rdtscl

标签: c linux performance linux-kernel multiprocessing


【解决方案1】:

如果您没有得到时钟滴答,则说明您的代码存在严重问题。你是自己写的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 );  
}

另外,作为一个返回值的函数:

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 指针,这让我怀疑你实际上并没有将时间戳计数器传递回调用者,而只是保留它碰巧具有的任何值 - 这可能两个值应该是一样的。

【讨论】:

  • 这里的 lo 和 hi 是什么?
  • 固定,它们是 32 位整数。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    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 成为不稳定的时间源。

    【讨论】:

      【解决方案4】:

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

      在 Ubuntu 中,您可以执行 sudo apt-get install cpuid

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

      【讨论】:

        猜你喜欢
        • 2015-11-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-16
        • 1970-01-01
        • 2012-12-18
        • 2015-01-26
        相关资源
        最近更新 更多