Если я правильно помню курс по компиляторам, типичный компилятор имеет следующую упрощенную схему:
- Лексический анализатор сканирует (или вызывает некоторую функцию сканирования) исходный код посимвольно
- Строка входных символов проверяется на соответствие словаря лексем
- Если лексема действительна, она классифицируется как токен, которому она соответствует
- Парсер проверяет синтаксис комбинации токенов; токен за токеном .
Теоретически возможно разделить исходный код на четверти (или любой знаменатель) и многопоточность процесса сканирования и анализа? Существуют ли компиляторы, которые используют многопоточность?
multithreading
compiler
parsing
8protons
источник
источник
Ответы:
Большие программные проекты обычно состоят из множества модулей компиляции, которые могут быть скомпилированы относительно независимо, поэтому компиляция часто распараллеливается с очень грубой детализацией, вызывая компилятор несколько раз параллельно. Это происходит на уровне процессов ОС и координируется системой сборки, а не самим компилятором. Я понимаю, что это не то, что вы просили, но это наиболее близко к распараллеливанию в большинстве компиляторов.
Это почему? Ну, большая часть работы, которую выполняют компиляторы, не легко поддается распараллеливанию:
После этого становится немного легче. Проверка и оптимизация типов, а также генерация кода могут, в принципе, распараллеливаться на уровне детализации функций. Я до сих пор знаю мало, если какие-либо компиляторы делают это, возможно, потому что выполнение любой такой большой задачи одновременно довольно сложно. Вы также должны учитывать, что большинство крупных программных проектов содержат так много модулей компиляции, что подход «запускать несколько компиляторов параллельно» вполне достаточен для того, чтобы сохранить все ваши ядра занятыми (а в некоторых случаях даже целую ферму серверов). Кроме того, в больших задачах компиляции дисковый ввод-вывод может быть таким же узким местом, как и фактическая работа по компиляции.
Из всего сказанного я знаю компилятор, который распараллеливает работу генерации и оптимизации кода. Компилятор Rust может разделить внутреннюю работу (LLVM, которая фактически включает в себя оптимизации кода, которые традиционно считаются «промежуточными») между несколькими потоками. Это называется «единицами кода». В отличие от других возможностей распараллеливания, описанных выше, это экономично, потому что:
источник
Компиляция - это «смущающая параллель» проблема.
Никто не заботится о времени для составления одного файла. Люди заботятся о времени составления 1000 файлов. А для 1000 файлов каждое ядро процессора может скомпилировать по одному файлу за раз, поддерживая все ядра полностью занятыми.
Совет: «make» использует несколько ядер, если вы укажете ему правильную опцию командной строки. Без этого он будет компилировать один файл за другим в 16-ядерной системе. Это означает, что вы можете сделать компиляцию в 16 раз быстрее, изменив параметры сборки на одну строку.
источник