Подходит ли clock_gettime () для субмикросекундной синхронизации?

Мне нужен таймер с высоким разрешением для встроенного профилировщика в сборку Linux нашего приложения. Наш профилировщик измеряет такие маленькие области, как отдельные функции, поэтому ему требуется точность таймера лучше 25 наносекунд.

Ранее наша реализация использовала встроенную сборку и операцию rdtsc для запроса высокочастотного таймера напрямую от ЦП, но это проблематично и требует частой повторной калибровки.

Поэтому я попытался использовать функцию clock_gettime вместо запроса CLOCK_PROCESS_CPUTIME_ID. Документы утверждают, что это дает мне время наносекунд, но я обнаружил, что накладные расходы на один вызов clock_gettime () превышают 250 нс. Это делает невозможным синхронизацию событий длительностью 100 нс, а такие высокие накладные расходы на функцию таймера серьезно снижают производительность приложения, искажая профили сверх значения. (У нас есть сотни тысяч узлов профилирования в секунду.)

Есть ли способ вызвать clock_gettime () с накладными расходами менее µs? Или есть другой способ, которым я могу надежно получить счетчик отметок времени с накладными расходами rdtsc ?

Ниже приведен код, который я использовал для измерения времени clock_gettime () .

// calls gettimeofday() to return wall-clock time in seconds:
extern double Get_FloatTime();
enum { TESTRUNS = 1024*1024*4 };

// time the high-frequency timer against the wall clock
{
    double fa = Get_FloatTime();
    timespec spec; 
    clock_getres( CLOCK_PROCESS_CPUTIME_ID, &spec );
    printf("CLOCK_PROCESS_CPUTIME_ID resolution: %ld sec %ld nano\n", 
            spec.tv_sec, spec.tv_nsec );
    for ( int i = 0 ; i < TESTRUNS ; ++ i )
    {
        clock_gettime( CLOCK_PROCESS_CPUTIME_ID, &spec );
    }
    double fb = Get_FloatTime();
    printf( "clock_gettime %d iterations : %.6f msec %.3f microsec / call\n",
        TESTRUNS, ( fb - fa ) * 1000.0, (( fb - fa ) * 1000000.0) / TESTRUNS );
}
// and so on for CLOCK_MONOTONIC, CLOCK_REALTIME, CLOCK_THREAD_CPUTIME_ID.

Результаты:

CLOCK_PROCESS_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 3115.784947 msec 0.371 microsec / call
CLOCK_MONOTONIC resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2505.122119 msec 0.299 microsec / call
CLOCK_REALTIME resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2456.186031 msec 0.293 microsec / call
CLOCK_THREAD_CPUTIME_ID resolution: 0 sec 1 nano
clock_gettime 8388608 iterations : 2956.633930 msec 0.352 microsec / call

Это стандартное ядро ​​Ubuntu.Приложение является портом приложения для Windows (где наша встроенная сборка rdtsc отлично работает).

Приложение:

Имеет ли x86-64 GCC внутренний эквивалент __ rdtsc () , чтобы я мог по крайней мере избежать встроенной сборки?

20
задан Crashworks 28 October 2011 в 22:59
поделиться