Трудности с измерением производительности C / C ++
Я написал фрагмент кода на C, чтобы показать точку в обсуждении оптимизации и прогнозирования ветвлений. Тогда я заметил еще более разнообразный исход, чем ожидал. Моя цель состояла в том, чтобы написать его на языке, который является общим подмножеством между C ++ и C, который совместим со стандартами для обоих языков и который достаточно переносим. Он был протестирован на разных ПК с Windows:
#include <stdio.h>
#include <time.h>
/// @return - time difference between start and stop in milliseconds
int ms_elapsed( clock_t start, clock_t stop )
{
return (int)( 1000.0 * ( stop - start ) / CLOCKS_PER_SEC );
}
int const Billion = 1000000000;
/// & with numbers up to Billion gives 0, 0, 2, 2 repeating pattern
int const Pattern_0_0_2_2 = 0x40000002;
/// @return - half of Billion
int unpredictableIfs()
{
int sum = 0;
for ( int i = 0; i < Billion; ++i )
{
// true, true, false, false ...
if ( ( i & Pattern_0_0_2_2 ) == 0 )
{
++sum;
}
}
return sum;
}
/// @return - half of Billion
int noIfs()
{
int sum = 0;
for ( int i = 0; i < Billion; ++i )
{
// 1, 1, 0, 0 ...
sum += ( i & Pattern_0_0_2_2 ) == 0;
}
return sum;
}
int main()
{
clock_t volatile start;
clock_t volatile stop;
int volatile sum;
printf( "Puzzling measurements:\n" );
start = clock();
sum = unpredictableIfs();
stop = clock();
printf( "Unpredictable ifs took %d msec; answer was %d\n"
, ms_elapsed(start, stop), sum );
start = clock();
sum = unpredictableIfs();
stop = clock();
printf( "Unpredictable ifs took %d msec; answer was %d\n"
, ms_elapsed(start, stop), sum );
start = clock();
sum = noIfs();
stop = clock();
printf( "Same without ifs took %d msec; answer was %d\n"
, ms_elapsed(start, stop), sum );
start = clock();
sum = unpredictableIfs();
stop = clock();
printf( "Unpredictable ifs took %d msec; answer was %d\n"
, ms_elapsed(start, stop), sum );
}
Составлено с VS2010; / O2 оптимизации Intel Core 2, WinXP результаты:
Puzzling measurements:
Unpredictable ifs took 1344 msec; answer was 500000000
Unpredictable ifs took 1016 msec; answer was 500000000
Same without ifs took 1031 msec; answer was 500000000
Unpredictable ifs took 4797 msec; answer was 500000000
Редактировать: Полные переключатели компилятора:
/ Zi / nologo / W3 / WX- / O2 / Oi / Oy- / GL / D "WIN32" / D "NDEBUG" / D "_CONSOLE" / D "_UNICODE" / D "UNICODE" / Gm- / EHsc / GS / Gy / fp: точный / Zc: wchar_t / Zc: forScope /Fp"Release\Tiring.pch "/ Fa" Release \ "/ Fo" Release \ "/Fd"Release\vc100.pdb" / Gd / analysis- / errorReport: очереди
Другой человек написал такое ... Скомпилировано с MinGW, g ++ 4.71, оптимизация -O1 Intel Core 2, WinXP:
Puzzling measurements:
Unpredictable ifs took 1656 msec; answer was 500000000
Unpredictable ifs took 0 msec; answer was 500000000
Same without ifs took 1969 msec; answer was 500000000
Unpredictable ifs took 0 msec; answer was 500000000
Также он опубликовал такие результаты для оптимизации -O3:
Puzzling measurements:
Unpredictable ifs took 1890 msec; answer was 500000000
Unpredictable ifs took 2516 msec; answer was 500000000
Same without ifs took 1422 msec; answer was 500000000
Unpredictable ifs took 2516 msec; answer was 500000000
Теперь у меня есть вопрос. Что здесь происходит?
Более конкретно ... Как фиксированная функция может занимать так много времени? Что-то не так в моем коде? Есть ли что-то хитрое с процессором Intel? Компиляторы делают что-то странное? Может ли это быть из-за того, что 32-битный код работает на 64-битном процессоре?
Спасибо за внимание!
Редактировать: Я принимаю, что g ++ -O1 просто повторно использует возвращенные значения в 2 других вызовах. Я также признаю, что g ++ -O2 и g ++ -O3 имеют дефект, который не учитывает оптимизацию. Значительное разнообразие измеренных скоростей (450% !!!) кажется все еще загадочным.
Я посмотрел на разборку кода, созданного VS2010. Это встроенныйunpredictableIfs
три раза. Встроенный код был довольно похож; петля была такая же. Не встроенныйnoIfs
, Это действительно катилосьnoIfs
немного. Это занимает 4 шага за одну итерацию.noIfs
рассчитать, как было написано в то время какunpredictableIfs
использованиеjne
перепрыгнуть через шаг.