Measure executing time on ARM Cortex-A8 using hardware counter
Asked Answered
E

2

7

I'm using a Exynos 3110 processor (1 GHz Single-core ARM Cortex-A8, e.g. used in the Nexus S) and try to measure execution times of particular functions. I have an Android 4.0.3 running on the Nexus S. I tried the method from

[1] How to measure program execution time in ARM Cortex-A8 processor?

I loaded the kernel module to allow reading the register values in user mode. I am using the following program to test the counter:

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;
}

According to [1] the counter is incremented with each clock cycle. I switched the scaling_governor to userspace and set the CPU frequency to 1GHz to make sure that the clock frequency is not change by Android.

If I run the program the sleeps of 1 second are executed, but the counter values are in the range of ~200e6, instead of the expected 1e9. Is there anything processor specific I am missing here? Is the clock rate of the counters different to the clock rate of the processor ?

Exhilaration answered 20/3, 2012 at 21:18 Comment(5)
Cool.. The code you've posted is exactly the code I've written two years ago.. Just wondering: Where do you got it from?Bille
Hi Nils, it is your code and I cited the topic from that time ;-) Do you have any idea why I get the factor of 5 in the timer values? ThanksExhilaration
Does the measured time changes if you do real work for a second instead of sleeping?Bille
Hi Nils, thanks! Indeed the sleep seems to influence the counter. For exec times in the range of seconds I get now reasonable results. I measured now longer execution times of programs using three methods: 1) by hand 2) with the counter 3) using the function gettimeofday(). The counter value was off by 36s for a program runtime of 129s. Any guess what could influence the counter? I need to log function calls including time stamps over longer periods (5-10min) as precise as possible and am wondering what would be the best way to do it.Exhilaration
It seems like Android is still scaling the frequency despite the changed governor. If I run the timing measurements and have a very low workload on the phone, the difference between the counter and gettimeofday() is significantly greater than with a higher workload... Looks like I should have a look into the Power Management part of Android :-)Exhilaration
C
1

Check out this professor's page: http://users.ece.utexas.edu/~valvano/arm/ He has multiple full example programs that have to do with time/periodic-timers/measuring-execution-time, they are developed for ARM Cortex-M3 based microcontrollers. I hope this isn't very different from what you are working on. I think you would be interested in Performance.c

Campfire answered 23/4, 2012 at 5:27 Comment(0)
C
0

Are you sure governors are used in Android for performance management the same way that in standard Linux? And are you using custom Android image or one provided by manufacturer? I would assume there are lower level policies in place in manufacturer provided image (tied to sleeps or modem activity, etc). It could be also that sleep code directly scales voltage and frequency. It might be worthwhile to disable the whole CPUFreq not just the policies (or governors).

Civilly answered 9/12, 2013 at 7:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.