2012-11-20 47 views
3

我在开发板上使用Zynq芯片(ZC702), ,它具有667MHz的双cortex-A9 MPCore并带有一个Linux内核3.3 我想比较执行时间一个程序首先使用了clock_gettime,然后使用了ARM的协处理器 提供的计数器。计数器每增加一个处理器周期。 (在此基础上question of stackoverflowthisARM性能计数器vs linux clock_gettime

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

我与性能计数器测量的时间是 583833498(周期)/ 666.666687兆赫= 875750.221(微秒)

在使用clock_gettime()(或者实时或单调或MONOTONIC_RAW) 测量的时间是: 731627.126(微秒) 这是微秒少..

任何人能解释我为什么会这样? 为什么会有差异?处理器不会进行时钟缩放,如何通过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); 

回答

3

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

+0

@auselen这不是我的错,因为时钟问题,我只是使用板附带的BSP。我认为它会工作。 – akarapatis

0

POSIX的时钟一定的精度,您可以与clock_getres得到内运行。检查150,000us的差异是否在误差范围之内或之外。

在任何情况下,应该没有关系,你应该多次重复你的基准,而不是5,但1000或更多。然后,您可以得到一个单一的基准测试中的时序像

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

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

如果e1e0是误差项,它们被一个很小的常数限制,那么最大测量误差将是abs (e1 - e0)/1000,随着回路数量的增加,这个误差可以忽略不计。

+0

由于基准测试已经是一个循环,我不需要再运行该程序多次。我更新了上面粘贴的代码。 正如@auselen提到的getres是1nsec – akarapatis