我在开发板(ZC702)上使用Zynq芯片, 它具有667MHz的双皮质-A9 MPCore,并配有Linux内核3.3 我想比较一个程序的执行时间,所以首先使用 clock_gettime然后使用协处理器提供的计数器 ARM计数器每个处理器周期递增一次。 (基于此question of stackoverflow和this)
我使用-O0标志编译程序(因为我不希望任何重新排序或优化)
我用性能计数器测量的时间是 583833498(周期)/ 666.666687 MHz = 875750.221 (微秒)
使用clock_gettime()(REALTIME或MONOTONIC或MONOTONIC_RAW) 测量的时间是: 731627.126 (微秒) 这是 150000 微秒..
有人能解释我为什么会这样吗? 为什么会有区别?处理器没有时钟缩放,怎么可能 通过clock_gettime测量的执行时间更少?我在下面有一个示例代码:
#define RUNS 50000000
#define BENCHMARK(val) \
__asm__ __volatile__("mov r4, %1\n\t" \
"mov r5, #0\n\t" \
"1:\n\t"\
"add r5,r5,r4\n\t"\
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"mov r4 ,r4 \n\t" \
"sub r4,r4,#1\n\t" \
"cmp r4, #0\n\t" \
"bne 1b\n\t" \
"mov %0 ,r5 \n\t" \
:"=r" (val) \
: "r" (RUNS) \
: "r4","r5" \
);
clock_gettime(CLOCK_MONOTONIC_RAW,&start);
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(start_cycles));
for(index=0;index<5;index++)
{
BENCHMARK(i);
}
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(end_cycles));
clock_gettime(CLOCK_MONOTONIC_RAW,&stop);
答案 0 :(得分:3)
我找到了解决方案。我将平台从Linux内核3.3.0升级到3.5,其值与性能计数器类似。显然,假设3.3.0中的时钟计数器的频率高于(大约400 MHz)而不是CPU频率的一半。可能是旧版本中的移植错误。
答案 1 :(得分:0)
POSIX时钟以一定的精度运行,您可以使用clock_getres
获得。检查150,000us差异是否在误差范围之内或之外。
无论如何,它应该无关紧要,你应该多次重复你的基准,而不是5,而是1000或更多。然后,您可以获得单个基准测试运行的时间,如
((end + e1) - (start + e0)) / 1000
或
(end - start) / 1000 + (e1 - e0) / 1000
。
如果e1
和e0
是误差项,它们受一个小常数的约束,那么您的最大测量误差将是abs (e1 - e0) / 1000
,随着循环次数的增加,这个误差可以忽略不计