测量时间以执行简单的指令

Measuring time to perform simple instruction

本文关键字:指令 简单 执行 时间 测量      更新时间:2023-10-16

我正在尝试测量CPU执行特定指令所需的周期数(应该需要一个CPU周期),并且输出必须以周期长度为单位(CPU完成一个周期所需的时间)。首先,我的CPU是2.1GHz,这意味着我电脑上的一个周期长度单位是1/2100,对吧?此外,我使用getTimeOfDay以微秒为单位测量时间,并计算1000000次迭代的平均值。所以,如果我没有错的话,我想要的输出必须是结果*2100(为了得到循环长度)。我说得对吗?谢谢

p.S不知道这是否重要,但我正在用cpp-

我相信你在一些事情上被误导了。

在现代术语中,时钟速度是速度的指示,而不是速度的实际度量,因此没有合理的方法来估计单个指令可能需要多长时间。

你的问题是基于所有指令都相等的假设——它们肯定不是,在某些架构上,一些CPU指令被解释为微指令序列,而在另一些架构上,时间可能会改变。

此外,您不能安全地假设在现代体系结构上,重复指令将以相同的方式执行,这取决于数据和指令缓存、管道和分支预测。

getTimeOfDay的分辨率不足以估计测量单个指令所需的时间长度,甚至CPU时钟周期计数器(x86上的TSC)也不够。

此外,您的操作系统是估计此类时间的主要错误源,上下文切换、电源管理、机器负载和中断都会产生巨大影响。但即使在真正的硬实时操作系统(QNX或VxWorks)上,这种测量仍然很困难,需要时间和工具,以及解释结果的专业知识。在通用操作系统(windows或基本Linux)上,你几乎没有希望获得准确的测量结果)

读取和存储CPU周期计数的计算开销和错误也往往会使一条指令所需的时间相形见绌。至少,我建议您考虑将几十万条指令组合在一起。

在没有缓存的确定性体系结构(1个周期=1条指令)上,如PIC芯片,您可以使用时钟乘法器完全按照您的建议进行操作,但即使这样,为了验证您的测量结果,您也可能需要一个逻辑分析器(即,您需要在硬件中进行此操作)。

简而言之,这是一个极其困难的问题。

CPU包含一个循环计数器,您可以通过一点内联汇编读取:

static inline uint64_t get_cycles()
{
    uint64_t n;
    __asm__ __volatile__ ("rdtsc" : "=A"(n));
    return n;
}

如果你测量了操作的1、2和300万次迭代的循环计数,你应该能够插值一次的成本,但一定要测量"空"循环,以消除循环的成本:

{
    unsigned int n, m = get_cycles();
    for (unsigned int n = 0; n != 1000000; ++n)
    {
        // (compiler barrier)
    }
    n = get_cycles();
    // cost of loop: n - m
}
{
    unsigned int n, m = get_cycles();
    for (unsigned int n = 0; n != 1000000; ++n)
    {
        my_operation();
    }
    n = get_cycles();
    // cost of 1000000 operations: n - m - cost of loop
}
// repeat for 2000000, 3000000.

我正在尝试测量我的计算机执行一个简单指令所需的时间

如果是这样的话,关键甚至不是你能找到的最准确的时间函数。我敢打赌,没有人有必要的决心来提供一个有意义的结果。

关键是要增加样本数量

因此,与其做这样的事情:

start = tik();
instruction();
end = tok();
time = end - start;

进行

start = tik();
for ( 1..10000 )
   instruction();
end = tok();
time = (end - start) / 10000;

这将提供更准确的结果,并且由测量机构引起的误差将是可忽略的。