Pull to refresh

Использование альтернативных компиляторов в Gentoo на примере Intel Compiler Suite

Configuring Linux *
В этой статья я хочу рассказать, как в Gentoo и других portage-based дистрибутивах для сборки пакетов исползовать отличный от gcc компилятор.
Выбор альтернативных компиляторов обширен: 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 за инвайт!
Tags:
Hubs:
Total votes 129: ↑113 and ↓16 +97
Views 5.3K
Comments Comments 53