· производительность

Оптимизация ядра с помощью 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-upstream
  • linux-upstream-headers
  • linux-upstream-api-headers
  • linux-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», который запускает разнообразные нагрузки.

https://imgur.com/a/YAjhXfN

Что дальше?

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/

Назад в блог