[Перевод] Компиляция C/C++ на Apple M1

2321b15c85bee0e06028954b29beb656.jpg

Заинтригованный впечатляющими бенчмарками M1, я достал последний Mac Mini, чтобы замерить скорость компиляции на C/C++.

Измеряем локальный build2 (без репозитория пакетов), который включает преимущественно код на C++ (611 единиц трансляции) с некоторыми блоками на C (29) и связками между ними (19). Такой бенчмарк требует только компилятора C++ и входит в тестовый набор Phoronix, поэтому можно сравниться с большим количеством процессоров.

Бенчмарк Phoronix в настоящее время использует build2 0.12.0, у нас 0.13.0 (текущий релиз), здесь сборка выполняется примерно на 10% медленнее.


После настройки Mac OS и установки инструментов командной строки для XCode 12.2 у нас есть всё необходимое:

$ clang++ --version
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: arm64-apple-darwin20.1.0


Судя по _LIBCPP_VERSION в заголовке __version файла libc++, эта версия Apple Clang ответвилась от ванильного Clang где-то в процессе разработки 10.0.0.

Возможно, вы также заметили, что название процессора в триплете Apple Clang отличается от стандартного aarch64. На самом деле config.guess показывает следующее:
$ ./config.guess
aarch64-apple-darwin20.1.0

Чтобы не использовать два названия для одного и того же, build2 канонизировал arm64 в aarch64, поэтому в buildfiles мы всегда видим aarch64.


Проверим количество аппаратных потоков в sysctl:

$ sysctl -n hw.ncpu
8


Здесь 8 потоков, это 4 производительных ядра и 4 энергоэффективных. В первом прогоне задействуем все ядра. Очевидно, это даёт наилучший результат:

$ time sh ./build2-install-0.13.0.sh --local --yes ~/install
163s


Приятным сюрпризом оказалось то, что build2 0.13.0 заработал без особых проблем, хотя он вышел раньше M1. Поскольку в ARM слабое упорядочение памяти, это также послужило дополнительной проверкой многопоточной реализации build2 и интенсивного использования атомиков.


Для начала сравним M1 с моей рабочей станцией на 8-ядерном Intel Xeon E-2288G (по сути, i9–9900K плюс ECC). Та же сборка на ванильном Clang занимает 131 с. Хотя это лучший результат, но производительность M1 всё равно впечатляет. Особенно если учесть, что во время компиляции рабочая станция буквально изрыгает горячий воздух и гудит как самолёт, а М1 тихо шуршит с едва заметным потоком тёплого воздуха.

Однопоточный бенчмарк оценивает производительность CPU в инкрементальных билдах:

$ time sh. /build2-install-0.13.0.sh --local --yes-j 1 ~ / install
691s


Ядро E-2288G справляется за 826 секунд. Таким образом, ядро Xeon на 5 ГГц на самом деле медленнее, чем ядро M1 на 3,2 ГГц.

Еще один интересный результат — четырёхпоточный прогон, который использует только производительные ядра М1:

$ time sh ./build2-install-0.13.0.sh --local --yes -j 4 ~/install
207s


Хотя он несколько медленнее восьмиядерного теста, но зато использует меньше памяти. Таким образом, такой вариант имеет смысл на системах с недостатком оперативной памяти (как на всех современных машинах M1).

Вот краткое изложение всех результатов:

CPU   CORES/THREADS  TIME
-------------------------
E-2288G    8/16      131s
M1         4+4       163s
M1         4         207s
M1         1         691s
E-2288G    1         826s


Понятно, что во многих отношениях это сравнение яблок с апельсинами (рабочая станция против мобильного устройства, старый дизайн и техпроцесс против самого современного и т. д.)

Теперь добавим несколько интересных результатов из бенчмарка Phoronix. В частности, уместно взять показатели новейших рабочих станций и мобильных процессоров Intel и AMD. Вот моя подборка (можете составить собственную, только не забудьте добавить дополнительные 10% к результатам Phoronix; также обратите внимание, что в большинстве тестов используется GCC вместо Clang):

CPU                    CORES/THREADS  TIME
------------------------------------------
AMD   Threadripper 3990X    64/128    56s
AMD   Ryzen        5950X    16/32     71s
Intel Xeon       E-2288G    8/16      131s
Apple                 M1    4+4       163s
AMD   Ryzen        4900HS   8/16      176s*
Apple                 M1    4         207s
AMD   Ryzen        4700U    8/8       222s
Intel Core         1185G    4/8       281s*
Intel Core         1165G    4/8       295s

* Экстраполяция.


Обратите внимание, что результаты для лучших мобильных Intel (1185G) и AMD (4900HS), к сожалению, ещё не доступны, и приведённые цифры экстраполированы на основе частоты и других бенчмарков.

Из приведённой выше таблицы легко понять, что Apple M1 — впечатляющий процессор, особенно с учётом энергопотребления. Более того, это первый общедоступный ARM-процессор настольного класса. Для сравнения, та же сборка на Raspberry Pi 4B занимает 1724 секунды, то есть более чем в 10 раз медленнее! Хотя мы не можем тут загрузить Linux или Windows, но есть некоторые свидетельства, что они работают на виртуальных машинах с приличной производительностью. В итоге, конвейер непрерывной сборки на базе ARM может стать стандартным.

Увидев бенчмарки M1, невольно задаёшься вопросом, как Apple такое удалось. Хотя есть много спекуляций с некоторыми элементами чёрной магии и колдовства, но вполне хорошим источником технической информации мне показалась эта статья о M1 на Anandtech (и ещё одна там по ссылке). Основные моменты:

Процесс TSMC 5 нм
По сравнению с интеловскими 10 нм (для 11×5G, 14 нм для E-2288G) и 7 нм у AMD/TSMC.

LPDDR4–4266 RAM
Только новейшие мобильные процессоры от Intel и AMD работают с такой быстрой памятью.

Большой кэш L1
У M1 необычно большой кэш L1 для команд и данных.

Большой и быстрый общий кэш L2
В отличие от процессоров Intel и AMD, которые используют отдельные кэши L2 меньшего объёма и большой, но более медленный общий кэш L3, в процессоре M1 реализован быстрый и большой общий кэш L2.

Широкое ядро
У M1 необычайно «широкое» ядро, которое выполняет несколько инструкций параллельно и/или не по порядку. Есть предположение, что из-за слабого упорядочения памяти ARM и кодирования команд фиксированного размера, Apple смогла сделать гораздо более широкое ядро.


Было бы также интересно посмотреть, как Apple сможет масштабировать эту конструкцию на большее количество ядер.

© Habrahabr.ru