Greetings,

I'm experiencing what appears to be a minimum clock resolution issue in using clock_gettime() on a PandaBoard ES running ubuntu.

   *> uname -r*
   3.1.1-8-linaro-lt-omap

   *> cat /proc/version*
   Linux version 3.1.1-8-linaro-lt-omap (buildd@diphda) (gcc version
   4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) )
   #8~lt~ci~20120118001257+025756-Ubuntu SMP PREEMPT Thu Jan 19 09:

I'm using clock_gettime() (and have tried gettimeofday()) to compute the elapsed time around roughly 15ms of computation (image processing). While the computed time is stable on my x86_64 machine, it is not on my PandaBoard ES. I have tried various clocks (e.g. CLOCK_REALTIME), but the issue remains. No error codes are returned by clock_gettime().

The result on my x86_64 machine looks like this:

   *elapsed (s)   elapsed (ns)   elapsed (us)     time
   (after)                     time (before)*
0s 532260ns *532us* (t1: 73741s 92573265ns) (t0: 73741s 92041005ns) 0s 544413ns *544us* (t1: 73741s 109390136ns) (t0: 73741s 108845723ns) 0s 529328ns *529us* (t1: 73741s 126024860ns) (t0: 73741s 125495532ns)

   A: 1.7s in total. *0.536ms* on average.


If I move over to my PandaBoard ES, I calculate elapsed times of 0us on some iterations.

   *elapsed (s)   elapsed (ns)   elapsed (us)     time
   (after)                     time (before)*
0s 0ns *0us* (t1: 269529s 192626951ns) (t0: 269529s 192626951ns) 0s 0ns *0us* (t1: 269529s 215606688ns) (t0: 269529s 215606688ns)
   0s      2655030ns *2655us*     (t1: 269529s    252349852ns)     (t0:
   269529s    249694822ns)
   0s      2593994ns *2593us*     (t1: 269529s    286163328ns)     (t0:
   269529s    283569334ns)
   0s        30518ns *30us*     (t1: 269529s    317657469ns)     (t0:
   269529s    317626951ns)


If I crank up the amount of work done between the time calls (timetest.c:18: inneriters = 1e7;) such that the timed loop takes around 72ms, the timing results seem accurate and none of the intermediate calculations result in a 0us elapsed time. If I reduce it to around 10-25ms (inneriters=1e6), I get occasional 0us elapsed times. Around 2ms (inneriters=1e5), most results measure an elapsed time of 0us.

I'm trying to optimize image processing functions, which take on the order of 2-15ms to process. Am I stuck with this timing resolution? I want to be careful to not omit issues like cache performance when timing, as I might if I repeatedly process an image to average the results. Currently, that seems like the best option.

Source code and makefile attached, as well as /proc/timer_list

Is this a property of the hardware, or might it be a bug?

Thanks,
Andrew
GCC = gcc -g -std=gnu99

all: timetest

timetest: timestamp.o timetest.o
        gcc -o $@ timestamp.o timetest.o -lrt

%.o: %.s
        $(GCC) -O0 -c $<

%.s: %.c
        $(GCC) -O0 -S $<

clean:
        rm -f *~ timetest *.o *.s

.PHONY: clean
#include "timestamp.h"

timespec_t timestamp_now()
{
    timespec_t ts; // tv_sec and tv_nsec fields

    // clock_gettime() version
    {
        clockid_t id = CLOCK_MONOTONIC_RAW;
        int res = clock_gettime(id, &ts);
        if (res != 0)
            printf("clock_gettime() returned an error code! %d\n", res);
    }

    // gettimeofday() version
    //{
    //    struct timeval tv;
    //    gettimeofday (&tv, NULL);

    //    // convert
    //    ts.tv_sec  = tv.tv_sec;
    //    ts.tv_nsec = tv.tv_usec * 1E3;
    //}

    return ts;
}

int32_t get_dt(timespec_t t1, timespec_t t0)
{
    // seconds
    __time_t ds  = t1.tv_sec  - t0.tv_sec;
    // nanoseconds
    long int dns = t1.tv_nsec - t0.tv_nsec;

    // microseconds
    int32_t dt = (ds * 1E6) + (dns * 1E-3);

    printf("%6ds %12dns %12dus     (t1: %6ds %12dns)     (t0: %6ds %12dns)\n",
           ds, dns, dt,
           t1.tv_sec, t1.tv_nsec,
           t0.tv_sec, t0.tv_nsec);

    return dt;
}
#ifndef TIMESTAMP_H
#define TIMESTAMP_H

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <assert.h>

#include <time.h>
#include <sys/time.h>

typedef struct timespec timespec_t;

timespec_t timestamp_now();
int32_t get_dt(timespec_t t1, timespec_t t0);

#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "timestamp.h"

int work(int iter)
{
    int a = 0;
    for (int foo=0; foo < iter; foo++)
        a += foo;
    return a;
}

int main(int argc, char *argv[])
{
    int outeriters = 100;
    int inneriters = 10000000;

    for (int iter=0; ; iter++) {

        ////////////////////////////////////////////////////////////////////////////////
        {
            int32_t total = 0;
            timespec_t outer_t0 = timestamp_now();
            for (int i=0; i < outeriters; i++) {

                timespec_t t0 = timestamp_now();
                int a = work(inneriters);
                timespec_t t1 = timestamp_now();

                int32_t dt = get_dt(t1, t0);
                total += dt;

                usleep(16000);
            }
            timespec_t outer_t1 = timestamp_now();

            int32_t outer_dt = get_dt(outer_t1, outer_t0);
            printf("A: %3.1fs in total. %8.3fms on average.\n",
                   outer_dt * 1.0E-6,
                   total / outeriters * 1.0E-3);
        }
    }
}
Timer List Version: v0.6
HRTIMER_MAX_CLOCK_BASES: 3
now at 272073099517824 nsecs

cpu: 0
 clock 0:
  .base:       00000000
  .index:      0
  .resolution: 1 nsecs
  .get_time:   ktime_get
  .offset:     0 nsecs
active timers:
 #0: <00000000>, tick_sched_timer, S:01, hrtimer_start_range_ns, swapper/0
 # expires at 272073101562500-272073101562500 nsecs [in 2044676 to 2044676 
nsecs]
 #1: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, compiz/2136
 # expires at 272073130037843-272073130097843 nsecs [in 30520019 to 30580019 
nsecs]
 #2: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
update-manager/2287
 # expires at 272074090667727-272074095667727 nsecs [in 991149903 to 996149903 
nsecs]
 #3: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
gnome-settings-/2070
 # expires at 272074097564700-272074098564669 nsecs [in 998046876 to 999046845 
nsecs]
 #4: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, nautilus/2159
 # expires at 272074098114016-272074099114016 nsecs [in 998596192 to 999596192 
nsecs]
 #5: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
accounts-daemon/1845
 # expires at 272076000455568-272076004451415 nsecs [in 2900937744 to 
2904933591 nsecs]
 #6: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
console-kit-dae/1706
 # expires at 272076000744143-272076029807112 nsecs [in 2901226319 to 
2930289288 nsecs]
 #7: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, rtkit-daemon/2193
 # expires at 272074290497480-272076790497480 nsecs [in 1190979656 to 
3690979656 nsecs]
 #8: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, rtkit-daemon/2194
 # expires at 272079290497480-272079290497480 nsecs [in 6190979656 to 
6190979656 nsecs]
 #9: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, ssh-agent/2051
 # expires at 272082669372562-272082679372562 nsecs [in 9569854738 to 
9579854738 nsecs]
 #10: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, rsyslogd/1445
 # expires at 272084191802980-272084221802980 nsecs [in 11092285156 to 
11122285156 nsecs]
 #11: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
gnome-screensav/2192
 # expires at 272093772472644-272093797927644 nsecs [in 20672954820 to 
20698409820 nsecs]
 #12: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, gconfd-2/2077
 # expires at 272099772078175-272099802072175 nsecs [in 26672560351 to 
26702554351 nsecs]
 #13: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
avahi-daemon/1492
 # expires at 272215547723390-272215647723390 nsecs [in 142448205566 to 
142548205566 nsecs]
 #14: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
udisks-daemon/2158
 # expires at 273746000990480-273746100990480 nsecs [in 1672901472656 to 
1673001472656 nsecs]
 #15: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, dhclient/1877
 # expires at 288948219330705-288948319330705 nsecs [in 16875119812881 to 
16875219812881 nsecs]
 clock 1:
  .base:       00000000
  .index:      1
  .resolution: 1 nsecs
  .get_time:   ktime_get_real
  .offset:     1328382209780821967 nsecs
active timers:
 clock 2:
  .base:       00000000
  .index:      2
  .resolution: 1 nsecs
  .get_time:   ktime_get_boottime
  .offset:     0 nsecs
active timers:
  .expires_next   : 272073101562500 nsecs
  .hres_active    : 1
  .nr_events      : 8492165
  .nr_retries     : 44620
  .nr_hangs       : 0
  .max_hang_time  : 0 nsecs
  .nohz_mode      : 2
  .idle_tick      : 272073078125000 nsecs
  .tick_stopped   : 0
  .idle_jiffies   : 34786953
  .idle_calls     : 13914835
  .idle_sleeps    : 10381583
  .idle_entrytime : 272073098114016 nsecs
  .idle_waketime  : 272073079345705 nsecs
  .idle_exittime  : 272073079742434 nsecs
  .idle_sleeptime : 266228859853210 nsecs
  .iowait_sleeptime: 1715169393760 nsecs
  .last_jiffies   : 34786956
  .next_jiffies   : 34786957
  .idle_expires   : 272073085937500 nsecs
jiffies: 34786956

cpu: 1
 clock 0:
  .base:       00000000
  .index:      0
  .resolution: 1 nsecs
  .get_time:   ktime_get
  .offset:     0 nsecs
active timers:
 #0: <00000000>, tick_sched_timer, S:01, hrtimer_start_range_ns, swapper/0
 # expires at 272073101562500-272073101562500 nsecs [in 2044676 to 2044676 
nsecs]
 #1: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
update-notifier/2248
 # expires at 272075990722723-272075995722723 nsecs [in 2891204899 to 
2896204899 nsecs]
 #2: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, cron/1543
 # expires at 272131329132084-272131329182084 nsecs [in 58229614260 to 
58229664260 nsecs]
 #3: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, 
zeitgeist-daemo/2215
 # expires at 272303304595553-272303404595553 nsecs [in 230205077729 to 
230305077729 nsecs]
 #4: <00000000>, hrtimer_wakeup, S:01, hrtimer_start_range_ns, cupsd/1487
 # expires at 273251841003420-273251941003420 nsecs [in 1178741485596 to 
1178841485596 nsecs]
 clock 1:
  .base:       00000000
  .index:      1
  .resolution: 1 nsecs
  .get_time:   ktime_get_real
  .offset:     1328382209780821967 nsecs
active timers:
 clock 2:
  .base:       00000000
  .index:      2
  .resolution: 1 nsecs
  .get_time:   ktime_get_boottime
  .offset:     0 nsecs
active timers:
  .expires_next   : 272073101562500 nsecs
  .hres_active    : 1
  .nr_events      : 3436951
  .nr_retries     : 201656
  .nr_hangs       : 0
  .max_hang_time  : 0 nsecs
  .nohz_mode      : 2
  .idle_tick      : 272073070312500 nsecs
  .tick_stopped   : 0
  .idle_jiffies   : 34786952
  .idle_calls     : 6405751
  .idle_sleeps    : 5671548
  .idle_entrytime : 272073086669924 nsecs
  .idle_waketime  : 272073079986574 nsecs
  .idle_exittime  : 272073079986574 nsecs
  .idle_sleeptime : 234101001227924 nsecs
  .iowait_sleeptime: 3747206917044 nsecs
  .last_jiffies   : 34786954
  .next_jiffies   : 34786955
  .idle_expires   : 272074562500000 nsecs
jiffies: 34786956


Tick Device: mode:     1
Broadcast device
Clock Event Device: gp timer
 max_delta_ns:   131072454787401
 min_delta_ns:   91553
 mult:           140737
 shift:          32
 mode:           3
 next_event:     9223372036854775807 nsecs
 set_next_event: omap2_gp_timer_set_next_event
 set_mode:       omap2_gp_timer_set_mode
 event_handler:  tick_handle_oneshot_broadcast
 retries:        166907
tick_broadcast_mask: 00000000
tick_broadcast_oneshot_mask: 00000000


Tick Device: mode:     1
Per CPU device: 0
Clock Event Device: local_timer
 max_delta_ns:   12579325019
 min_delta_ns:   1000
 mult:           358016
 shift:          20
 mode:           3
 next_event:     272073101562500 nsecs
 set_next_event: twd_set_next_event
 set_mode:       twd_set_mode
 event_handler:  hrtimer_interrupt
 retries:        6896962

Tick Device: mode:     1
Per CPU device: 1
Clock Event Device: local_timer
 max_delta_ns:   12579325019
 min_delta_ns:   1000
 mult:           358016
 shift:          20
 mode:           3
 next_event:     272073101562500 nsecs
 set_next_event: twd_set_next_event
 set_mode:       twd_set_mode
 event_handler:  hrtimer_interrupt
 retries:        3890

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to