GNU Parallel запускает Makefile с разными уровнями оптимизации

Не существует оптимального уровня -O. Мой подход, чтобы найти самое быстрое выполнение для моего конкретного кода, состоит в том, чтобы скомпилировать тот же код с обычными уровнями оптимизации (т.е. -O0, -Ofast, -O1, -O2, -O3, -march=native) и проверить, какие флаги производят мне самое быстрое исполнение (со временем).

Итак, есть ли способ проверить все уровни оптимизации (перечисленные выше), запустив Makefile с каждой оптимизацией (уровень -O)?

Я думаю, что Gnu Parallel может запустить Makefile, изменив уровень -O, но я не знаю, как это понять?

Заранее спасибо.


person Bruce_Warrior    schedule 31.07.2015    source источник
comment
Почему установка CCFLAGS снова не вариант?   -  person Eugene Sh.    schedule 31.07.2015
comment
Может быть вариант, но как рекурсивно редактировать CCFLAGS, чтобы проверить все уровни оптимизации с использованием уникального Makefile? GnuParallel может быть полезен, но я не знаю, как эффективно выполнить эту задачу.   -  person Bruce_Warrior    schedule 31.07.2015
comment
Команда time не очень хороший показатель скорости работы программы. ncsu.edu/hpc/Documents/sprofile.php   -  person Jeremiah Dicharry    schedule 31.07.2015
comment
Попробуйте запустить time дважды в одной и той же программе, вы можете увидеть, что она работает быстрее во второй раз, потому что она загружается с жесткого диска в первый раз, а во второй раз уже находится в памяти.   -  person Jeremiah Dicharry    schedule 01.08.2015
comment
Вы получите гораздо больше информации с помощью профилировщика.   -  person Jeremiah Dicharry    schedule 01.08.2015
comment
-Ofast -march=native должна дать самую быструю программу, даже если вы игнорируете строгое соответствие стандартам, то есть -ffast-math. gcc.gnu.org/onlinedocs/ gcc-5.2.0/gcc/   -  person Jeremiah Dicharry    schedule 01.08.2015
comment
@JeremiahDicharry: -funroll-loops — важная опция, которая доступна только с -fprofile-use. (или вручную), поэтому не просто профилируйте, но и позволяйте компилятору использовать результаты.   -  person Peter Cordes    schedule 01.08.2015
comment
Также разрешить компилятору использовать результаты?. Пожалуйста, @PeterCordes, не могли бы вы объяснить мне смысл этого предложения?   -  person Bruce_Warrior    schedule 01.08.2015
comment
@Bruce_Warrior: обновил мой ответ оптимизацией на основе профиля со ссылками на руководства по clang и gcc.   -  person Peter Cordes    schedule 01.08.2015


Ответы (1)


Вы хотите использовать GNU Parallel для параллельного выполнения нескольких сборок? Вам понадобятся как минимум отдельные каталоги сборки и более сложная настройка сборки, если вы хотите избежать копирования всего каталога исходного кода. Если вы попытаетесь сделать несколько отдельных сборок в одном и том же каталоге одновременно, некоторые объектные файлы будут собраны с одним набором CFLAGS, а другие — с другими.

Используйте предложение цикла @Etan:

NJOBS=$(getconf _NPROCESSORS_ONLN)  # adjust as desired
for flag in -O{0..3} -O{3,fast}" -march=native"; do
    make clean
    make -j"$NJOBS" CFLAGS+="$flag -fprofile-generate"
    ./a.out  # feed it some input that exercises different options and code paths
    make clean
    make -j"$NJOBS" CFLAGS+="$flag -fprofile-use"
    perf stat ./a.out | tee "perfstat$flag.txt"
done

Обратите внимание на использование make -j для параллелизма, а не параллелизма GNU. Также обратите внимание на использование профильной оптимизации. x264 имеет систему сборки с целью make fprofiled для сборки исполняемого файла PGO, которая заботится о цикле сборки/запуска/перестроения. Так что это возможно, но IDK, если это запутает их Makefile.

Вы можете использовать GNU parallel для хронометража вашего кода, но вы получите более согласованные результаты, если будете выполнять хронометраж на бездействующей машине.

Если вы хотите проверить, как работает ваш код, когда несколько его копий выполняются одновременно, конкурируя за место в кеше и пропускную способность памяти (или даже ресурсы выполнения с гиперпоточностью), протестируйте это с несколькими копиями одного и того же код, некоторые прогоны которого не конкурируют с gcc, некоторые с -O0, а некоторые с -O3.

Что касается параметров оптимизации, вы обычно получаете наилучшие результаты от gcc с -fprofile-generate и -fprofile-use вариантов. Clang также может выполнять оптимизацию на основе профиля, используя те же параметры. или с использованием данных счетчиков производительности ЦП. (В руководстве описывается использование инструмента для преобразования данных Linux perf record во что-то, что может использовать Clang.)

Некоторые оптимизации gcc включаются только с помощью -fprofile-use (или вручную, а не только с помощью -O3). например -funroll-loops может помочь в некоторых сложных петлях. Не используйте для всего, потому что больший размер кода может привести к общему промаху I-кэша во всей программе, что перевешивает выигрыш от уменьшения накладных расходов на цикл в некоторых горячих циклах.

person Peter Cordes    schedule 31.07.2015
comment
NCPUS=getconf _NPROCESSORS_ONLN - person Bruce_Warrior; 01.08.2015
comment
На самом деле имеет смысл сказать make использовать больше заданий, чем у вас есть ЦП, чтобы скрыть задержку ввода-вывода. Или использовать меньше, если у вас есть другие вещи. Но хорошее предложение для getconf. - person Peter Cordes; 01.08.2015
comment
Другой альтернативой проверке производительности кода является: valgrind —tool=callgrind ./a.out и анализ ее позже с помощью kcachegrind или callgrind_annotate, проверяющих стоимость оценки цикла. Однако я не знаю, какой вариант (альтернатива perf или valgrind) рекомендуется - person Bruce_Warrior; 04.08.2015