В этой статья я хочу рассказать, как в Gentoo и других portage-based дистрибутивах для сборки пакетов исползовать отличный от gcc компилятор.
Выбор альтернативных компиляторов обширен: Intel Compiler Suite, Sun Studio Express Compilers, TenDRA C/C++ Compiler, Tiny C Compiler и прочие легковесные компиляторы.
Я рассмотрю переход на самый популярный (AFAIK) из альтернативных компиляторов — icc.
Вы можете спросить: а зачем это вообще надо? Дело в том, что icc оптимизирует код для исполнения на интеловских процессорах лучше, чем gcc.
Сравните сами:
Согласитесь, весьма неплохие результаты.
Конфигурация компьютера, на котором производилась проверка: Intel Core 2 Duo T7250 @ 2.00 GHz; linux 2.6.31-gentoo-r7 x86; gcc-4.4.2; icc-11.1.056; все тесты выполнялись в tmpfs — разделе, дабы не грешить на скорость i/o.
Если вы готовы, приступим к установке.
icc требует для своей работы лицензию, воспользуемся бесплатным некоммерческим вариантом, который можно получить здесь. Когда вы получите .lic-файлик, положите его в /opt/intel/licenses.
Сразу предупрежу, что некоторые приложения не собираются icc, а некоторые собираются, но не работают, хотя разработчики icc стремятся сделать его максимально совместимым с gcc. Поэтому нельзя сказать, что смена компилятора будет полной — что-то можно собрать только gcc, и отказываться от него мы не будем. У нас два варианта: компилировать всё icc, а отдельные приложения — gcc, либо наоборот, оставить основным компилятором gcc, а icc собирать только некоторые программы. Вам решать, какой из них выбрать — если вы не можете себе позволить долго ковыряться в системе, или просто не хотите лишних проблем, то для вас, скорее всего, более приемлим второй вариант; если же у вас достаточно свободного времени и/или желания попробовать что-то новенькое, то ваш вариант — первый.
Будем считать, что флаги для icc в make.conf определены как ICCCFLAGS и ICCCXXFLAGS (как CFLAGS и CXXFLAGS для gcc); список пакетов, которые нужно собирать gcc, лежит в /etc/portage/package.gcc; особые флаги для отдельных пакетов — в /etc/portage/package.gcc-cflags и /etc/portage/package.icc-cflags.
Текущий компилятор определен в переменных окружения OCC и OCXX — вот и изменим их.
Для этого создадим скрипт /etc/portage/bashrc следующего содержания:
Аналогично предыдущему случаю, только тут список пакетов, собираемых icc, в /etc/portage/package.icc
Все! Ваша система готова собирать пакеты новым компилятором.
Один, но жирный. Заметное ускорение работы процессороемких процессов — (де)кодирования аудио/видео, (де)шифрования, etc.
1. Неполная совместимость с gcc. Некоторые программы не собираются icc, некоторые собираются, но не работают. Например, программы, использующие алгоритм LZMA (xz-utils, p7zip), собираются, но не распаковывают архивы — мол, они битые. Уверен, что это не единственный пример.
2. icc линкует исполняемые файлы с собственными библиотеками, и, если вы по каким-либо причинам решите удалить его, то вам придется пересобирать все пакеты, собранные им.
3. icc закрыт. Для некоторых это не минус, но согласитесь, что открытие его исходников никому бы (кроме Intel, конечно) вреда не принесло.
Хочу сказать, что переход на другие компиляторы ничем не отличается по сути — в скрипте нужно всего лишь изменить icc на выбранный компилятор.
Надеюсь, что эта статья будет вам полезна.
P.S. Спасибо gribozavr за инвайт!
Выбор альтернативных компиляторов обширен: Intel Compiler Suite, Sun Studio Express Compilers, TenDRA C/C++ Compiler, Tiny C Compiler и прочие легковесные компиляторы.
Я рассмотрю переход на самый популярный (AFAIK) из альтернативных компиляторов — icc.
Вы можете спросить: а зачем это вообще надо? Дело в том, что icc оптимизирует код для исполнения на интеловских процессорах лучше, чем gcc.
Сравните сами:
тестируемая программа | bunzip2 linux-2.6.32.tar.bz2 | bzip2 linux-2.6.32.tar | oggenc -q5 testfile.wav | lame -V4 testfile.wav |
---|---|---|---|---|
среднее время выполнения (gcc) | 22.118 | 91.452 | 108.554 | 98.438 |
среднее время выполнения (icc) | 20.373 | 68.284 | 88.581 | 84.626 |
прирост скорости | 8.5% | 33.9% | 22.5% | 16.3% |
Согласитесь, весьма неплохие результаты.
Конфигурация компьютера, на котором производилась проверка: Intel Core 2 Duo T7250 @ 2.00 GHz; linux 2.6.31-gentoo-r7 x86; gcc-4.4.2; icc-11.1.056; все тесты выполнялись в tmpfs — разделе, дабы не грешить на скорость i/o.
Установка
Если вы готовы, приступим к установке.
# emerge icc
icc требует для своей работы лицензию, воспользуемся бесплатным некоммерческим вариантом, который можно получить здесь. Когда вы получите .lic-файлик, положите его в /opt/intel/licenses.
Настройка portage
Сразу предупрежу, что некоторые приложения не собираются icc, а некоторые собираются, но не работают, хотя разработчики icc стремятся сделать его максимально совместимым с gcc. Поэтому нельзя сказать, что смена компилятора будет полной — что-то можно собрать только gcc, и отказываться от него мы не будем. У нас два варианта: компилировать всё icc, а отдельные приложения — gcc, либо наоборот, оставить основным компилятором gcc, а icc собирать только некоторые программы. Вам решать, какой из них выбрать — если вы не можете себе позволить долго ковыряться в системе, или просто не хотите лишних проблем, то для вас, скорее всего, более приемлим второй вариант; если же у вас достаточно свободного времени и/или желания попробовать что-то новенькое, то ваш вариант — первый.
Первый вариант: основной компилятор — icc, дополнительный — gcc
Будем считать, что флаги для icc в make.conf определены как ICCCFLAGS и ICCCXXFLAGS (как CFLAGS и CXXFLAGS для gcc); список пакетов, которые нужно собирать gcc, лежит в /etc/portage/package.gcc; особые флаги для отдельных пакетов — в /etc/portage/package.gcc-cflags и /etc/portage/package.icc-cflags.
Текущий компилятор определен в переменных окружения OCC и OCXX — вот и изменим их.
Для этого создадим скрипт /etc/portage/bashrc следующего содержания:
export GCC=${OCC} # сохраним старое значение переменных
export GCXX=${OCXX}
export OCC="icc" # меняем компилятор
export OCXX="icpc"
export GCCCFLAGS=${CFLAGS} # сохраним старые флаги
export GCCCXXFLAGS=${CXXFLAGS}
export CFLAGS=${ICCCFLAGS} # меняем флаги
export CXXFLAGS=${ICCCXXFLAGS}
[ -r ${ROOT}/etc/portage/package.gcc ] || return 0
while read -a target; do
if [ "${target}" = "${CATEGORY}/${PN}" ]; then # если текущий пакет указан в /etc/portage/package.gcc, то
export OCC="${GCC}" # возвращаем старый компилятор
export OCXX="${GCXX}"
export CFLAGS="${GCCCFLAGS}" # и флаги для него
export CXXFLAGS="${GCCCXXFLAGS}"
if [ -r ${ROOT}/etc/portage/package.gcc-cflags ]; then # а если еще и в /etc/portage/package.gcc-cflags, то
while read target flags; do
if [ "${target}" = "${CATEGORY}/${PN}" ]; then
export CFLAGS="$CFLAGS $flags" # добавим еще флаги
export CXXFLAGS="$CXXFLAGS $flags"
break
fi
done < ${ROOT}/etc/portage/package.gcc-cflags
fi
return 0
fi
done < ${ROOT}/etc/portage/package.gcc
if [ -r ${ROOT}/etc/portage/package.icc-cflags ]; then # аналогично для icc
while read target flags; do
if [ "${target}" = "${CATEGORY}/${PN}" ]; then
export CFLAGS="$CFLAGS $flags"
export CXXFLAGS="$CXXFLAGS $flags"
break
fi
done < ${ROOT}/etc/portage/package.icc-cflags
fi
export CC_FOR_BUILD="${OCC}" # маленький workaround
unset GCC
unset GCXX
unset GCCCFLAGS
unset GCCCXXFLAGS
Второй вариант: основной компилятор — gcc, дополнительный — icc
Аналогично предыдущему случаю, только тут список пакетов, собираемых icc, в /etc/portage/package.icc
[ -r ${ROOT}/etc/portage/package.icc ] || return 0
while read -a target; do
if [ "${target}" = "${CATEGORY}/${PN}" ]; then # если текущий пакет указан в /etc/portage/package.icc, то
export OCC="icc" # меняем компилятор
export OCXX="icpc"
export CFLAGS="${ICCCFLAGS}" # и флаги для него
export CXXFLAGS="${ICCCXXFLAGS}"
if [ -r ${ROOT}/etc/portage/package.icc-cflags ]; then # а если еще и в /etc/portage/package.icc-cflags, то
while read target flags; do
if [ "${target}" = "${CATEGORY}/${PN}" ]; then
export CFLAGS="$CFLAGS $flags" # добавим еще флаги
export CXXFLAGS="$CXXFLAGS $flags"
break
fi
done < ${ROOT}/etc/portage/package.icc-cflags
fi
export CC_FOR_BUILD="${OCC}" # маленький workaround
return 0
fi
done < ${ROOT}/etc/portage/package.icc
if [ -r ${ROOT}/etc/portage/package.gcc-cflags ]; then # аналогично для gcc
while read target flags; do
if [ "${target}" = "${CATEGORY}/${PN}" ]; then
export CFLAGS="$CFLAGS $flags"
export CXXFLAGS="$CXXFLAGS $flags"
break
fi
done < ${ROOT}/etc/portage/package.gcc-cflags
fi
fi
Все! Ваша система готова собирать пакеты новым компилятором.
Плюсы и минусы
Плюс
Один, но жирный. Заметное ускорение работы процессороемких процессов — (де)кодирования аудио/видео, (де)шифрования, etc.
Минусы
1. Неполная совместимость с gcc. Некоторые программы не собираются icc, некоторые собираются, но не работают. Например, программы, использующие алгоритм LZMA (xz-utils, p7zip), собираются, но не распаковывают архивы — мол, они битые. Уверен, что это не единственный пример.
2. icc линкует исполняемые файлы с собственными библиотеками, и, если вы по каким-либо причинам решите удалить его, то вам придется пересобирать все пакеты, собранные им.
3. icc закрыт. Для некоторых это не минус, но согласитесь, что открытие его исходников никому бы (кроме Intel, конечно) вреда не принесло.
Заключение
Хочу сказать, что переход на другие компиляторы ничем не отличается по сути — в скрипте нужно всего лишь изменить icc на выбранный компилятор.
Надеюсь, что эта статья будет вам полезна.
P.S. Спасибо gribozavr за инвайт!