Сравнение эффективности компиляторов под Эльбрус на примере решета Эратосфена
На Хабре уже тестирование Эльбрусов на разных языках программирования (например, здесь). И данный обзор стоит рассматривать как дополнение, с ещё одним тестом, новыми версиями компиляторов и новыми участниками (Rust, С++). Так же обзор сделан с упором на тест возможностей именно компиляторов и настройки оптимизации.
Тестовые стенды:
x86:
Софт:
Ubuntu 22.04.
Java: OpenJDK Runtime Environment (build 11.0.25+9-post-Ubuntu-1ubuntu122.04).
Rust: rustc / cargo v. 1.83.0; LLVM version: 19.1.1.
C++: GCC v11.4.0; LLVM version 19.1.5.
e2k:
Софт:
Java: OpenJDK Runtime Environment (build 11.0.15-Unipro+0-adhoc.root.openjdk11–11.0.15).
Rust: rustc / cargo v. 1.57.0.
C++: GCC v9.3.0 compatible; LLVM version 13.0.1.
Испытуемые: Java, Rust, C++(GCC, LLC).
Тест.
В качестве теста выступает решето Эратосфена в блочном варианте. Один поток. На трёх языках реализовано максимально идентично. Программа в консольном варианте. Есть возможность повторного расчёта.
Методика тестирования.
Выполняем два запуска по пять прогонов поиска простых чисел в диапазоне 0 — 5×108. Первый прогон разогревочный и в расчёт не идёт. Для Java прогревочный проход обязателен. И, как показала практика, на C++ и Rust первый прогон тоже чуть медленнее. По оставшимся результатам двух прогонов вычисляется средний показатель.
Результаты тестов.
В сравнении gcc и llc, gcc оказался чуть эффективнее, но разница очень маленькая, меньше 1%. Поэтому ниже в тестах будут фигурировать значения llc с обозначением gcc/llc. Значения указаны в миллисекундах.
Некоторые неожиданности.
Ожидалось, что исполняемые файлы, полученные на одной x86-машине должны работать на другой x86-машине. Но файлы, скомпилированные GCC/LLC на AMD FX с настройкой оптимизации выше чем O0, на Intel Celeron (Haswell) выпадали с ошибкой:»Недопустимая инструкция (образ памяти сброшен на диск)». Однако с Rust таких проблем не наблюдалось. И так же всё, что скомпилировано на Intel, работало на AMD FX. При этом, независимо от того, на какой машине был получен исполняемый файл, результаты тестов совпадали.
gcc | gcc/llc O2 | gcc/llc O3 | gcc/llc O4 | Rust | Rust | Java | |
Elbrus 8C @ 1.2Ghz | 45712 | 4694 | 3912 | 3830 | 4941 | 5033 | 19357 |
AMD FX @ 3.5Ghz | 7743 | 2373 | 2208 | 2205 | 1818 | 1918 | 4635 |
Cel G1820 @ 2.7Ghz | 7508 | 1648 | 1523 | 1543 | 1183 | 1213 | 5123 |
Жирным выделены результаты самых удачных настроек компиляции для каждой машины.
Сразу бросается в глаза разница между gcc O0 и gcc/llc O2 на Эльбрусе. Такова плата за запуск неоптимизированных программ на e2k.
В отличие от x86, для Эльбруса оптимизация O4 даёт профит.
А вот для Rust везде лучший результат показала оптимизация O2.
И так, лучшие настройки оптимизации для данного теста на платформах:
x86: Rust — O2, C++ — O3.
e2k: Rust — O2, C++ — O4.
P.S.
Не являюсь специалистом по Rust и C++. Код достаточно простой и там вряд ли будут серьёзные недочёты. Но мог недоработать в плане настроек компиляции.
Благодарю компанию МЦСТ за возможность ознакомления с ЦП семейства Эльбрус!
Ресурсы:
Исходник Java, исходник Rust, исходник C++