Насчёт распараллеливания загрузки XML - это дичь какая-то. Как человек, который реализовал на работе красивый StAX - загрузчик, я с уверенностью могу сказать, что скорость работы таких задач упирается в скорость жёсткого диска (при адекватном исполнении, конечно). Делал как раз для задач, подобных этой. Проц не загружен даже при работе с SSD. Распараллеливать можно обработку в памяти уже загруженных данных, но никак не саму загрузку/выгрузку. Тут есть смысл делать в отдельных потоках загрузку и выгрузку. Это даст профит при расположении XML и БД на разных дисках. Обработку (если таковая требуется) можно так же делать в отдельном потоке. Синхронизация через очереди. На Java SE всё это можно делать легко и красиво. И при том, что оба диска будут работать на полную катушку, у ЦП ещё запас будет.
На самом деле очень важно, что за Java там. Если от Унипро, то должна неплохо работать и с минимальным разбросом. А если openjdk портированное, тогда странно, что вообще есть хорошие результаты.
По сравнению со всеми, кроме C++ и Rust (может и фортран, хз...), да, хорошие результаты. Но когда я специально сравнивал соотношение производительности C++/Rust/Java на x86 и на e2k, то на e2k Java сливает примерно в 2.5 раза. Всё-таки есть куда расти.
На Java, а может и не только, в методе addEdge пропущена строка adjLists[dest].add(src); Без неё не работает. Да как бы и вся идея алгоритма строится на том, что ребра - не векторы. Поэтому можно для начала выбирать любую вершину.
Я в этом тоже не силён. Но, как я понимаю, чтобы использовать LLVM при компиляции C++, нужно компилировать через clang. lcc не использует LLVM. Разница видна не только на Эльбрусах, и на x86 тоже. Только там наоборот Rust сильно вперёд ушёл. Но это под Линуксом! Попробовал под Виндой компилировать. Там для Rust сишный компилятор вроде используется и результат получается уже ближе к сишному (Rust под Виндой медленнее, чем под Линуксом). Пробовал под Линуксом собрать для Винды бинарник (кросс-компиляция). Бинарник собрался, но при запуске возникли проблемы. Толи библиотеки не хватало, не помню. Не стал в эту тему дальше закапываться.
На самом деле отставание может сократиться, когда будет доступен режим PGO для Rust. Для плюсов режим PGO дал шикарный профит, сопоставимый с опцией -ffast-math. Жду обновы ОС до 8.2 на тестовой машине. Может и GO добавлю, если будут адекватные результаты. Реализация на GO есть, но результаты на e2k сейчас совсем неприличные.
Это yukari. Т.е. просадки проявляются, если над многопоточным приложением трудятся ядра с разных ЦП? В общем то, я подозревал, что при использовании нескольких ЦП могут быть просадки. Хотя для тестов одного ЦП в многопотоке эта проблема решается довольно просто. Особенно если нет задачи брать все 8 ядер, а ограничиться, например, четырьмя. Но здесь у меня тут не стояла задача тестить производительность всего проца. Акцент именно на компиляторах. На одном ядре точнее выходит.
DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang. Выше я привёл как это сделать.
Да, спасибо. Позже, если буду дальше закапываться в C++, подойду к компиляции более серьёзно.
Компиляция в режиме -fprofile-generate, запуск программы на данных в 5*10^8,
Я конечно понимаю, что в данной программе скорее всего диапазоны: 0-100М, 0-500М, 0-1000М... дадут одну и ту же статистику. Но сам подход подстановки исключительно данных теста для сбора статистики больше похож на читерство. Нужно же, чтобы после профилирования программа получила бонус на произвольном диапазоне. Я поставлял последовательно: 100М, 500М, 2000М. Процесс подробно описал в разделе "Описание опций тестирования". Профит гарантирован.
Да я знаю. Я имел ввиду команду, которой запускаю компиляцию. Подразумевая, что настройки компиляции следует читать в CMakeLists.txt.
Вы могли сами это проверить, но давайте я сделаю это за вас:
Честно говоря, в представленном ниже выводе мне и сейчас не очевидно, что LLVM не работает. =)
-- Using LLVM version 9.0.1
...подключен же. Но, видимо, использование LLVM должно выглядеть по другому.
PGO тут не помогло.
Кстати, получил результат C++ O3+PGO - 2447мс (без прочих -ffast -ffast-math). Пока не опубликовал, т.к. буксует компиляция Rust+PGO. Не знаю, как вы делали двухфазную компиляцию, но у меня профит хороший получился. В статье укажу подробно как делал. С вашими рекомендациями: long int, #pragma swp; -O4 -march=elbrus-v4 -ffast -ffast-math -fforce-loop-apb -fforce-vect -fforce-swp PGO даёт результат 1970мс. (при 1200Мгц), что при пересчёте на 1300Мгц даст 1818мс. Не хотел обновлять статью с результатом PGO, пока нет аналогичного на Rust. Но на Rust двухфазная компиляция недоступна по независящим от меня причинам и на неопределённое время. Так что выложу пока как есть.
Внимание! Мы тестим однопоток! Это раз. Целерон тоже можно засунуть в четырёхпроцессорный сервер и получить в итоге 32 ядра? Он поддерживает ECC память? Статья не про "выбор самого выгодного ЦП на 2015 год". Это два. Ядрён, батон, какая цена?
Эльбрус можно и с лампочкой сравнить, если речь пойдёт о содержании драг.металлов в электронных компонентах. Главное - оставаться в теме.
Я, как бы, имел ввиду в общем... Ну а в этой задаче, почему линейно частоте? У 2C3 пиковая производительность в два раза больше операций за такт. Вы смотрели исходники теста? По моему, самая затратная функция makeHoles() отлично разложится в широкую команду любой длины. Там блоки по 10000!
Я же написал, ко компилировал двумя способами: g++ и cmake. И про мизерную разницу между компиляторами... как раз про это.
CMakeFiles.txt взят от балды из интернета
Не от балды, а как результат поиска вариантов использования LLVM в cmake. На статус спеца по C++ не претендую. И в статье об этом написал. У меня, как у java-разработчика с минимальными знаниями C++ и Rust, написав годный код на этих языках, стояла задача собрать годный исполняемый файл с применением самых профитных оптимизаций. Единственной ошибкой в этом вопросе пока неиспользование PGO. Исправляю этот момент. Огромная просьба! Прочитайте внимательнее статью и мои комментарии. А то вы уже начинаете с меня спрашивать то, чего я не писал... Даже тут:
В сравнении gcc и llc, gcc оказался чуть эффективнее, но разница очень маленькая
Это один и тот же компилятор. LCC является совместимым с GCC по опциям, чтобы облегчить жизнь пользователям по системе сборки. И на Эльбрусах gcc является алиасом lcc в системе.
У меня написано про llc - LLVM static compiler. А вы мне про LCC...
Насчёт распараллеливания загрузки XML - это дичь какая-то. Как человек, который реализовал на работе красивый StAX - загрузчик, я с уверенностью могу сказать, что скорость работы таких задач упирается в скорость жёсткого диска (при адекватном исполнении, конечно). Делал как раз для задач, подобных этой. Проц не загружен даже при работе с SSD.
Распараллеливать можно обработку в памяти уже загруженных данных, но никак не саму загрузку/выгрузку.
Тут есть смысл делать в отдельных потоках загрузку и выгрузку. Это даст профит при расположении XML и БД на разных дисках. Обработку (если таковая требуется) можно так же делать в отдельном потоке. Синхронизация через очереди. На Java SE всё это можно делать легко и красиво. И при том, что оба диска будут работать на полную катушку, у ЦП ещё запас будет.
На самом деле очень важно, что за Java там. Если от Унипро, то должна неплохо работать и с минимальным разбросом. А если openjdk портированное, тогда странно, что вообще есть хорошие результаты.
По сравнению со всеми, кроме C++ и Rust (может и фортран, хз...), да, хорошие результаты. Но когда я специально сравнивал соотношение производительности C++/Rust/Java на x86 и на e2k, то на e2k Java сливает примерно в 2.5 раза. Всё-таки есть куда расти.
На Java, а может и не только, в методе
addEdge
пропущена строкаadjLists[dest].add(src);
Без неё не работает. Да как бы и вся идея алгоритма строится на том, что ребра - не векторы. Поэтому можно для начала выбирать любую вершину.Я в этом тоже не силён. Но, как я понимаю, чтобы использовать LLVM при компиляции C++, нужно компилировать через clang. lcc не использует LLVM. Разница видна не только на Эльбрусах, и на x86 тоже. Только там наоборот Rust сильно вперёд ушёл. Но это под Линуксом!
Попробовал под Виндой компилировать. Там для Rust сишный компилятор вроде используется и результат получается уже ближе к сишному (Rust под Виндой медленнее, чем под Линуксом).
Пробовал под Линуксом собрать для Винды бинарник (кросс-компиляция). Бинарник собрался, но при запуске возникли проблемы. Толи библиотеки не хватало, не помню. Не стал в эту тему дальше закапываться.
На самом деле отставание может сократиться, когда будет доступен режим PGO для Rust. Для плюсов режим PGO дал шикарный профит, сопоставимый с опцией
-ffast-math
. Жду обновы ОС до 8.2 на тестовой машине. Может и GO добавлю, если будут адекватные результаты. Реализация на GO есть, но результаты на e2k сейчас совсем неприличные.Это yukari. Т.е. просадки проявляются, если над многопоточным приложением трудятся ядра с разных ЦП?
В общем то, я подозревал, что при использовании нескольких ЦП могут быть просадки. Хотя для тестов одного ЦП в многопотоке эта проблема решается довольно просто. Особенно если нет задачи брать все 8 ядер, а ограничиться, например, четырьмя. Но здесь у меня тут не стояла задача тестить производительность всего проца. Акцент именно на компиляторах. На одном ядре точнее выходит.
Если все задачи аналогичны той, что на примере, то тест ни разу не сложный.
Лучше бы пенсионерам раздали?
Для Эльбруса используется lcc. В разделе "Софт" так и указал:
Elbrus Linux 7.2
Java: OpenJDK Runtime Environment (build 11.0.15-Unipro+0-adhoc.root.openjdk11-11.0.15).
Rust: rustc / cargo v.1.57.0.
C++: lcc:1.26.22:Jan-10-2024:e2k-v4-linux (gcc (GCC) 9.3.0 compatible)
Испытуемые: Java, Rust, C++(GCC, LСC).
Сделал по отдельной ветке для тестов. Добавил туда исполняемые файлы и ассемблер.
Да, спасибо. Позже, если буду дальше закапываться в C++, подойду к компиляции более серьёзно.
Я конечно понимаю, что в данной программе скорее всего диапазоны: 0-100М, 0-500М, 0-1000М... дадут одну и ту же статистику. Но сам подход подстановки исключительно данных теста для сбора статистики больше похож на читерство. Нужно же, чтобы после профилирования программа получила бонус на произвольном диапазоне. Я поставлял последовательно: 100М, 500М, 2000М. Процесс подробно описал в разделе "Описание опций тестирования". Профит гарантирован.
... см. "Описание опций тестирования"
О, спасибо! Поправлю статью с учётом этих данных.
Да я знаю. Я имел ввиду команду, которой запускаю компиляцию. Подразумевая, что настройки компиляции следует читать в CMakeLists.txt.
Честно говоря, в представленном ниже выводе мне и сейчас не очевидно, что LLVM не работает. =)
...подключен же. Но, видимо, использование LLVM должно выглядеть по другому.
Кстати, получил результат C++ O3+PGO - 2447мс (без прочих -ffast -ffast-math). Пока не опубликовал, т.к. буксует компиляция Rust+PGO.
Не знаю, как вы делали двухфазную компиляцию, но у меня профит хороший получился. В статье укажу подробно как делал.
С вашими рекомендациями:
long int
,#pragma swp
; -O4 -march=elbrus-v4 -ffast -ffast-math -fforce-loop-apb -fforce-vect -fforce-swp PGO даёт результат 1970мс. (при 1200Мгц), что при пересчёте на 1300Мгц даст 1818мс.Не хотел обновлять статью с результатом PGO, пока нет аналогичного на Rust. Но на Rust двухфазная компиляция недоступна по независящим от меня причинам и на неопределённое время. Так что выложу пока как есть.
Я уже не знаю как ответить, честно. Тему статьи пробовали читать?
Внимание! Мы тестим однопоток! Это раз.
Целерон тоже можно засунуть в четырёхпроцессорный сервер и получить в итоге 32 ядра? Он поддерживает ECC память? Статья не про "выбор самого выгодного ЦП на 2015 год". Это два.
Ядрён, батон, какая цена?
Эльбрус можно и с лампочкой сравнить, если речь пойдёт о содержании драг.металлов в электронных компонентах. Главное - оставаться в теме.
Жаль, что нет образца потестить. Самое крутое, что есть в общем доступе, это E8C.
Я, как бы, имел ввиду в общем...
Ну а в этой задаче, почему линейно частоте? У 2C3 пиковая производительность в два раза больше операций за такт. Вы смотрели исходники теста? По моему, самая затратная функция makeHoles() отлично разложится в широкую команду любой длины. Там блоки по 10000!
Я же написал, ко компилировал двумя способами: g++ и cmake. И про мизерную разницу между компиляторами... как раз про это.
Не от балды, а как результат поиска вариантов использования LLVM в cmake. На статус спеца по C++ не претендую. И в статье об этом написал. У меня, как у java-разработчика с минимальными знаниями C++ и Rust, написав годный код на этих языках, стояла задача собрать годный исполняемый файл с применением самых профитных оптимизаций. Единственной ошибкой в этом вопросе пока неиспользование PGO. Исправляю этот момент.
Огромная просьба! Прочитайте внимательнее статью и мои комментарии. А то вы уже начинаете с меня спрашивать то, чего я не писал...
Даже тут:
У меня написано про llc - LLVM static compiler. А вы мне про LCC...
Благодарю. Поправил.