Я использую gettimeofday()
для измерения времени простого примера умножения матрицы, но я получаю результаты, которые изначально почти в два раза длиннее. На компьютере с сервером RHEL6 я получаю «плохие» результаты синхронизации в течение почти 1 секунды (~ 65 отдельных таймингов в этом примере). Все другие наши машины представляют собой рабочие станции RHEL5, и этот код работает на них намного лучше; Сначала я получаю только пару «плохих» результатов (в течение первых ~ 20 миллисекунд).
Судя по сообщениям на этом сайте, я думаю, что это, вероятно, как-то связано с планировщиком процессов ОС. Если я раскомментирую первый оператор «for» ниже (тем самым вставив начальный цикл занятости путем многократной инициализации матриц a, b и c), я не получу «плохих» результатов как на рабочей станции RHEL5, так и на сервере RHEL6. В качестве альтернативы, если я раскомментирую оператор сна, я получу ВСЕ «плохие» результаты синхронизации как для 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? Так ли сильно она отличается от рабочей станции RHEL5? Я предполагаю, что разница, которую я вижу, больше связана с тем, что одна коробка является серверной версией RHEL, а другая — версией для рабочих станций (а не различием между выпуском 5 и 6). Есть ли простой способ уменьшить этот эффект на сервере RHEL6 и сделать его более похожим на рабочие станции RHEL5?
Есть идеи? Спасибо.
gettimeofday()
называется послесловием. Просто мои 0,02 доллара - person Lelouch Lamperouge   schedule 31.12.2011