![]() |
|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
![]() |
|
Опции темы | Поиск в этой теме |
![]() |
#1 |
Форумчанин
Регистрация: 16.05.2024
Сообщений: 186
|
![]()
Вижу что моё сообщение здесь про сравнение разных языков программирования на примере расчёта простых чисел набрало 765 просмотров, видимо эта тема интересует многих (или это всё боты?). Поэтому решил продолжить исследование на эту тему.
Сейчас буду сравнивать языки программирования на работе с одномерными массивами в операционной системе Linux. Начну с C++. Задача, решение которой будет реализовано на нескольких языках, такая: даны два множества целых чисел, в каждом из множеств элементы не повторяются. Множества представляются в виде массивов, где элементы случайно перемешаны. Необходимо проверить, не является ли какое-либо из множеств подмножеством другого. Проверку будем проводить простым перебором. А что тут сравнивать, подумают некоторые. Цикл в цикле, а в нём проверка a[i]==b[j], и всё. Но доступ к элементам массивов может быть организован по-разному в разных языках. В разных языках по-разному реализована run-time проверка индекса массива. Кроме этого, для хранения массивов можно использовать различные средства: статическая память, динамическая память, тип-контейнер. Это тоже будем сравнивать - с каким массивом работа быстрее. Ещё интересно проверить ускорит ли работу применение SIMD-инструкций (MMX, SSE и т.д.) и применение параллельных функций обработки типов-контейнеров (политика исполнения std::execution: ![]() Для работы программ необходимо сначала подготовить файлы с тестовыми массивами. В первом массиве будет 500 тысяч элементов (целых чисел), а во-втором - 50 тысяч. Формат файла - текстовый, в каждой строке - по одному числу, в первой строке - длина массива, в дальнейших строках идут элементы друг за другом. Код для генерации тестового массива выглядит так (на языке C++): Код:
set1_len - длина массива, resize - выделяем место для массива в контейнере, iota - массив заполняется целыми числами от 1 до set1_len, shuffle - элементы массива перемешиваются случайным образом. Полный текст программы для создания тестовых массивов смотрите в прикреплённом архиве в каталоге cpp/genset. ------ Подсчёт времени работы программы ведётся при помощи функции std::chrono::system_clock::now() без учёта времени запуска программы операционной системой, то есть так: Код:
Компиляцию и запуск делал на компьютере в Debian 10 и ALT Linux 10. В Debian компиляторы GCC 8.3, Clang 7, в ALT - GCC 10.3, Clang 17. В результатах если никаких пометок, значит компилировал и запускал в Debian, если пометка alt - значит в ALT. Все программы компилируются с опциями -O или -O3 (для оптимизации). -------- Считается, что с данными в статической памяти программы работают быстрее всего, поэтому начнём тестирование с массивов в стэке. Выделить память в стэке функции можно вызовом alloca(): Код:
Проверка множеств (в виде массивов) на вхождение друг в друга происходит так (хронометраж только для этого): Код:
Результаты запуска программы с массивами в стэке (обратите внимание: в C++ нет автоматической проверки индекса массива) - время вычисления в секундах, чем меньше тем лучше (вычисляется среднее значение по нескольким запускам): Clang C++ - 14.02215 Clang C++ (alt) - 14.62863 GNU C++ (alt) - 14.6694 GNU C++ - 18.46837 Видно, что результаты почти одинаковые, а 18 секунд у GNU C++ в Debian'е потому что у него не включился оптимизатор (я задавал разные опции, но он не включился). SIMD-инструкции не генерировались (я дизассемблировал), даже если задавать опции -mmmx и -msse. -------- Для размещения массива в динамической памяти применяется оператор new: set1 = new long int [ set1_len ] ; Потом память надо освободить через delete []. Сравнение динамических массивов происходит точно так же, как статических: Код:
Результаты запуска программы с динамическими массивами (обратите внимание что нет проверки индекса) в секундах: GNU C++ (alt) - 14.96082 Clang C++ (alt) - 15.06715 Clang C++ - 16.04735 GNU C++ - 18.43532 18 секунд у GNU C++ - потому что не включился оптимизатор. SIMD-инструкции не генерировались. ------ Продолжение в следующем сообщении |
![]() |
![]() |
![]() |
#2 |
Форумчанин
Регистрация: 16.05.2024
Сообщений: 186
|
![]()
Если массив размещять в типе-контейнере std::vector, то работать с ним надо при помощи функций из <algorithm>, а иначе нет смысла использовать вектор.
Код:
![]() Код:
![]() std::execution::unseq - разрешает в однопоточном коде использовать SIMD. Проверим скорость работы программы со всеми этими параметрами в ALT (в Debian компиляторы это не поддерживают). В секундах: GNU C++ - 10.44525 GNU C++ (alt) - 11.32513 GNU C++ (alt) паралел. - 11.10373 GNU C++ (alt) паралел.+SIMD - 28 GNU C++ (alt) SIMD - 20 Clang C++ - 10.27182 Clang C++ (alt) паралел. - 11.2052 Clang C++ (alt) паралел.+SIMD - 18 Видно, что параллельный код не генерируется, только однопоточный. SIMD значительно ухудшает производительность. Текст программы в cpp/subset_par. ------- Для сравнения проверим скорость работы с вектором когда доступ к его элементам осуществляется через конструкцию for (element : container ): Код:
Результаты в секундах: GNU C++ (alt) - 14.782 GNU C++ - 18.32765 Clang C++ - 18.3533 Clang C++ (alt) опция -O3 - 19.483 Clang C++ (alt) опция -O2 - 19.9807 Clang C++ (alt) опция -O или -O1 или без оптимиз. - завис. В Debian'е оба компилятора не смогли произвести оптимизацию. В ALT GNU C++ хорошо соптимизировал на уровне скорости статического массива, а Clang C++ не смог, и даже сгенерировал ошибочный код при некоторых опциях. -------- Соберём все результаты хронометража вместе: Контейнер (итераторы и алгоритмы STL) - 10-11 сек. Статический массив - 14 сек. Контейнер ( for each ) - 14 сек. Динамический массив - 15 сек. Результаты для C++: 1. Получается что для работы с одномерными массивами в C++ надо использовать vector, так будет надёжнее и быстрее, причём обязательно в стиле функционального программирования (через итераторы, замыкания, предикаты). 2. Пытаться ускорить обработку при помощи параллельный алгоритмов из STL и SIMD не стоит, компиляторы пока не готовы генерировать оптимальный код. 3. В работе компилятора Clang C++ 17 в ALT Linux 10 обнаружены ошибки. Также ошибки обнаружены в отладчике lldb 17 и компоновщике GNU ld, библиотеке GTK+ 3. |
![]() |
![]() |
![]() |
#3 | |
Просветитель
Участник клуба
Регистрация: 26.12.2012
Сообщений: 1,844
|
![]() Цитата:
Сообщения на форумах иногда бывают полезны не тем, что задумано автором, да. ![]()
В разработке: воспроизводственный контур ИТ
|
|
![]() |
![]() |
![]() |
Опции темы | Поиск в этой теме |
![]() |
||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Сравнение языков по скорости | DeepFlake | Общие вопросы по программированию, компьютерный форум | 29 | 20.08.2024 17:18 |
Коэффициенты в массивах | 9398 | Visual C++ | 0 | 12.02.2016 13:50 |
Сравнение последовательности чисел с часть самой себя | Tolyman | Помощь студентам | 19 | 12.08.2011 15:20 |
Сравнение значений в 2 массивах | Verano naranjo | Microsoft Office Excel | 10 | 01.12.2010 11:49 |
Часть фона одним цветом а другая часть другим (без таблиц). | Lanselot | HTML и CSS | 4 | 25.04.2008 18:41 |