Низкие начальные временные результаты с использованием gettimeofday - хуже под RHEL6 Server - PullRequest
3 голосов
/ 31 декабря 2011

Я использую gettimeofday(), чтобы рассчитать простой пример умножения матриц, но я получаю результаты, которые изначально были вдвое длиннее.На компьютере с сервером RHEL6 я получаю «плохие» результаты синхронизации в течение почти 1 секунды (~ 65 отдельных временных интервалов в этом примере).Все остальные наши машины - это рабочие станции RHEL5, и этот код работает на них намного лучше;Изначально я получаю только пару «плохих» результатов (за первые ~ 20 миллисекунд).

Из сообщений на этом сайте я думаю, что это, вероятно, связано с планировщиком процесса ОС.Если я раскомментирую первый оператор «ниже» ниже (тем самым вставляя начальный цикл занятости путем многократной инициализации матриц a, b и c), я получаю ноль «плохих» результатов как на рабочей станции RHEL5, так и на сервере RHEL6.В качестве альтернативы, если я раскомментирую оператор sleep, я получу ВСЕ «плохие» результаты синхронизации для RHEL5 и RHEL6.

По какой-то причине мой процесс изначально запускается только с половиной доступа к ЦП, затемон получает «полный» доступ к процессору, пока процесс остается занятым.Если он «спит», а затем возобновляет синхронизацию, он снова временно получает только половину полного доступа к ЦП.

На машине больше ничего не происходит (X не работает).Я пытался «chrt» контролировать приоритет процесса, но это ничего не изменило.Я подтвердил, что это происходит как с GCC 4.4.6, так и с ICC 12.1.0.Я также попробовал "хорошо".

Вот код:

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#define N 225
#define DELAY_LOOPS 8000
main() {
  struct timeval _t0, _t1, _t2;
  double a[N][N], b[N][N], c[N][N];
  double millisec, cum_ms;
  int i, j, k, l, m=0;
  gettimeofday( &_t0, NULL );
  // for( l=0; l<DELAY_LOOPS; l++ )
    for( i=0; i<N; i++ )
      for( j=0; j<N; j++ ) {
        a[i][j]=0;
        b[i][j]=i;
        c[i][j]=j;
      }
  for( l=0; l<75; l++ ) {
    gettimeofday( &_t1, NULL );
    for( i=0; i<N; i++ )
      for( j=0; j<N; j++ )
        for( k=0; k<N; k++ )
          a[i][j]+=b[i][k]*c[k][j];
    gettimeofday( &_t2, NULL );
    millisec  = 1000*(_t2.tv_sec-_t1.tv_sec);
    millisec += 1e-3*(_t2.tv_usec-_t1.tv_usec);
    cum_ms  = 1000*(_t2.tv_sec-_t0.tv_sec);
    cum_ms += 1e-3*(_t2.tv_usec-_t0.tv_usec);
    printf( "%d: duration %fms, cumulative %fms\n",
            m++, millisec, cum_ms );
    // sleep( 2 );
  }
  printf( "a[%d][%d]=%f\n", N/2, N/2, a[N/2][N/2] );
}

и вот результаты:

% icc -O2 -o test main.c; ./test
0: duration 13.049000ms, cumulative 13.677000ms
1: duration 13.026000ms, cumulative 26.753000ms
2: duration 12.911000ms, cumulative 39.668000ms
3: duration 12.913000ms, cumulative 52.584000ms
4: duration 12.914000ms, cumulative 65.501000ms
5: duration 12.911000ms, cumulative 78.415000ms
6: duration 12.912000ms, cumulative 91.331000ms
/* snip */
64: duration 12.912000ms, cumulative 840.633000ms
65: duration 10.455000ms, cumulative 851.092000ms
66: duration 5.910000ms, cumulative 857.004000ms
67: duration 5.908000ms, cumulative 862.914000ms
68: duration 5.907000ms, cumulative 868.823000ms
69: duration 5.908000ms, cumulative 874.732000ms
70: duration 5.912000ms, cumulative 880.646000ms
71: duration 5.907000ms, cumulative 886.554000ms
72: duration 5.907000ms, cumulative 892.462000ms
73: duration 5.908000ms, cumulative 898.372000ms
74: duration 5.908000ms, cumulative 904.281000ms
a[112][112]=211680000.000000

Я испытываю проблему независимо от того,уровень оптимизации (-O0, -O1, -O2 и т. д.).

Кто-нибудь знает что-нибудь о том, как выполняется планирование в RHEL6 Server?Это так сильно отличается от RHEL5 Workstation?Я предполагаю, что различие, которое я вижу, больше зависит от того факта, что одна коробка - это серверная версия RHEL, а другая - версия для рабочей станции (а не разница между выпуском 5 и 6).Есть ли какой-нибудь простой способ уменьшить этот эффект в RHEL6 Server и заставить его работать больше как коробки RHEL5 Workstation?

Есть идеи?Спасибо.

Ответы [ 2 ]

4 голосов
/ 31 декабря 2011

Не используйте gettimeofday(2) для измерения производительности. Это слишком медленно и просто не предназначено для работы.

Вместо этого используйте clock_gettime(2). Это позволяет вам выбрать один из нескольких системных таймеров. CLOCK_REALTIME - самый простой выбор, но CLOCK_PROCESS_CPUTIME_ID может быть лучше, если он у вас есть.

2 голосов
/ 31 декабря 2011

Может ли процессор переходить в состояние пониженного энергопотребления?Что-то вроде powertop может сказать вам это.(на вкладке Статистика частоты)

...