在ARM Cortex-A8上使用硬件计数器测量执行时间

7
我正在使用Exynos 3110处理器(1 GHz单核ARM Cortex-A8,例如在Nexus S中使用),并尝试测量特定函数的执行时间。我在Nexus S上运行Android 4.0.3。我尝试了来自[1]的方法(如何在ARM Cortex-A8处理器中测量程序执行时间?)。我加载了内核模块以允许在用户模式下读取寄存器值。我正在使用以下程序测试计数器:
static inline unsigned int get_cyclecount (void)
{
    unsigned int value;
    // Read CCNT Register
    asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));
    return value;
}


static inline void init_perfcounters (int do_reset, int enable_divider)
{
    // in general enable all counters (including cycle counter)
    int value = 1;

    // peform reset:  
    if (do_reset)
    {
        value |= 2;     // reset all counters to zero.
        value |= 4;     // reset cycle counter to zero.
    } 

    if (enable_divider)
        value |= 8;     // enable "by 64" divider for CCNT.

    value |= 16;

    // program the performance-counter control-register:
    asm volatile ("MCR p15, 0, %0, c9, c12, 0\t\n" :: "r"(value));  

    // enable all counters:  
    asm volatile ("MCR p15, 0, %0, c9, c12, 1\t\n" :: "r"(0x8000000f));  

    // clear overflows:
    asm volatile ("MCR p15, 0, %0, c9, c12, 3\t\n" :: "r"(0x8000000f));
}


int main(int argc, char **argv)
{
    int i = 0;
    unsigned int start = 0;
    unsigned int end = 0;

    printf("Hello Counter\n");

    init_perfcounters(1,0);

    for(i=0;i<10;i++)
    {
        start = get_cyclecount();
        sleep(1); // sleep one second
        end = get_cyclecount();

        printf("%u %u %u\n", start, end, end - start);
    }

    return 0;
}

根据[1],计数器在每个时钟周期中递增。我将scaling_governor切换到userspace并将CPU频率设置为1GHz,以确保Android不改变时钟频率。
如果我运行程序,1秒的睡眠时间会被执行,但是计数器值在约2亿左右,而不是预期的10亿。这里是否有任何特定于处理器的问题?计数器的时钟速率是否与处理器的时钟速率不同?

1
很棒.. 你发布的代码和我两年前写的完全一样.. 只是好奇:你从哪里得到它的? - Nils Pipenbrinck
2
嗨尼尔斯,这是你的代码,我引用了当时的主题;-) 你有什么想法为什么计时器值中会出现5的因子吗?谢谢 - user1207228
1
如果你进行实际工作一秒钟而不是睡觉,测量的时间会改变吗? - Nils Pipenbrinck
嗨Nils,谢谢!确实,睡眠似乎影响计数器。对于几秒钟的执行时间,我现在得到了合理的结果。我现在使用三种方法测量程序的较长执行时间:1)手动 2)使用计数器 3)使用gettimeofday()函数。计数器值在一个运行时间为129s的程序中偏差36s。有什么猜测会影响计数器吗?我需要记录包括时间戳在内的函数调用长时间(5-10分钟),尽可能精确,并想知道最好的方法是什么。 - user1207228
2
似乎Android仍在调整频率,尽管已更改了管理器。如果我在手机上运行计时测量,并且负载非常低,则计数器和gettimeofday()之间的差异显着大于较高负载时...看起来我应该查看Android的电源管理部分 :-) - user1207228
2个回答

1

看看这位教授的页面:http://users.ece.utexas.edu/~valvano/arm/ 他有多个完整的示例程序,与时间/周期计时器/测量执行时间有关,它们是为基于ARM Cortex-M3的微控制器开发的。我希望这不会与您正在处理的内容非常不同。 我认为您会对Performance.c感兴趣。


0

您确定在Android中使用governors来进行性能管理的方式与标准Linux中的方式相同吗?您是使用自定义的Android镜像还是由制造商提供的镜像?我会假设制造商提供的镜像中有更低级别的策略(与睡眠或调制解调器活动相关)。也可能是睡眠代码直接缩放电压和频率。禁用整个CPUFreq而不仅仅是策略(或governors)可能是值得的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接