Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Версия 3.4 #361

Draft
wants to merge 205 commits into
base: master
Choose a base branch
from
Draft

Версия 3.4 #361

wants to merge 205 commits into from

Conversation

Mazdaywik
Copy link
Member

@Mazdaywik Mazdaywik commented Aug 1, 2021

В версию 3.4 войдут, прежде всего расширенные прогонка и специализация, написанные @Apakhov’ым и @VladisP’ом, этот код уже в master.

Данный pull request вливает:

Ранее специализация замыкания {{ &F CONTENT }} осуществлялась как
специализация фиктивного вызова <F CONTENT e.@>. Оптимизатор строил новый
вызов <F@1 CONTENT′ e.@>, из которого восстанавливалось замыкание
{{ &F@1 CONTENT′ }}.

Добавлять и удалять фиктивную переменную e.@ было безопасно, т.к. она была
в позиции динамического параметра, позиция параметра не менялась (оставалась
последней) и во внутрь функции она не протекала.

Теперь же при специализации это имя может протечь внутрь экземпляра,
внутри экземпляра может оказаться другое замыкание, в контексте которого
будет переменная e.@. Добавление e.@ в конец вызовет конфликт имён.

----

В коде есть некоторый костыль, который проистекает из отсутствия поддержки
подавления предупреждений. Исходники намеренно собираются с -Werror,
а в данном коде было бы разумно явно добавить «подозрительную» (#290)
повторную переменную. Пришлось достигать эту проверку более громоздким
куском исходного кода.
Самоприменение выполняется в режиме

set RLMAKE_FLAGS=-X-OiDPRS
Ошибка была внесена в коммите 2042653 в рамках задачи #303.
До оптимизации после самоприменения в режиме:

set RLMAKE_FLAGS=-X-OiDPRS
call makeself.bat
set RLMAKE_FLAGS=-X-OiDS
call makeself.bat

со включённым профилем время работы составило 1590 секунд, где-то 50 %
времени ушло на проверку отношения Хигмана-Крускала.

В актуальной реализации время работы составило 575 секунд, отношение
Хигмана-Крускала занимает где-то около процента.

Подробности с логами профилировщика в issue.
Рекомендуется смотреть коммит с игнорированием пробельных символов.
Эта правка была закоммичена в предыдущем коммите по ошибке.
• Переименования функций,
• уточнения комментариев,
• изменение типа результата функции Solve-Clashes,
• удалена неиспользуемая функция IsFreeVariableSeq.
Ранее при построении дерева прогонки, из сужений для ветвей извлекались
имена используемых переменных. Теперь эти имена возвращаются функцией
Solve-Drive. На быстродействие это почти не повлияло.

Ранее:

ExtractVariables-Expr (0000) -> 11519.0 ms (2.64 %, += 21.06 %)
                       rel step time 0.67
ExtractVariables-Expr (0000) -> 13593437 (3.92 %, += 8.41 %)
                       rel step time 0.67

Теперь:

ExtractVariables-Expr (0000) -> 11687.0 ms (2.73 %, += 21.22 %)
                       rel step time 0.71
ExtractVariables-Expr (0000) -> 13442507 (3.87 %, += 8.34 %)
                       rel step time 0.71

Число шагов уменьшилось на 0,05 % (3,92−3,87), а доля времени даже
выросла.
Данная правка на время и число шагов функции SimplifyCoordinates-Expr,
вопреки ожиданиям, никак не повлияла.

Ранее:

Total time: 427.50000 s

SimplifyCoordinates-Expr (3646) -> 6957.0 ms (1.63 %, += 26.16 %)
                    rel step time 0.90
SimplifyCoordinates-Expr (3646) -> 6259417 (1.80 %, += 24.36 %)
                    rel step time 0.90

SimplifyCoordinates-Expr-Inner (3646) -> 6274.0 ms (1.47 %, += 29.18 %)
              rel step time 1.17
SimplifyCoordinates-Expr-Inner (3646) -> 4372638 (1.26 %, += 30.18 %)
              rel step time 1.17

Сейчас:

Total time: 422.06200 s

SimplifyCoordinates-Expr (5246) -> 6909.0 ms (1.64 %, += 28.27 %)
                    rel step time 0.90
SimplifyCoordinates-Expr (5246) -> 6222848 (1.81 %, += 24.66 %)
                    rel step time 0.90

Число шагов SimplifyCoordinates-Expr даже, почему-то, возросло.

Но SimplifyCoordinates-Expr-Inner больше нет, программа ускорилась
на сэкономленные ≈6 секунд. Понятно, что это однократный замер,
просто интересно совпало.
Этот лимит инкрементировался в рамках задач #251, #322, #340.
В коммите 286a098 классификация была неточная,
но к ошибкам это не приводило.
#359)

Файл OptTree-Drive-Expr.ref переименован для сохранения истории правок.
Содержимое лога для теста bloat-basic.ref (приложенного к заявке)
не изменилось за исключением вывода самой истории. Т.е. на данный
тест замена никак не повлияла.

На других примерах работу не испытывал.
Фактически, развёрнут последний виток цикла.
• Удалено промежуточное звено SpecCall-BuildSignature-***,
• функция SpecCall-CheckSignature выпала из цепочки и стала
  нерекурсивной (избыточные параметры удалены).
Экземпляры строятся как обычно, но при обнаружении зацикливания
более ранний экземпляр в истории также подменяется вызовом обобщённого
вроде

  Loop@3 {
    (e.0) t.1 t.2 e.3 = <Loop@8 (e.0) t.1 W S t.2 e.3>;
  }
Перемена нумерации позволяет тривиальным сигнатурам на дне истории
(сигнатурам псевдоэкземпляров Func@0) выглядеть в логеконсистентно
с последующими сигнатурамии Func@n, где нумерация начинается с 0.
Два автотеста недописаны (нет функции Go) и поэтому выключены
(переименованы в *._ref).

Случайно сгенерированный автотест, заваливший CI, сохранён и на нём
компилятор по-прежнему падает.

Смысл коммита — не потерять эти тесты. Когда проблема #362 будет
исправлена, тесты opt-tree-bloat-*._ref будут дописаны и включены.
Для специализации это очевидный рефакторинг, т.к. разметка выполняется
не более чем один раз в любом режиме компиляции. (Вообще, этот код
давно надо было упростить.)

Для прогонки это не рефакторинг, т.к. при прогонке экземпляров
содержимое лога будет немного другим.

Помимо непосредственного удаления кода «обновления» структур данных,
были сделаны некоторые простые рефакторинги в окружающем коде.
Ранее было обнаружено, что с новым алгоритмом специализации компилятор
в некоторых тестах увязает, и был добавлен грязный хак, ограничивающий
максимальное число экземпляров (54c28ca, #332).

Предыдущие два коммита стали строить дополнительные let-экземпляры, из-за
чего порог стал достигаться раньше и глубина оптимизации снизилась.
Поэтому потребовалось поднять порог.

Порог был поднят до 150 по двум причинам:

• В тесте saved-test-10_Mon-Aug-23-21-51-16-UTC-2021.ref (81667ba)
  на пороге в 100 экземпляров условие остановки не срабатывает
  (до let-экземпляров срабатывало). Опытным путём было выяснено,
  что условие установки срабатывает на пороге между 140 и 145, было
  выбрано круглое значение.

  Заметим, что этот тест в текущем коммите проходит.

• Тест saved-test-77_14.08.2021_20-00-01,67-big.ref (41ce59e, #314),
  напротив, проходит только благодаря наличию этого лимита (на момент
  написания коммита 41ce59e не анализировалась проблема
  с непрохождением теста, просто был повышен порог). С лимитом 200
  тест не проходит, с лимитом 150 проходит.
Конкретная проблема предыдущего коммита была в том, что на вход финальной
прогонки экземпляров подавалось дерево с функцией Func*n, но при этом
функция Func в дереве могла отсутствовать. Для прогонщика это было
нарушением инварианта.

Исправление свелось к тому, что Func*n уже больше не подлежат финальной
прогонке, т.к. подлежат только экземпляры — функции с другим суффиксом @n.

Была и другая проблема (не проявлялась). Она была в том, что ранее
на финальном этапе выполнялась разметка всех функций для прогонки,
а функции с именами вида Func*n прогонялись уже не адекватно,
т.к. предложения в них уже могли быть размножены, и прогонка одного
предложения приводила бы к неправильной функции Func*‹n+1›.
Обнаружилась проблема, связанная с исчерпанием числа шагов на тесте
varcopy-fail.ref. Я предположил, что проблема в лишних let-экземплярах,
которые съедают один шаг. Поэтому всё-таки реализовал #230 в рамках
исправления #362.

Как оказалось, реализовать поддержку активных вызовов оказалось проще,
чем я думал ранее.
Проблему прекрасно описывает обширный комментарий в коде.

Тест varcopy-fail.ref переименован, т.к. он выявлял проблему, решённую
в коде.
Теперь специализация одного вызова может порождать несколько экземпляров,
а значит, сравнение на точное значение может «перескочить».
TonitaN
TonitaN previously approved these changes Sep 30, 2021
Copy link
Member

@TonitaN TonitaN left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Совершенству нет предела. Скоро новый релиз?

@Mazdaywik
Copy link
Member Author

Совершенству нет предела. Скоро новый релиз?

Когда появится коммит, меняющий этот файл.

Но вообще, в конце комментария #362 (comment) поставлен вопрос, на который я бы хотел сначала ответить. Самому интересно, на сколько актуален сейчас этот проход. А так да, совершенству нет предела.

Предыдущий коммит d5847ba устранял падение компилятора, скрывая ошибку:
оптимизация просто переставала работать.
После вливания правок по #341 в FindErrors в Checker.ref увеличилась
потребность в памяти — дерево e.AST теперь копируется:

    <CheckScreening (e.WarningIds) (e.AST)>
    <CheckMultiScreening (e.WarningIds) (e.AST)>;

Поэтому пришлось повысить лимит для компиляции Library.ref
в соответствующей папке.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants