ARM性能计数器与linux时钟设置时间



我在开发板(ZC702)上使用Zynq芯片,它有一个667MHz的双cortex-A9 MPCore,并配有Linux内核3.3我想比较一个程序的执行时间,所以首先使用clock_gettime,然后使用协同处理器提供的计数器ARM。计数器每一个处理器周期递增一次。(基于stackoverflow和这个问题)

我用-O0标志编译程序(因为我不想做任何重新排序或优化)

我用性能计数器测量的时间是583833498(周期)/666.66687 MHz=875750.221(微秒)

使用clock_gettime()时(REALTIME、MONOTONIC或MONOTONIC_RAW)测量的时间为:731627.126(微秒)小于150000微秒。。

有人能解释一下为什么会发生这种事吗?为什么会有区别?处理器没有时钟刻度,怎么可能以clock_gettime度量的执行时间更少?我有一个示例代码如下:


#define RUNS 50000000
#define BENCHMARK(val) 
__asm__  __volatile__("mov r4, %1nt" 
"mov r5, #0nt" 
"1:nt"
"add r5,r5,r4nt"
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"mov r4 ,r4  nt" 
"sub r4,r4,#1nt" 
"cmp r4, #0nt" 
"bne 1bnt" 
"mov %0 ,r5  nt" 
:"=r" (val) 
: "r" (RUNS) 
: "r4","r5" 
);
clock_gettime(CLOCK_MONOTONIC_RAW,&start);
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0tn": "=r"(start_cycles));
for(index=0;index<5;index++)
{
BENCHMARK(i);
}
__asm__ __volatile__ ("MRC p15, 0, %0, c9, c13, 0tn": "=r"(end_cycles));
clock_gettime(CLOCK_MONOTONIC_RAW,&stop);

我找到了解决方案。我将平台从linux内核3.3.0升级到3.5,其值与性能计数器的值相似。显然,3.3.0中时钟计数器的频率被假设为高于其实际频率(大约400MHz),而不是CPU频率的一半。可能是旧版本中的移植错误。

POSIX时钟在一定的精度内运行,这可以通过clock_getres获得。检查150000us的差异是否在误差范围之内或之外。

在任何情况下,这都不重要,你应该多次重复你的基准测试,不是5次,而是1000次或更多。然后,您可以获得像这样的单个基准测试运行的时间

((end + e1) - (start + e0)) / 1000

(end - start) / 1000 + (e1 - e0) / 1000

如果e1e0是误差项,它们由一个小常数约束,则最大测量误差将是abs (e1 - e0) / 1000,随着循环数量的增加,该误差将可以忽略不计。

最新更新