Оптимизация ядра с помощью AutoFDO в CachyOS
autofdo, оптимизация, ядро, производительность
AutoFDO — это метод оптимизации, повышающий производительность кода на основе профилирования выборкой. AutoFDO работает аналогично PGO (Profile-Guided Optimization), но использует для оптимизации получаемого кода данные профилирования процессора. Как и PGO, AutoFDO требует двух этапов компиляции.
В этом руководстве показано, как с помощью функции make pacman-pkg создать ядро, которое легко устанавливается в системе на базе Arch Linux. Я пытался встроить это в стандартный процесс на основе PKGBUILD, но столкнулся с проблемами при упаковке, о которых было сообщено в upstream. Отчёт можно посмотреть здесь: https://lore.kernel.org/lkml/3183ab86-8f1f-4624-9175-31e77d773699@cachyos.org/
Опция make pacman-pkg использует упрощённый PKGBUILD для упаковки ядра, и этот способ у меня сработал лучше. Поэтому мы будем использовать именно его.
Поддерживаемые процессоры
- AMD: Zen 3 (только EPYC с BRS) и Zen4 / Zen5
- Intel: все процессоры, поддерживающие LBR (вероятно, любые начиная с Haswell)
Клонирование и настройка ядра
В этом разделе мы клонируем ядро Linux и настроим его для AutoFDO. Кроме того, мы включим ThinLTO для дополнительной оптимизации.
git clone -b 6.12/base-autofdo https://github.com/cachyos/linux
cd linux
zcat /proc/config.gz > .config
make LLVM=1 LLVM_IAS=1 prepare
## Enable AutoFDO and ThinLTO
scripts/config -e CONFIG_AUTOFDO_CLANG
scripts/config -e CONFIG_LTO_CLANG_THIN
Компиляция
make LLVM=1 LLVM_IAS=1 pacman-pkg -j"$(nproc)"
Установка и запуск рабочей нагрузки
После завершения компиляции вы получите пакет с именем linux-upstream-$pkgver.tar.zst. Пакетов будет три:
linux-upstreamlinux-upstream-headerslinux-upstream-api-headerslinux-upstream-debug
Удалите пакет linux-upstream-api-headers следующей командой (он не нужен и в данный момент вызывает конфликт при установке):
rm linux-upstream-api-headers-$pkgver
После этого установите ядро командой:
sudo pacman -U linux-upstream-$pkgver.tar.zst linux-upstream-headers-$pkgver.tar.zst linux-upstream-debug-$pkgver.tar.zst
Рабочая нагрузка
Сначала нужно отключить требование прав sudo для perf record:
sudo sh -c "echo 0 > /proc/sys/kernel/kptr_restrict"
sudo sh -c "echo 0 > /proc/sys/kernel/perf_event_paranoid"
Затем запустите рабочую нагрузку и профилируйте ядро. Лично я собирал ядро CachyOS по его PKGBUILD следующими командами: Примечание: для этого perf должен быть собран с «libpfm». В CachyOS это есть по умолчанию. В archlinux, пожалуйста, выполните следующее:
paru -S libpfm devtools
pkgctl repo clone --protocol=https linux-tools && cd linux-tools
rm PKGBUILD && wget https://raw.githubusercontent.com/CachyOS/CachyOS-PKGBUILDS/refs/heads/master/toolchain/linux-tools/PKGBUILD
makepkg -s
sudo pacman -U perf-$pkgver.tar.zst
git clone https://github.com/cachyos/linux-cachyos
cd linux-cachyos/linux-cachyos
sudo pacman -S perf
# We use perf record to profile the workload
# AMD:
perf record --pfm-events RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c 500009 -o kernel.data -- time makepkg -sfc --skipinteg
# Intel:
perf record --pfm-events BR_INST_RETIRED.NEAR_TAKEN:k -a -N -b -c 500009 -o kernel.data -- time makepkg -sfci --skipinteg
Когда компиляция завершится, у вас появится файл kernel.data. Его размер зависит от частоты профилирования. В моём случае он составил около 1,4 ГБ.
Генерация профиля для AutoFDO
Сначала скачайте приложение AutoFDO create_llvm_prof отсюда. Поместите его в текущий каталог и выполните следующую команду для преобразования профиля:
./create_llvm_prof --binary=/usr/lib/modules/6.12.0-rc5-00015-gd89df38260bb/build/vmlinux --profile=/home/ptr1337/projects/kernel/linux-cachyos/linux-cachyos/kernel.data --format=extbinary --out=/home/ptr1337/projects/kernel/linux-cachyos/linux-cachyos/kernel-compilation.afdo
Замените --binary на путь для вашей версии пакета (pkgver). Путь также можно посмотреть через pacman:
pacman -Ql linux-upstream-headers | grep vmlinux
С LLVM 19 create_llvm_prof больше не понадобится, но поскольку Arch Linux часто с опозданием выпускает новые версии LLVM, пока мы используем этот инструмент.
Полученный в моём случае профиль весил около 1,2 МБ. В моих тестах на процессоре Zen5 размеры профилей составляли от 800 КБ до 1,5 МБ в зависимости от нагрузки. Несколько профилей можно объединить с помощью LLVM 19 и llvm-profgen.
Финальная компиляция
Это последний шаг перед тем, как у нас наконец появится ядро, оптимизированное с AutoFDO. Перейдите в каталог «linux» из первого клонированного репозитория и выполните:
cd ~/projects/kernel/linux # example of my path
make clean
make LLVM=1 LLVM_IAS=1 CLANG_AUTOFDO_PROFILE=/home/ptr1337/Desktop/kernel-compilation.afdo pacman-pkg -j"$(nproc)"
Замените CLANG_AUTOFDO_PROFILE на путь к вашему преобразованному профилю (из предыдущего шага). После запуска компиляции будет сформирован пакет, который можно установить после оптимизации.
Результаты
Я протестировал это оптимизированное ядро с помощью «cachyos-benchmarker», который запускает разнообразные нагрузки.
Что дальше?
Propeller
Propeller также добавлен в тот же набор патчей, что и AutoFDO. Он может ещё больше повысить производительность ядра, но требует дополнительного этапа компиляции и профилирования. Как только Archlinux обновится до LLVM 19, я также подготовлю руководство по нему, которое можно будет считать второй частью этого руководства.
BOLT
В BOLT также недавно добавлена поддержка ядра. Патч для ядра пока ожидает рассмотрения, но в ближайшем будущем он также будет опубликован в lkml. BOLT можно применять даже после AutoFDO и Propeller.
Интеграция в PKGBUILD linux-cachyos
Встроить AutoFDO в наш текущий PKGBUILD было бы очень здорово — это упростило бы процесс и сделало использование ещё удобнее для многих пользователей. Как уже упоминалось, я всё ещё сталкиваюсь с ошибками при интеграции propeller, но мы постараемся решить это в ближайшем будущем.
Кроме того, мы хотим найти способ интегрировать AutoFDO в наше ядро по умолчанию, но остаются сложности с созданием профиля непосредственно в том же процессе. Я немного изучил virtme-ng, и это может стать возможным решением. Либо можно представить такой вариант: ядро собирается в chroot, устанавливается на тестовую машину, затем профиль загружается в источник PKGBUILD и используется во время компиляции.
Это ещё больше улучшит производительность CachyOS «из коробки».
Обновление
Выявлена первопричина проблемы упаковки стандартного «linux-cachyos». Проблема в том, что strip завершается с ошибкой, из-за чего упаковка не может продолжиться. Эта регрессия появилась в binutils 2.43. Упаковка с binutils 2.42 работает без проблем. Мы скоро сообщим о проблеме и надеемся, что вскоре сможем интегрировать AutoFDO в ядро CachyOS!
Подробнее: https://lore.kernel.org/lkml/CAF1bQ=SbeR3XhFc7JYGOh69JZfAwQV8nupAQM+ZxpzNEFUFxJw@mail.gmail.com/