Spec-Zone.ru › Haskell 8

7.3. Оптимизация (улучшение кода)

Параметры -O* задают удобные «пакеты» флагов оптимизации; параметры -f* , описанные позже, задают отдельные оптимизации, которые нужно включить/выключить; параметры -m* задают специфичные для машины оптимизации, которые нужно включить/выключить.

Большинство из этих параметров — булевы и имеют варианты для включения и выключения (начинающиеся с префикса no-). Например, -fspecialise включает специализацию, а -fno-specialise её отключает. Если на командной строке появляются несколько флагов для одного параметра, они обрабатываются слева направо. Например, -fno-specialise -fspecialise включит специализацию.

Важно отметить, что флаги -O* примерно эквивалентны комбинациям флагов -f*. По этой причине, эффект флагов -O* и -f* зависит от порядка их появления на командной строке.

Например, рассмотрим пример -fno-specialise -O1. Несмотря на то, что -fno-specialise присутствует в командной строке, специализация всё равно будет включена. Это потому, что -O1 подразумевает -fspecialise, переопределяя предыдущий флаг. В противоположность этому, -O1 -fno-specialise будет компилироваться без специализации, как и ожидалось.

7.3.1. -O*: удобные «пакеты» флагов оптимизации.

Существует множество параметров, влияющих на качество кода, генерируемого GHC. У большинства людей есть общая цель, например, «Компилировать быстро» или «Сделать мою программу быстрой, как молния». Следующие «пакеты» оптимизаций (или их отсутствие) должны быть достаточными.

Обратите внимание, что более высокие уровни оптимизации приводят к большему межмодульному оптимизации, что может повлиять на то, сколько вашей программы нужно перекомпилировать при внесении изменений. Это одна из причин придерживаться отсутствия оптимизации при разработке кода.

Не указан параметр типа ``-O*``: Это означает «Пожалуйста, скомпилируйте быстро; я не слишком забочусь о качестве скомпилированного кода». Так, например, ghc -c Foo.hs

-O0

Означает «выключить всю оптимизацию», возвращаясь к тем же настройкам, что и если не было указано никаких параметров -O. Указание -O0 может быть полезно, если, например, make уже вставил -O в командную строку.

-O
-O1

Означает: «Сгенерировать качественный код без чрезмерных затрат времени». Таким образом, например: ghc -c -O Main.lhs

-O2

Означает: «Применить все безопасные оптимизации, даже если это приведёт к значительному увеличению времени компиляции».

Избегаемые «опасные» оптимизации — те, которые могут ухудшить время выполнения или потребление памяти, если вам не повезёт. Обычно они включаются или выключаются индивидуально.

-O⟨n⟩

Любой -On, где n > 2, эквивалентен -O2.

Мы не используем флаг -O* в повседневной работе. Мы используем -O для достижения приемлемой скорости; например, когда мы хотим что-то измерить. Когда мы хотим добиться максимального результата, мы склонны использовать -O2 (и делаем много кофе-пауз).

Самый простой способ понять, что -O (и т.д.) «действительно означают», — это запустить с -v и полюбоваться результатом.

7.3.2. -f*: независимые от платформы флаги

Эти флаги включают и выключают отдельные оптимизации. Флаги, помеченные как включенные по умолчанию, включены параметром -O, поэтому вам, вероятно, не придётся устанавливать ни один из них явно. Флаг -fwombat может быть отменён, сказав -fno-wombat.

-fcase-merge
По умолчанию

включено

Объединить вложенные выражения case, которые анализируют одну и ту же переменную. Например,

case x of
   Red -> e1
   _   -> case x of
            Blue -> e2
            Green -> e3

Преобразуется в,

case x of
   Red -> e1
   Blue -> e2
   Green -> e2
-fcase-folding
По умолчанию

включено

Разрешить свёртку констант в выражениях case, которые анализируют некоторые примитивные операции: Например,

case x `minusWord#` 10## of
   10## -> e1
   20## -> e2
   v    -> e3

Преобразуется в,

case x of
   20## -> e1
   30## -> e2
   _    -> let v = x `minusWord#` 10## in e3
-fcall-arity
По умолчанию

включено

Включить анализ арности вызовов.

-fexitification
По умолчанию

включено

Включает вынесение точек выхода из рекурсивных функций.

-fcmm-elim-common-blocks
По умолчанию

включено

Включает оптимизацию удаления общих блоков в генераторе кода. Эта оптимизация пытается найти одинаковые блоки Cmm и удалить дубликаты.

-fcmm-sink
По умолчанию

включено

Включает проход погружения в генераторе кода. Эта оптимизация пытается найти одинаковые блоки Cmm и удалить дубликаты. Также она пытается переместить определения переменных ближе к местам их использования. Кроме того, она встраивает простые выражения, такие как литералы или регистры.

-fasm-shortcutting
По умолчанию

выключено

Включает обход на этапе сборки кода генератора. Проще говоря, обход означает, что если блок инструкций A состоит только из безусловного перехода, мы заменяем все переходы к A переходами к преемнику A.

Это в основном делается во время проходов Cmm. Однако это может пропустить частные случаи. Поэтому в -O2 мы запускаем проход ещё раз на стадии asm, чтобы поймать эти случаи.

-fblock-layout-cfg
По умолчанию

выключено, но включено с -O.

Новый алгоритм учитывает все исходящие края базового блока для расположения кода вместо только последней инструкции перехода. Он также строит граф потока управления для функций, пытается найти горячие пути кода и расположить их последовательно, что приводит к лучшей загрузке кэша и производительности.

Ожидается, что это улучшит производительность в среднем, но фактическое различие в производительности может меняться.

Если вы найдёте случаи существенного снижения производительности, которые можно отследить до очевидно плохого расположения кода, пожалуйста, откройте запрос.

-fblock-layout-weights

Этот флаг — для продвинутых пользователей. Главная цель этого флага — упростить отладку и настройку нового алгоритма расположения кода. Нет гарантии, что значения, дающие лучшие результаты сейчас, не ухудшат их в следующем выпуске.

Если вы считаете, что ваш код заслуживает изменения этих настроек, проконсультируйтесь с исходным кодом для значений по умолчанию и документации. Но я настоятельно не рекомендую этого.

-fblock-layout-weightless
По умолчанию

выключено

Когда не используется cfg-основанное расположение, расположение блоков определяется либо последним переходом в базовом блоке, либо самым тяжёлым исходящим ребром блока в cfg.

С этим флагом мы используем последнюю инструкцию перехода в блоках. Без этого флага старый алгоритм также использует самое тяжёлое исходящее ребро.

Если этот флаг включён и -fblock-layout-cfg выключен, расположение блоков ведёт себя так же, как в версиях 8.6 и ранее.

-fcpr-anal
По умолчанию

включено

Включить анализ CPR в анализаторе запросов.

-fcse
По умолчанию

включено

Включает оптимизацию удаления общих подвыражений. Выключение этого может быть полезно, если у вас есть некоторые unsafePerformIO выражения, которые вы не хотите объединять.

-fstg-cse
По умолчанию

включено

Включает оптимизацию удаления общих подвыражений в промежуточном языке STG, где она может объединять некоторые подвыражения, которые различаются по своим типам, но не по своему представлению.

-fdicts-cheap
По умолчанию

выключено

Очень экспериментальный флаг, который заставляет выражения со словарями-значениями казаться дешёвыми для оптимизатора.

-fdicts-strict
По умолчанию

выключено

Сделать словари строгими.

-fdmd-tx-dict-sel
По умолчанию

включено

Использовать специальный трансформатор запросов для селекторов словарей.

-fdo-eta-reduction
По умолчанию

включено

Применить эта-редукцию к лямбда-выражениям, если это избавляет от целой группы лямбда-выражений.

END_OF_DOCUMENT_MARKER
-fdo-lambda-eta-expansion
По умолчанию

включено

Расширять связывания let с помощью эта-расширения, чтобы увеличить их арность.

-feager-blackholing
По умолчанию

выключено

Обычно GHC чернит сущность только при переключении потоков. Этот флаг заставляет его делать это сразу после входа в сущность. См. Haskell on a shared-memory multiprocessor.

См. Параметры компиляции для параллелизма SMP для обсуждения его использования.

-fexcess-precision
По умолчанию

выключено

При задании этого параметра промежуточные значения с плавающей точкой могут иметь большую точность/диапазон, чем конечный тип. Обычно это хорошо, но некоторые программы могут полагаться на точную точность/диапазон Float/Double значений и не должны использовать этот параметр для компиляции.

Обратите внимание, что генератор кода для 32-битных x86 поддерживает режим сверхточной точности, поэтому ни -fexcess-precision ни -fno-excess-precision не имеют никакого эффекта. Это известный баг, см. Ошибки в GHC.

-fexpose-all-unfoldings
По умолчанию

выключено

Экспериментальный флаг для раскрытия всех развёртываний, даже для очень больших или рекурсивных функций. Это позволяет выполнять инлайнирование всех функций, в то время как GHC обычно избегает инлайнирования больших функций.

-ffloat-in
По умолчанию

включено

Перемещать связывания let внутрь, ближе к их месту связывания. См. Let-floating: moving bindings to give faster programs (ICFP’96).

Эта оптимизация перемещает связывания let ближе к месту их использования. Преимущество заключается в том, что это может предотвратить ненужное выделение памяти, если ветвь, в которой находится let, никогда не выполняется. Также это позволяет другим оптимизирующим этапам работать эффективнее, так как у них больше информации локально.

Однако эта оптимизация не всегда полезна (поэтому GHC применяет некоторые эвристики, чтобы решить, когда её применять). Детали усложняются, но простой пример заключается в том, что часто бывает выгодно перемещать связывания let наружу, чтобы несколько связываний let можно было сгруппировать в одно больше связывание let, эффективно объединяя их выделение и помогая сборщику мусора и аллокатору.

-ffull-laziness
По умолчанию

включено

Запустить полную оптимизацию ленивости (также известную как let-floating), которая перемещает связывания let за пределы окружающих лямбда-выражений, надеясь, что таким образом они будут вычисляться реже. См. Let-floating: moving bindings to give faster programs (ICFP’96). Полная ленивость увеличивает совместное использование, что может привести к увеличению резидентности памяти.

Примечание

GHC не реализует полную ленивость. Несмотря на то, что оптимизация полной ленивости GHC позволяет выполнить некоторые преобразования, которые выполняла бы полностью ленивая реализация (например, извлечение повторяющихся вычислений из циклов), эти преобразования не применяются последовательно, поэтому не полагайтесь на них.

-ffun-to-thunk
По умолчанию

выключено

Worker-wrapper удаляет неиспользуемые аргументы, но обычно мы не удаляем их все, чтобы не превратить замыкание функции в сущность, что, возможно, создаст утечку памяти и/или нарушит инлайнирование. Этот флаг позволяет worker/wrapper удалять все лямбды значений.

-fignore-asserts
По умолчанию

включено

Приводит GHC к игнорированию использования функции Exception.assert в исходном коде (другими словами, переписывание Exception.assert p e в e (см. Утверждения).

-fignore-interface-pragmas
По умолчанию

выключено

Указывает GHC игнорировать всю неважную информацию при чтении файлов интерфейсов. То есть, даже если M.hi содержит информацию о развертывании или строгости для функции, GHC проигнорирует эту информацию.

-flate-dmd-anal
По умолчанию

выключено

Повторный запуск анализа спроса в конце потока упрощения. Мы обнаружили некоторые возможности для обнаружения строгости, которые раньше были не видны; и оптимизации, такие как -fspec-constr, могут создавать функции с неиспользуемыми аргументами, которые удаляются поздним анализом спроса. Улучшения скромные, как и стоимость. См. примечания на странице wiki.

-fliberate-case
По умолчанию

выключено, но включено с -O2.

Включить преобразование liberate-case. Это раскручивает рекурсивную функцию один раз в своём правом члене, чтобы избежать повторного анализа case свободных переменных. Это немного похоже на специализатора шаблонов вызова (-fspec-constr), но для свободных переменных вместо аргументов.

-fliberate-case-threshold=⟨n⟩
По умолчанию

2000

Установить порог размера для преобразования liberate-case.

-floopification
По умолчанию

включено

При включении этой оптимизации генератор кода преобразует все саморекурсивные насыщенные хвостовые вызовы в локальные переходы вместо вызовов функций.

-fllvm-pass-vectors-in-regs
По умолчанию

включено

Инструктирует GHC использовать встроенные векторные регистры платформы для передачи векторных аргументов при вызовах функций. Как и вся поддержка векторов, это требует -fllvm.

-fmax-inline-alloc-size=⟨n⟩
По умолчанию

128

Установить максимальный размер выделения инлайновых массивов до n байт. GHC выделит не закреплённые массивы со статически известным размером в текущем блоке выделения памяти, если они не больше n байт, игнорируя переполнение GC.

-fmax-inline-memcpy-insns=⟨n⟩
По умолчанию

32

Инлайнировать вызовы memcpy , если они сгенерируют не более ⟨n⟩ псевдоинструкций.

-fmax-inline-memset-insns=⟨n⟩
По умолчанию

32

Инлайнировать вызовы memset , если они сгенерируют не более n псевдоинструкций.

-fmax-relevant-binds=⟨n⟩
По умолчанию

6

В сообщениях об ошибках тип-чекер иногда отображает фрагмент окружения типов, но только до определённого максимального числа, заданного этим флагом. Выключение с -fno-max-relevant-binds даёт неограниченное число. Синтаксически верхнеуровневые связывания обычно также исключаются (поскольку их может быть много), но -fno-max-relevant-binds включает и их.

-fmax-uncovered-patterns=⟨n⟩
По умолчанию

4

Максимальное число несопоставленных шаблонов, которое будет показано в предупреждениях, генерируемых -Wincomplete-patterns и -Wincomplete-uni-patterns.

-fmax-simplifier-iterations=⟨n⟩
По умолчанию

4

Устанавливает максимальное число итераций для упростителя.

-fmax-worker-args=⟨n⟩
По умолчанию

10

Если у работника столько аргументов, больше их не будет распаковываться.

-fno-opt-coercion
По умолчанию

оптимизация coercion включена.

Отключить оптимизатор coercion.

-fno-pre-inlining
По умолчанию

прединлайнирование включено

Отключить прединлайнирование.

-fno-state-hack
По умолчанию

включен режим «state hack»

Отключить «state hack», благодаря которому любая лямбда с маркером State# в качестве аргумента считается одноэлементной, следовательно, вложение кода внутри неё допустимо. Это может улучшить производительность кода с использованием монады IO и ST, но существует риск уменьшения совместного использования.

-fomit-interface-pragmas
По умолчанию

Включено по умолчанию, если указано -O0, в противном случае выключено.

Указывает GHC опустить всю неважную информацию из файла интерфейса, сгенерированного для компилируемого модуля (например, M). Это означает, что модуль, импортирующий M, увидит только типы экспортируемых функций M, но не их развертывания, информацию о строгости и т. д. Таким образом, например, никакая функция, экспортируемая из M, не будет встроена в импортирующий модуль. Преимущество заключается в том, что модулям, импортирующим M, потребуется рекомпилироваться реже (только при изменении типа экспорта M, а не при изменении его реализации).

-fomit-yields
По умолчанию

указаны точки yield

Указывает GHC опустить проверки кучи, когда не происходит выделение памяти. Хотя это улучшает размер двоичного файла примерно на 5 %, это также означает, что потоки, выполняемые в узких циклах без выделения памяти, не будут своевременно прерываться. Если важно всегда иметь возможность прерывать такие потоки, следует отключить эту оптимизацию. Также следует рассмотреть возможность повторной компиляции всех библиотек с выключенной этой оптимизацией, если вам необходимо гарантировать прерывистость.

-fpedantic-bottoms
По умолчанию

выключено

Заставляет GHC быть более точным в обращении с дном (но см. также -fno-state-hack). В частности, останавливает GHC от eta-расширения через выражение case, что хорошо для производительности, но плохо, если вы используете seq для частичных применений.

-fregs-graph
По умолчанию

выключено из-за ошибки производительности (#7679)

Применяется только в сочетании с генератором кода нативного кода. Используйте алгоритм выделения регистров с окраской графов для выделения регистров в генераторе кода нативного кода. По умолчанию GHC использует более простой и быстрый линейный алгоритм выделения регистров. Недостатком является то, что линейный алгоритм выделения регистров обычно генерирует худший код.

Обратите внимание, что алгоритм выделения регистров с окраской графов является немного экспериментальным и может не удастся при столкновении с кодом с высокой нагрузкой на регистры #8657.

-fregs-iterative
По умолчанию

выключено

Применяется только в сочетании с генератором кода нативного кода. Используйте итеративный алгоритм коалиции графа с окраской графов для выделения регистров в генераторе кода нативного кода. Это тот же алгоритм выделения регистров, что и у -fregs-graph, но также включает итеративную коалицию при выделении регистров.

-fsimplifier-phases=⟨n⟩
По умолчанию

2

Устанавливает количество фаз для упростителя. Игнорируется при -O0.

-fsimpl-tick-factor=⟨n⟩
По умолчанию

100

Оптимизатор GHC может разойтись, если вы напишете правила переписывания (Правила переписывания), которые не завершаются, или (менее удовлетворительно) если вы используете рекурсию через типы данных (Ошибки в GHC). Чтобы избежать попадания компилятора в бесконечный цикл, оптимизатор использует «счетчик тактов» и останавливает встраивание и применение правил переписывания, когда этот счетчик превышен. Предел установлен как кратное размеру программы, поэтому у больших программ больше тактов. Флаг -fsimpl-tick-factor позволяет изменить множитель. По умолчанию значение 100; числа больше 100 дают больше тактов, а числа меньше 100 — меньше.

Если счетчик тактов истекает, GHC суммирует выполненные шаги упростителя; вы можете использовать -fddump-simpl-stats для получения более подробного списка. Обычно это довольно точно определяет цикл, поскольку некоторые числа очень велики.

-fspec-constr
По умолчанию

выключено, но включено с помощью -O2.

Включить специализацию шаблона вызова; см. Специализация шаблона вызова для программ Haskell.

Эта оптимизация специализирует рекурсивные функции в соответствии с «формами» их аргументов. Лучше всего это объяснить на примере, поэтому рассмотрим:

last :: [a] -> a
last [] = error "last"
last (x : []) = x
last (x : xs) = last xs

В этом коде, как только мы пройдём начальную проверку на пустой список, мы знаем, что в рекурсивном случае это соответствие шаблонов избыточно. Поэтому -fspec-constr преобразует приведенный выше код в:

last :: [a] -> a
last []       = error "last"
last (x : xs) = last' x xs
    where
      last' x []       = x
      last' x (y : ys) = last' y ys

Кроме того, избегание ненужного сопоставления шаблонов, также помогает избежать ненужного выделения. Это применяется, когда аргумент является строгим в рекурсивном вызове самому себе, но не при начальном входе. Создаётся строгая рекурсивная ветвь функции, подобная приведенному выше примеру.

Также возможно, что авторы библиотек могут указать GHC на выполнение специализации шаблона вызова очень агрессивно. Это необходимо для некоторых высокооптимизированных библиотек, где мы можем захотеть специализировать независимо от количества специализаций или размера кода. В качестве примера рассмотрим упрощённый случай использования из библиотеки vector.

import GHC.Types (SPEC(..))

foldl :: (a -> b -> a) -> a -> Stream b -> a
{-# INLINE foldl #-}
foldl f z (Stream step s _) = foldl_loop SPEC z s
  where
    foldl_loop !sPEC z s = case step s of
                            Yield x s' -> foldl_loop sPEC (f z x) s'
                            Skip       -> foldl_loop sPEC z s'
                            Done       -> z

Здесь, после того, как GHC встроит тело foldl в точку вызова, он выполнит очень агрессивную специализацию шаблона вызова для foldl_loop из-за использования SPEC в аргументе тела цикла. SPEC из GHC.Types специально распознаётся компилятором.

(Примечание: крайне важно использовать seq или шаблон с указанием на строгость для аргумента SPEC!)

В частности, после встраивания это позволит напрямую передать f в тело цикла, что позволит сильно специализировать рекурсивные случаи.

-fspec-constr-keen
По умолчанию

выключено

Если этот флаг включен, специализация шаблона вызова будет специализировать вызов (f (Just x)) с явным аргументом конструктора, даже если аргумент не проверяется в теле функции. Иногда это полезно; например, аргумент может быть передан другой функции, которая сама может быть специализирована.

-fspec-constr-count=⟨n⟩
По умолчанию

3

Устанавливает максимальное количество специализаций, которые будут созданы для любой функции преобразованием SpecConstr.

-fspec-constr-threshold=⟨n⟩
По умолчанию

2000

Устанавливает пороговое значение размера для преобразования SpecConstr.

-fspecialise
По умолчанию

включено

Специализировать каждую функцию, перегруженную типом класса, определённую в этом модуле, для типов, в которых она вызывается в этом модуле. Если установлен -fcross-module-specialise, импортированные функции, имеющие прагму INLINABLE (Прагма INLINABLE), также будут специализированы.

-fspecialise-aggressively
По умолчанию

выключено

По умолчанию специализируются только методы типа класса и методы, помеченные INLINABLE или INLINE. Этот флаг будет специализировать любую перегруженную функцию независимо от размера, если её развертывание доступно. Этот флаг не включен в уровень оптимизации, так как может значительно увеличить размер кода. Его можно использовать совместно с -fexpose-all-unfoldings, если вы хотите убедиться, что все вызовы специализированы.

-fcross-module-specialise
По умолчанию

включено

Специализировать INLINABLE (Прагма INLINABLE) функции, перегруженные типом класса, импортированные из других модулей, для типов, в которых они вызываются в этом модуле. Обратите внимание, что специализация должна быть включена (флагом -fspecialise) для того, чтобы это имело какой-либо эффект.

-flate-specialise
По умолчанию

выключено

Выполняет другой этап специализации в конце оптимизационной цепочки. Это может выявить возможности специализации, которые возникли на предыдущем этапе специализации или в результате другого встраивания.

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

-fsolve-constant-dicts
По умолчанию

включено

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

Например:

class M a b where m :: a -> b

type C a b = (Num a, M a b)

f :: C Int b => b -> Int -> Int
f _ x = x + 1

Тело f требует экземпляр Num Int. Мы могли бы решить это ограничение из контекста, потому что у нас есть C Int b, который предоставляет нам решение для Num Int. Однако, мы часто можем создавать гораздо лучший код, напрямую решая для доступного Num Int словаря, который у нас может быть под рукой. Это устраняет потенциально много уровней косвенности и, что очень важно, позволяет запускать другие оптимизации, так как словарь будет статически известен, и функции выбора могут быть встроены.

Оптимизация также работает для GADTs, которые связывают словари. Если мы статически знаем, какой словарь класса нам нужен, то мы решим его напрямую, а не косвенно, используя тот, что передан во время выполнения.

-fstatic-argument-transformation
По умолчанию

выключено

Включить статическую трансформацию аргументов, которая преобразует рекурсивную функцию в нерекурсивную с локальным рекурсивным циклом. См. главу 7 диссертации Андре Сантоса https://www.microsoft.com/en-us/research/publication/compilation-transformation-non-strict-functional-languages/.

-fstg-lift-lams
По умолчанию

включено

Включает оптимизацию позднего подъема лямбда-выражений в промежуточном языке STG. Это выборочно поднимает локальные функции на верхний уровень, преобразуя свободные переменные в параметры функции.

-fstg-lift-lams-known
По умолчанию

выключено

Разрешить превращение известных вызовов в неизвестные при выполнении позднего подъема лямбда-выражений. Это считается невыгодным, поэтому по умолчанию выключено.

-fstg-lift-lams-non-rec-args
По умолчанию

5

Создать функции без рекурсии на верхнем уровне с не более чем <n> параметрами во время выполнения позднего подъема лямбда-выражений. По умолчанию 5, количество доступных регистров параметров на x86_64.

-fstg-lift-lams-rec-args
По умолчанию

5

Создать рекурсивные функции на верхнем уровне с не более чем <n> параметрами во время выполнения позднего подъема лямбда-выражений. По умолчанию 5, количество доступных регистров параметров на x86_64.

-fstrictness
По умолчанию

включено

Включить анализатор строгости. Реализация описана в статье https://www.microsoft.com/en-us/research/wp-content/uploads/2017/03/demand-jfp-draft.pdf.

Анализатор строгости определяет, когда аргументы и переменные в функции могут быть обработаны «строго» (то есть они всегда оцениваются в функции в какой-то момент). Это позволяет GHC применять определенные оптимизации, такие как unboxing, которые в противном случае не применяются, так как они изменяют семантику программы, когда применяются к ленивым аргументам.

-fstrictness-before=⟨n⟩

Выполнить дополнительный анализ строгости перед фазой упрощения ⟨n⟩.

-funbox-small-strict-fields
По умолчанию

включено

Этот параметр вызывает распаковку всех полей конструкторов, которые помечены как строгие (т. е. «!») и размер представления которых меньше или равен размеру указателя, если это возможно. Он эквивалентен добавлению директивы UNPACK (см. директива UNPACK) к каждому строгому полю конструктора, которое удовлетворяет ограничению размера.

Например, поля конструкторов в следующих типах данных

data A = A !Int
data B = B !A
newtype C = C B
data D = D !C

все будут представлены одним значением Int# (см. Неупакованные типы и примитивные операции) при включённом -funbox-small-strict-fields.

Этот параметр менее радикален, чем -funbox-strict-fields; он редко ухудшает ситуацию. Если вы используете -funbox-small-strict-fields для включения распаковки по умолчанию, вы можете отключить её для определенных полей конструктора с помощью директивы NOUNPACK (см. директива NOUNPACK).

Обратите внимание, что для согласованности Double, Word64, и Int64 поля конструкторов распаковываются на 32-битных платформах, даже если они технически больше, чем указатель на этих платформах.

-funbox-strict-fields
По умолчанию

выключено

Этот параметр вызывает распаковку всех полей конструкторов, помеченных как строгие (т. е. !), если это возможно. Это эквивалентно добавлению директивы UNPACK к каждому строгому полю конструктора (см. директива UNPACK).

Этот параметр немного радикален: иногда он может ухудшить ситуацию. Лучше использовать селективное распаковку полей, используя директивы UNPACK. Альтернативой является использование -funbox-strict-fields для включения распаковки по умолчанию, но отключение её для определенных полей конструкторов с помощью директивы NOUNPACK (см. директива NOUNPACK).

Альтернативно, можно использовать -funbox-small-strict-fields, чтобы распаковывать только строгие поля, которые «маленькие».

-funfolding-creation-threshold=⟨n⟩
По умолчанию

750

Определяет максимальный размер, который GHC позволит функции разворачиваться. (Развертывание имеет «размер», который отражает стоимость с точки зрения «разбухания кода» при расширении (т. е. вставке) этого разворачивания в месте вызова. Более крупной функции будет присвоен больший размер.)

Последствия:

  1. ничего больше этого не будет вставлено (если нет директивы INLINE)
  2. ничего больше этого не будет выведено в файл интерфейса.

Увеличение этого значения скорее приведет к более длительному времени компиляции, чем к более быстрому коду. -funfolding-use-threshold=⟨n⟩ является более полезным.

-funfolding-dict-discount=⟨n⟩
По умолчанию

30

Насколько рьяно компилятор должен вставлять словари?

-funfolding-fun-discount=⟨n⟩
По умолчанию

60

Насколько рьяно компилятор должен вставлять функции?

-funfolding-keeness-factor=⟨n⟩
По умолчанию

1.5

Насколько рьяно компилятор должен вставлять функции?

-funfolding-use-threshold=⟨n⟩
По умолчанию

60

Это волшебная граница для разворачивания (вставки): функции меньшего размера будут развернуты в месте вызова, функции большего размера — нет. Вычисленная для функции величина размера зависит от двух вещей: фактического размера выражения минус любые скидки, которые применяются в зависимости от контекста, в который это выражение должно быть вставлено.

Разница между этим параметром и -funfolding-creation-threshold=⟨n⟩ заключается в том, что этот параметр определяет, будет ли определение функции вставлено в месте вызова. Другой параметр определяет, будет ли определение функции вообще сохранено для потенциальной вставки.

-fworker-wrapper

Включить преобразование worker-wrapper после прохождения анализа строгости. Подразумевается -O и -fstrictness. Отключено -fno-strictness. Включение -fworker-wrapper при отключенном анализе строгости (с помощью -fno-strictness) не имеет эффекта.

-fbinary-blob-threshold=⟨n⟩
По умолчанию

500000

Генератор нативного кода может либо поместить двоичные фрагменты (например, строковые литералы) в файл ассемблера (используя директивы ассемблера “.asciz” или “.string”), либо поместить их как двоичные данные во временный файл, который затем включается ассемблером (используя директиву ассемблера “.incbin”).

Этот флаг устанавливает размер (в байтах) порог, выше которого используется второй подход. Вы можете полностью отключить второй подход, установив порог в 0.

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/8.10.2/docs/html/users_guide/using-optimisation.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API