Каким бы тёплым и ламповым старый софт не был, но рано или поздно от него приходится отказываться, и сейчас я покажу это на примере компиляторов.
Допустим у нас есть приложение, которое выполняет некоторые вычисления.
Попробуем скомпилировать его различными версиями gcc и icc. И измерим время выполнения. Опции компиляции следующие:
1 2 |
gcc-4.X -std=c99 -O3 Puncare_Map_ADgyro_v.1.1_win.c time_measurement.c -lm -o linear_4.X icc -std=c99 -O2 Puncare_Map_ADgyro_v.1.1_win.c time_measurement.c -lm -o linear_icc -static |
Версия компилятора | Время выполнения,c | Во сколько раз медленнее лидера |
gcc-4.1 | 70.0 | 3.68 |
gcc-4.3 | 45.3 | 2.38 |
gcc-4.4 | 45.9 | 2.42 |
gcc-4.5 | 34.9 | 1.84 |
gcc-4.6 | 34.7 | 1.83 |
gcc-4.7 | 34.9 | 1.84 |
icc-13.1.1 | 19.0 | 1.0 |
*Использованы средние значения по 10 измерениям.
Уже хорошо видно, что использование современных компиляторов позволяет сократить длительность вычислений почти в 4 раза. Но это ещё не всё! В новых версиях gcc/icc добавлена поддержка OpenMP, который позволяет распараллеливать код с помощью директив компилятора и минимальными изменениями кода. Параллельную версию использованного выше примера можно также посмотреть на github’е. Использованные опции компиляции:
1 2 |
gcc-4.X -fopenmp -std=c99 -O3 Puncare_Map_ADgyro_v.1.1_win_parallel.c time_measurement.c -lm -o parallel_4.X icc -fopenmp -std=c99 -O2 Puncare_Map_ADgyro_v.1.1_win_parallel.c time_measurement.c -lm -o parallel_icc -static |
Версия компилятора | Время выполнения,c | Во сколько раз медленнее лидера |
gcc-4.4 | 9.85 | 2.46 |
gcc-4.5 | 6.85 | 1.71 |
gcc-4.6 | 6.76 | 1.69 |
gcc-4.7 | 6.75 | 1.68 |
icc-13.1.1 | 4.01 | 1.0 |
*Использованы средние значения по 10 измерениям.
Кроме того компиляторы начинают лучше подстраиваться под особенности архитектуры конкретных линеек процессоров. С оптимизацией под процессор хоста компилировалось так:
1 2 |
gcc-4.X -fopenmp -mtune=native -march=native -std=c99 -O3 Puncare_Map_ADgyro_v.1.1_win_parallel.c time_measurement.c -lm -o parallel_4.X icc -fopenmp -std=c99 -O2 Puncare_Map_ADgyro_v.1.1_win_parallel.c time_measurement.c -lm -o parallel_icc -static |
Тут стоит заметить, что код, сгенерированный компилятором от Intel, запускался на процессоре AMD!
Версия компилятора | Время выполнения,c | Во сколько раз медленнее лидера |
gcc-4.4 | 9.81 | 2.45 |
gcc-4.5 | 6.79 | 1.69 |
gcc-4.6 | 6.64 | 1.66 |
gcc-4.7 | 6.60 | 1.65 |
icc-13.1.1 | 4.01 | 1.0 |
*Использованы средние значения по 10 измерениям.
В итоге небольшая модификация кода и выбор современного компилятора может уменьшить время выполнения почти в 20 раз.
UPD. Ну и ко всей этой бочке мёда прилагается ложка дёгтя — почти во всех тестах результаты вычислений получались разные, а т.к. качество результата я определить не могу, а «на глаз» они все довольно близки, то в рамках данного теста оставим всё как есть, а с числами с плавающей запятой разберёмся отдельно в следующем посте.
Ну и разные опции -O2 и -O3 обусловлены тем, что во время тестирования компилятора от Intel было замечено, что -O2 генерирует более быстрый код, а все предыдущие перетестировать было уже лень.
Исходник time_measurement.c