|
|
Регистрация Восстановить пароль |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
Опции темы | Поиск в этой теме |
29.08.2024, 11:56 | #1 |
Пользователь
Регистрация: 16.05.2024
Сообщений: 88
|
Сравнение языков на массивах. Часть 2
В сообщении "Сравнение языков на массивах. Часть 1" в этом разделе описывались программы на языке C++, а в этом сообщении будут рассматриваться программы на языке Ada. Язык Ada по возможностям и стилю программирования очень похож на C++, но более надёжный. Он применяется там, где цена ошибки высока. Так же как для С++, программы будут компилироваться и запускаться в двух операционных системах на основе Linux - Debian 10 и ALT Linux 10. Компилятор языка Ada - GNAT от компании AdaCore. В Debian GNAT версии 8.3, а в ALT - 10.3 .
Все программы компилировались с опцией оптимизации -O2 или -O3, а иначе скорость их работы становится позорно низкой. Если в результатах замеров времени никаких пометок - значит в Debian, если пометка (alt) - значит в ALT. В отличие от C++ в Ada есть run-time проверки, в том числе проверка индекса массива на выход из допустимого диапазона. Однако они реализованы достаточно эффективно и не сильно снижают производительность программ. В Ada так же будем проверять скорость работы со статическим массивом, динамическим массивом и массивом в типе-контейнере Vector. Тестовые массивы те же, один на 500000 элементов, второй на 50000. ---------- Массив в стеке выделяется в Ada несколько необычно, такого нет ни в одном языке. Во всех языках длина статического массива должна быть известна заранее, на этапе компиляции, то есть в Pascal'е нельзя так написать (и в C ): Код:
Код:
Код сравнения двух множеств на предмет вхождения одного множества в другое, когда множества представлены в виде статических массивов: Код:
Результаты замеров времени работы программы в секундах (среднее значение): GNAT - 13.66483 GNAT (alt) - 14.77729 В ALT почему-то все программы работают медленнее, хоть на каком языке написанные. Это система виновата, не компиляторы. Сравним эти данные с результатами замеров для языка C++ из моего предыдущего сообщения: Clang C++ - 14.02215 Clang C++ (alt) - 14.62863 GNU C++ (alt) - 14.6694 То есть Ada в Debian обогнал C++ несмотря на то, что в Ada run-time проверки. По крайней мере Ada не медленнее C++. Это очень хороший результат. ------ Динамический массив в языке Ada создаётся как в C++ и Pascal - вызывается оператор new, а уничтожается вызовом специальной функции. Отличие от C++ такое: в C++ для одиночных объектов память выделяется при помощи new, а для массивов - new []. При помощи оператора new нельзя создать массив потому что в язые C и С++ указатель на массив это то же самое, что указатель на первый элемент массива. То есть new создаст не массив, а только один элемент массива. А в Ada всё по-нормальному, оператор new может создавать как одиночные объекты, так и массивы. Код:
Выделение памяти под массивы из хипа: Код:
Освобождение динамической памяти производится функцией unchecked_deallocation, правда это функция с шаблоном типа, который надо освободить. Код проверки множеств для динамических массивов ничем не отличается от кода для статических массивов: Код:
Результаты замеров времени запуска в секундах: GNAT - 19.703419 GNAT (alt) - 20.8893 Видно, что для Ada замедление работы с динамическими массивами по сравнению со статическими гораздо больше чем для C++. Для Ada замедление на 46%, для С++ - на 7%. В Ada дольше происходит разыменование указателя и скрытая проверка индекса начинает тормозить. ------- Продолжение в следующем сообщении |
29.08.2024, 11:58 | #2 |
Пользователь
Регистрация: 16.05.2024
Сообщений: 88
|
В Ada, так же как в C++, есть разнообразные типы-контейнеры и функции для работы с ними. Но функции называются непривычно, все привыкли к iter, map, filter, take, drop, enumerate и т.д., а в Ada нет таких названий. Сами функции есть, но называются по-другому.
В Ada отсутствуют замыкания и функциональные объекты, но вместо них используют внутренние функции (функция внутри функции). Внутренняя функция имеет доступ к внешним переменным, как и замыкание. Дело в том, что замыкание может спровоцировать неправильную работу программы, если она захватит объект и будет работать с ним, а он через какое-то время уничтожится, замыкание это не заметит и будет ошибка. С внутренними функциями такого не будет. Типы-контейнеры являются настраиваемыми типами, то есть надо указывать тип элементов. Конкретизация вектора происходит так: Код:
typedef std::vector<long int> LongInteger_Vector; Заполняется вектор функцией set1.append() - это добавляет в конец. Поиск нужного элемента производится функцией set1.Find( el1 ). Вот код программы для векторов: Код:
Результаты запусков для векторов в секундах: GNAT - 13.6729 GNAT (alt) - 21.3264 В Debian программа на Ada отработала с той же скоростью, что и со статическим массивом (13 секунд), это хороший результат. В ALT версия GNAT более новая, но скорость работы как с динамическим массивом (20 секунд). Программа на С++ работает с векторами быстрее (10 секунд). ------- Работа с вектром в стиле for each: Код:
Результаты: GNAT - 24.12821 GNAT (alt) - 38.6873 Очень медленно. -------- Соединим все результаты замеров для языка Ada вместе: Статический массив - 13.664 Динамический массив - 19.703 Вектор с алгоритмом - 13.6729 Вектор с for each - 24.12821 Напомню результаты для языка C++: Вектор (алгоритм STL) - 10-11 сек. Статический массив - 14 сек. Вектор ( for each ) - 14 сек. Динамический массив - 15 сек. Выводы можно такие сделать для языка Ada: 1. Если массив небольшой и фиксированной длины, то можно разместить его в стеке. 2. Если массив большой или его длина может меняться в процессе работы, то размещать в Vector и работать с ним через встроенные функции (не через for). 3. Версия компилятора GNAT, которая в ALT, производит медленный код при работе с типами-контейнерами, я подозреваю что это из чисто маркетинговых соображений, ведь GNAT - это демо-версия коммерческого продукта GNAT Pro. |
29.08.2024, 12:20 | #3 |
Старожил
Регистрация: 15.02.2010
Сообщений: 15,757
|
|
29.08.2024, 12:36 | #4 | ||||
Старожил
Регистрация: 15.02.2010
Сообщений: 15,757
|
Цитата:
Можно Цитата:
Цитата:
Цитата:
И кроме ваших думок есть основания? Вы дизасмнули код? Вы сравниливерсии? |
||||
01.09.2024, 16:28 | #5 |
Пользователь
Регистрация: 16.05.2024
Сообщений: 88
|
Сравнение языков на массивах. Часть 3
Сейчас посмотрим как быстро работают с массивами программы на Free Pascal. Free Pascal - язык, используемый в визуальном RAD-инструменте Lazarus. Хотя на Lazarus'е можно сделать любую программу, но ускорение разработки происходит, в основном, только для GUI-программ (с графическим интерфейсом). Не совсем корректно сравнивать Free Pascal и С++, Ada, Java, потому что у них разные области применения, более правильно сравнивать Lazarus со своими конкурентами, тоже визуальными RAD-инструментами, например, с Gambas, KBasic, MonoDevelop.
Lazarus и Free Pascal производят неоднозначное впечатление. С одной стороны, вроде бы, это простые и удобные инструменты, позволяющие быстро создать программу, а с другой стороны, не всё в них удобно, программы получаются не слишком надёжные и медленно работающие. Например, при разработке GUI-программ самое важное - так расположить оконные элементы, чтобы они сами подстраивались под размер окна. Обычно это достигается использованием менеджеров раскладки (layout manager, arrangement), однако менеджеры раскладки удобно когда GUI пишешь в виде кода, и неудобно их использовать в визуальном редакторе окон, потому что приходится делать менеджер в менеджере и специальные настройки для некоторых ячеек. Поэтому в Lazarus'е в редакторе окон используются другие способы автоматической раскладки, которые гораздо удобнее для визуального создания GUI: первый на основе выравнивания (align), второй - на основе якорей (anchor). На практике приходится применять комбинацию из этих методов. Но проблема в том, что эти способы не так-то легко изучить, зато легко забыть, если не программировать в Lazarus'е постоянно. Free Pascal - странная смесь языков С и Java с паскалевским синтаксисом. По-умолчанию компилятор не создаёт в коде никаких run-time проверок (индекса, переполнения, стека), поэтому я их включил опциями для честного сравнения с другими языками. В Debian Free Pascal версии 3.0.4, в ALT Linux 10 - 3.2.2. ------- Я не смог найти способ разместить массив произвольного размера в стеке на Free Pascal'е, поэтому статический массив фиксированного размера сделал как глобальную переменную. Код:
Результаты замеров в секундах: Free Pascal - 49.4955 Free Pascal (alt) - 51.361 ------- Динамический массив создавать при помощи функции new можно только фиксированного размера: Код:
Результаты: Free Pascal - 51.9165 Free Pascal (alt) - 64.342 |
01.09.2024, 16:31 | #6 |
Пользователь
Регистрация: 16.05.2024
Сообщений: 88
|
Сравнение языков на массивах. Часть 3, продолжение
Если надо создать динамический массив произвольного размера, то следует использовать функции GetMem, FreeMem, ReallocMem, однако в этом случае не производится run-time проверка индекса массива на диапазон.
Код:
Результаты: Free Pascal - 36.8815 Free Pascal (alt) - 38.438 Почему в этом случае скорость не как у С, ведь проверка индекса на диапазон не производится? Оказывается производится проверка индекса на переполнение. ------ Free Pascal похож на Java ещё тем, что в язык встроен объект-массив. Он является управляемым объектом (managed), то есть память освобождается автоматически. Объект-массив может в процессе работы программы менять размер и быть неровным. Код:
Результаты: Free Pascal - 89.4925 Free Pascal (alt) - 93.3365 Free Pascal (без проверки индекса) - 31.464 Free Pascal (alt) (без проверки индекса) - 32.849 Проверка индекса на вхождение в диапазон производится во Free Pascal'е неэффективно. ------- А что если в процессе работы программы необходимо добавлять/удалять/вставлять элеиенты в массиве по определённой позиции? Для этого есть класс-список, для которого произведена специализация. В пакете lazutils есть модуль IntegerList, а в нём готовые специализированные классы-списки для целых чисел: Код:
Код:
Результаты: Free Pascal - 166.3015 Free Pascal (alt) - 174.285 -------- |
01.09.2024, 16:32 | #7 |
Пользователь
Регистрация: 16.05.2024
Сообщений: 88
|
Сравнение языков на массивах. Часть 3, продолжение 2
Соберём все результаты для Free Pascal вместе:
Статический массив (фиксир.) - 49.4955 Динамический массив (фиксир.) - 51.9165 Динамический массив (произв., без проверки индекса) - 36.8815 Объект-массив - 89.4925 IntegerList - 166.3015 Что можно сказать здесь? Проверка индекса на диапазон производится неэффективно, а сам компилятор - туповатый. Но Free Pascal никогда и не позиционировали как инструмент для высокопроизводительных расчётов. Впрочем, если кому-то необходимо быстрые вычисления с 2-х, 3-х, 4-х мерными матрицами и векторами во Free Pascal, то в нём для этого есть модуль matrix. Также есть отдельные модули для работы с векторами и матрицами из чисел произвольной точности. |
Опции темы | Поиск в этой теме |
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Сравнение языков на массивах. Часть 1 | DeepFlake | Общие вопросы по программированию, компьютерный форум | 2 | 25.08.2024 18:05 |
Сравнение языков по скорости | DeepFlake | Общие вопросы по программированию, компьютерный форум | 29 | 20.08.2024 17:18 |
Сравнение последовательности чисел с часть самой себя | 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 |