我正在尝试测量CPU执行特定指令所需的周期数(一个应占用一个CPU周期),输出必须是周期长度(CPU完成一个周期所需的时间)周期)。 首先,我的CPU是2.1GHz,这意味着我的计算机上的一个周期长度单位是1/2100,对吧? 另外 - 我使用getTimeOfDay来测量以微秒为单位的时间,并计算1,000,000次迭代的平均值。 因此,如果我没有弄错,我想要的输出必须是结果* 2100(为了得到循环长度)。我对吗? 谢谢!
P.S不知道这是否重要,但我正在用cpp写作
答案 0 :(得分:3)
我相信你对一些事情有些误导。
在现代术语中,时钟速度是速度的指示,而不是速度的实际测量 - 因此没有合理的方法来估计单个指令可能需要多长时间。
你的问题是基于所有指令都相同的假设 - 它们肯定不是,某些CPU指令被解释为某些架构上的微指令序列,而其他指令可能会改变。
此外,您不能安全地假设在现代架构中重复指令将以相同的方式执行,这取决于数据和指令缓存,管道和分支预测。
getTimeOfDay的分辨率不足以估计测量单个指令所需的时间长度,甚至CPU时钟周期计数器(x86上的TSC)也不够。
此外,您的操作系统是估计此类时序的错误的主要来源,上下文切换,电源管理,机器负载和中断都会产生巨大影响。但即使在真正的硬实时操作系统(QNX或VxWorks)上,这样的测量仍然很困难,并且需要时间和工具以及解释结果的专业知识。在通用操作系统(Windows或基本Linux)上,您几乎没有希望获得准确的测量结果。
读取和存储CPU周期计数的计算开销和错误也会使一条指令所需的时间相形见绌。至少,我建议你考虑将数百或数千条指令组合在一起。
在没有高速缓存的确定性架构(1个周期= 1个指令)上,如PIC芯片,您可以使用时钟倍频器完全按照您的建议进行操作,但即使这样,您也可能需要使用逻辑分析仪验证测量结果(即你需要在硬件中这样做。)
简而言之,这是一个非常难的问题。
答案 1 :(得分:1)
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.
答案 2 :(得分:1)
我正在尝试衡量计算机执行简单指令所需的时间
如果是这种情况,那么钥匙甚至不是您能找到的最准确的时间功能。我敢打赌,没有必要提供必要的决议来提供有意义的结果。
关键是增加样品数量。
所以不要做类似的事情:
start = tik();
instruction();
end = tok();
time = end - start;
DO
start = tik();
for ( 1..10000 )
instruction();
end = tok();
time = (end - start) / 10000;
这将提供更准确的结果,并且由测量机制引起的误差将是可忽略的。