Open Mazdaywik opened 5 years ago
crefal
(компиляция MRefal.r5.ref
)Начиная с версии 2.2.6 Рефал-5λ умеет декодировать и компилировать .rsl-файлы. А это значит, что можно сравнить производительность.
И без усреднения по N замерам очевидно, что Рефал-5λ работает в 3 раза медленнее.
Попробуем с оптимизациями.
Разницы немного. В обоих случаях ≈30 секунд времени уходит на копирование переменных.
Рассмотрим другой тест.
crefal
(компиляция себя)Другая программа, другой стиль её написания. Компиляция без оптимизаций выполняется в 4 раза медленнее, с оптимизациями — только в 3 раза.
TimeElapsed.OK.ref
Тест скопирован из каталога тестов совместимости.
Без оптимизаций работает примерно в 2 раза медленнее, с оптимизациями — почти догнало.
Вывод в том, что функция Mu
не при чём. Особенно, в последнем тесте, где бо́льшую часть времени выполняется цикл по открытой переменной. В предыдущих двух тестах немалую часть затрат составляли копирования переменных.
Впрочем, измерения, предложенные выше, сделать всё равно было бы полезно.
В заявке #264 приведён бенчмарк, также демонстрирующий проблемы с производительностью.
Ещё один бенчмарк, показывающий проблемы с производительностью:
https://groups.google.com/d/msg/refal/Bc429ngDJf4/ccUeOsbRBwAJ
Профилировка показывает, что треть времени уходит на функцию DoFirst
. Так что есть проблемы производительности из-за того, что библиотечные функции написаны на смеси Рефала и Си++.
В коммите ca96a728969fcbb6b8b8b3772045ea0560bd620b сделаны интересные замеры производительности. В частности, замечено, что сопоставление с повторной переменной на 15 % медленнее, чем копирование той же переменной.
Бенчмарк из комментария https://github.com/bmstu-iu9/refal-5-lambda/issues/194#issuecomment-552890284:
Скачать: primes-swi2.ref.txt.
Такой странный стиль кодирования (в частности, mul
и add
связан с тем, что программа была конвертирована с Рефала/2 Стеллецкого. И благодаря этому, служит хорошим бенчмарком на встроенные функции арифметики.
Вот так выглядит начало бенчмарка функций:
Библиотека собрана с RLC_FLAGS=-OCDPRS
.
Скачать: _profile_time.txt, _profile_count.txt.
Функция прикладной программы впервые появляется в 14-й строчке — остальное это реализация встроенных функций библиотеки. Причём 40 % времени занимает реализация функции First
(функция DoFirst
+ Sub-Digits
).
В самом компиляторе заметную долю времени занимает DoLenw
— реализация Lenw
, написанная на Рефале. Она вызывает Add-Digits
, которая, однако, вызывается не только из DoLenw
. Причина — для блоков, из которых формируется RASL, вычисляется их объём в байтах — для каждого байта вызывается в цикле DoLenw
, которая вызывает Add-Digits
.
Профиль выглядит так:
Режимы:
set RLC_FLAGS=-OCDPRS
set RLMAKE_FLAGS=
Скачать: _profile_time.txt, _profile_count.txt.
Так что надо оптимизировать Lenw
, First
и Last
, переписав их на C++. А в перспективе — вообще все функции арифметики. Но первые три выигрываю по соотношению затраты/результат в этих бенчмарках.
Замеры времени для предшествующих коммитов:
Профиль для программы primes-swi2.ref
теперь выглядит так:
Скачать: _profile_time.txt, _profile_count.txt.
Функция First
теперь последняя! Общее время работы программы уполовинилось. Но функции арифметики оптимизировать надо.
В случае самоприменимого компилятора «медленные» DoLenw
, Add-Digits
и IncCol
теперь даже не в третьей десятке! (Замеры: _profile_time.txt, _profile_count.txt.)
Первые по списку функции уже оптимизировать не так интересно:
NumberFromOpcode (0000) -> 1420.0 ms (4.60 %, += 4.60 %) rel step time 5.55
DoGenSubst (0177) -> 1001.0 ms (3.24 %, += 7.84 %) rel step time 21.46
Map (9549) -> 950.0 ms (3.08 %, += 10.92 %) rel step time 2.82
Map (4746) -> 759.0 ms (2.46 %, += 13.38 %) rel step time 1.41
DoMapAccum (8023) -> 640.0 ms (2.07 %, += 15.45 %) rel step time 1.12
GenCommand-RASL (4746) -> 610.0 ms (1.98 %, += 17.43 %) rel step time 2.32
Apply (8023) -> 581.0 ms (1.88 %, += 19.31 %) rel step time 0.71
Apply (2191) -> 526.0 ms (1.70 %, += 21.01 %) rel step time 0.57
Close (0000) -> 516.0 ms (1.67 %, += 22.68 %) rel step time 1850.30
DoMapAccum (9549) -> 512.0 ms (1.66 %, += 24.34 %) rel step time 1.43
__Step-Drop (0000) -> 502.0 ms (1.63 %, += 25.97 %) rel step time 0.34
Функцию DoGenSubst
нужно переписывать — делать команды сопоставления функциональными (#204), остальные функции оптимизируются при прогонке или специализации, а также имеют небольшой вклад.
Замеры производительности к предыдущему коммиту (f2484e9):
Эта задача — подзадача для #185.
Выяснилось, что компилятор Рефала-05, собранный Рефалом-5λ, в три раза медленнее компилятора, собранного самим собой, и компилятора, собранного
refc
. И это не смотря на максимально доступные оптимизации (-OdPRC
).То, что обгоняет
refgo
, можно объяснить более оптимальным форматом языка сборки. Команды сопоставления функциональны, они не изменяют значения уже присвоенных ячеек стека, а инициализируют новые. В то время как в Рефале-5λ при каждом сопоставлении изменяется содержимое ячейки-диапазона.Но при этом Рефал-05 вообще не содержит никаких оптимизаций и его идеология языка сборки совпадает с идеологией в Рефале-5λ.
Можно предположить следующие причины:
vm->ref(descr)
.Mu
(в силу особенностей языка) и она активно используется. Например, в кодогенераторе инструкции формируются путём косвенного вызова их тегов в цикле. И, возможно, за счёт дешевизныMu
Рефал-05 обгоняетrefc
+refgo
.<__Step-Start>
и<__Step-End>
Используется неоптимальное построение результатных выражений, а именно, без учёта последовательного распределения строящихся элементов и с проверками успешности команд аллокации.
В Рефале-5λ
Mu
не оптимизирована. Мало того, что она написана на Рефале с условиями и несколькими вспомогательными функциями, так ещё и сам поиск имени достаточно тяжеловесен.Что нужно сделать:
[ ] Замерить время без использования функции
Mu
— конвертировать программу на Рефале-05 в Рефал-5λ, заменив все идентификаторыFunc
на указатели&Func
и вызовы<Mu s.F …>
на непосредственный вызов<s.F …>
. Для этого можно написать препроцессор на Рефале-05, тем более что Рефал-05 декларируется как язык для написания таких инструментальных средств.В результате получится программа, семантически идентичная Рефалу-05, а значит, сравнение будет честнее.