4

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

我用 -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);
4

2 回答 2

4

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

于 2012-11-26T10:31:23.350 回答
0

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

无论如何,没关系,您应该多次重复基准测试,而不是 5 次,而是 1000 次或更多。然后,您可以获得单个基准测试运行的时间,例如

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

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

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

于 2012-11-20T13:52:38.697 回答