Контекст: на работе я компилирую набор пакетов для Intel64 и ARM64 и объединяю их в пакеты Linux (.rpm, .deb, .apk). Для этого я создаю целый конвейер, который будет использоваться в нашей установке Artifactory.
Мы создаем автономные собственные версии ARM64 для нашей системы GitHub Enterprise Server, которые будут работать вместе с нашими существующими автономными версиями Intel64. Наши бегунки построены на базе инстансов Amazon EC2. Оба оптимизированы для вычислений.
uname -m
amd64
/x86_64
c5.2xlarge
8
16 Гб
x86_64
arm64
/aarch64
c6g.2xlarge
8
16 Гб
aarch64
arm64
/aarch64
c7g.2xlarge
8
16 Гб
aarch64
Хосты — это кластеры EKS, на которых работает Amazon Linux 2, оптимизированный для EKS.
Наши «бегуны» — это модули K8S/EKS (~Docker-контейнеры), которые умирают/возрождаются после каждого отдельного рабочего процесса. Образ Docker — это многоплатформенный образ: то же программное обеспечение, та же конфигурация, несколько процессоров. Контейнерная ОС — Ubuntu «Focal Fossa» 20.04 LTS.
Используя наши собственные средства запуска GitHub Actions, я написал рабочий процесс GHA для загрузки исходного кода проекта Rust и его компиляции — один раз на процессоре Intel и один раз на процессоре ARM64. Я запускаю uname -m
и вывожу результат как первый шаг рабочего процесса и вижу то, что ожидаю. Я также запускаю file
скомпилированный двоичный файл и вижу то, что ожидаю.
(Я очень стараюсь провести здесь сравнение яблок с яблоками.)
Я создаю https://github.com/lycheeverse/lychee как тестовый проект конвейера. Я (пока) не тестировал другие компиляции, но это показалось мне достаточно сложным, чтобы протестировать новые бегуны ARM64.
Вот скрипт сборки (${ARCH}
— это x86-64
или aarch64
, в зависимости от ситуации):
sudo apt-get -y update
sudo apt-get -y install --no-install-recommends \
build-essential \
ca-certificates \
curl \
file \
git \
gpg \
gpg-agent \
gzip \
libssl-dev \
openssh-client \
pkg-config \
software-properties-common \
tar \
wget \
;
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "${HOME}/.cargo/env"
# shellcheck disable=2154
wget --header "Authorization: Bearer ${GITHUB_TOKEN}" \
"https://github.com/lycheeverse/lychee/archive/refs/tags/v0.15.1.tar.gz"
tar zxvf "v0.15.1.tar.gz"
### Start measuring time
cd "lychee-0.15.1/" || true
cargo fetch --target = "${ARCH}-unknown-linux-gnu" --locked
cargo install cargo-auditable --locked
# The `mold` linker is pre-installed.
mold -run cargo auditable build --timings --frozen --release
sudo install -Dm755 target/release/lychee -t "/usr/local/bin/"
### Stop measuring time
Бегунок Intel на одно поколение старше бегуна Graviton/ARM64. Те же виртуальные процессоры, тот же объем доступной памяти. За измеренный промежуток времени (сценарий выше) я вижу следующие результаты (в среднем из 5 сборок):
c5
): 6 минут 18 секунд (базовый уровень)c6g
): 12 м 2 с (~ 2 раза)c7g
): 9 минут 36 секунд (~ 1,5 раза)Я ожидал паритета между двумя архитектурами ЦП или, может быть, небольшого преимущества для ARM64, поскольку экземпляр Graviton на одно поколение новее. Я также знаю, что такие языки, как Haskell, все еще работают над внедрением ARM64, и мне интересно, верно ли то же самое для Rust.
Для любителей Rustace: есть ли части конвейера сборки Rust, которые еще не оптимизированы для ARM64 в Linux на базе glibc?
Далее я собираюсь попытаться создать важный проект на Go, просто чтобы попробовать другой язык, который, как я знаю, оптимизирован для ARM64, и попытаться исключить проблемы с процессорами Graviton. Я также собираюсь создать еще один представительный проект Rust, чтобы посмотреть, получу ли я другие результаты.
Обновление (в тот же день): я выполнил тот же тест в проекте Go (OpenTofu). Он содержит более 300 000 строк кода, а также зависит от нескольких внешних зависимостей, которые необходимо загрузить и скомпилировать.
c5
): 3 мес 35 с (базовый уровень)c7g
): 2 мин 18 с (~0,64x)Здесь arm64
было улучшение на 36 % по сравнению с экземпляром Intel второго поколения. Поэтому я не думаю, что моя проблема с Rust связана с ложью Amazon о соотношении цены и качества Graviton. Я думаю, это связано с чем-то конкретно о Расте или личи.
Перед этим я тестировал экземпляр m6g.2xlarge
. Но для модулей/раннеров на базе Docker для CI мы ограничили 4 ГБ ОЗУ. Вы предполагаете, что в сборке Arm64 есть что-то, что требует больше памяти, чем сборка x86_64?
Кроме того, я использую компоновщик mold
, который должен работать намного быстрее, чем lld
, gold
или ld
.
Я сказал «может», логичное объяснение, если вы не нажмете кнопку подкачки памяти, заключается в том, что она работает медленнее.
Чтобы повысить производительность Rust на Graviton, вам следует указать использование расширений для больших систем (LSE) через RUSTFLAGS
перед созданием проекта. LSE включен в архитектуру Armv8.1 и повышает общую пропускную способность системы. Все Graviton 2 и последующие версии, основанные на линейке процессоров Neoverse, включают функцию LSE.
Включите LSE с помощью следующей строки кода перед командой cargo build --release
:
export RUSTFLAGS = "-Ctarget-feature=+lse"
Итак, после установки sudo apt-get ваш окончательный код должен выглядеть так:
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "${HOME}/.cargo/env"
# shellcheck disable=2154
wget --header "Authorization: Bearer ${GITHUB_TOKEN}" \
"https://github.com/lycheeverse/lychee/archive/refs/tags/v0.15.1.tar.gz"
tar zxvf "v0.15.1.tar.gz"
### Start measuring time
cd "lychee-0.15.1/" || true
cargo fetch --target = "${ARCH}-unknown-linux-gnu" --locked
cargo install cargo-auditable --locked
# Set RUSTFLAGS to enable LSE
export RUSTFLAGS = "-Ctarget-feature=+lse"
# The `mold` linker is pre-installed.
mold -run cargo auditable build --timings --frozen --release
sudo install -Dm755 target/release/lychee -t "/usr/local/bin/"
### Stop measuring time
В итоге я отследил это на github.com/aws/aws-graviton-getting-started/blob/main/rust.md примерно в то же время, когда вы ответили. Но я очень благодарен за вашу помощь. Спасибо! Graviton 2 был примерно на 100% медленнее, чем его эквивалент x86_64. Гравитон-3 был примерно на 50% медленнее. Если вы установите это значение, в трех отдельных проектах скорость будет в среднем примерно на 27 % медленнее. Данные говорят мне, что компиляция на aarch64 сейчас просто медленнее. Меня это устраивает, теперь, когда у меня есть объяснение.
связывание может быть тяжелым для памяти, вы можете нажать на своп, если он у вас есть.