И увидел там "Листинг 6. Определение тактовой частоты процессора (файл extent.c)"
Загрузил архив с примерами lang_c_details.tgz (правда, для этого пришлось принять соглашение). Распаковавл make выдал кучу предупреждений. В основном из-за несоответствия типов. Исправил это, заменив %d на %zd. Но меня заинтересовала программа extent, которая среди прочего выводит и тактовую частоту процессора, читая какой-то счётчик с помощью функции (в модуле t030t.c)
Код: Выделить всё
static unsigned long long rdtsc( void ) {
unsigned long long int x;
asm volatile ( "rdtsc" : "=A" (x) ); // команда RDTSC
return x;
}
Запускаю. Иногда выдаёт реальную частоту (3.512 Ghz), а иногда -- что-то несуразное: 18446744072.926 Ghz
Считается она так:
Код: Выделить всё
time_t t1, t2;
unsigned long long cf=0, cs=0;
TITLE( "ассемблерные вставки" );
time( &t1 );
while( t1 == time( &t2 ) ) cf = rdtsc(); // начало очередной секунды
while( t2 == time( &t1 ) ) cs = rdtsc(); // завершение этой секунды
printf( "тактовая частота процессора %.3f Ghz\n (%llu - %llu)\n",(double)( cs - cf ) / 1.E9 , cs, cf);
Оказалось, что иногда cs меньше, чем cf.
Решил посмотреть, как меняется значение счётчика при последовательном считывании. Добавил после этого код:
Код: Выделить всё
for(i=0;i<100;i++) {
// printf("m[%d] = ",i); fflush(stdout);
m[i] = rdtsc();
// printf("%llu\n",m[i]);
}
Запускаю -- после выдачи частоты получаю
Ошибка сегментирования
Но если раскомментировать строки с printf, то программа работает.
При этом средняя разность между соседними значениями составляет примерно 37785 при выводе на консоль (в иксах) и 2800 при записи stdout в файл.
Посмотрел Makefile -- увидел, что среди опций компилятора есть -O. Убрал. Программа отработала нормально. Средняя разность между соседними получениями значения счётчика составила примерно 40.
Но как оптимизация (причём, без указания значения) могла на это повлиять?
Система Debian Jessie, amd64, gcc version 4.9.2 (Debian 4.9.2-10)