Se eu me lembro corretamente do curso dos compiladores, o compilador típico tem o seguinte esquema simplificado:
- Um analisador lexical verifica (ou ativa alguma função de verificação) o código - fonte caractere por caractere
- A cadeia de caracteres de entrada é comparada com o dicionário de lexemas quanto à validade
- Se o léxico for válido, ele será classificado como o token ao qual corresponde
- O analisador valida a sintaxe da combinação de tokens; token por token .
É teoricamente viável dividir o código-fonte em quartos (ou qualquer que seja o denominador) e multithread o processo de digitalização e análise? Existem compiladores que utilizam multithreading?
multithreading
compiler
parsing
8protons
fonte
fonte
Respostas:
Projetos de software grandes geralmente são compostos de muitas unidades de compilação que podem ser compiladas de forma relativamente independente e, portanto, a compilação geralmente é paralelizada com uma granularidade muito grosseira, invocando o compilador várias vezes em paralelo. Isso acontece no nível dos processos do SO e é coordenado pelo sistema de compilação, e não pelo compilador propriamente dito. Sei que não foi o que você pediu, mas é a coisa mais próxima da paralelização na maioria dos compiladores.
Por que é que? Bem, grande parte do trabalho que os compiladores fazem não se presta à paralelização facilmente:
Depois disso, fica um pouco mais fácil. A verificação e a otimização do tipo e a geração de código podem, em princípio, ser paralelas à granularidade da função. Ainda conheço poucos ou nenhum compilador fazendo isso, talvez porque fazer qualquer tarefa desse tamanho ao mesmo tempo seja bastante desafiador. Você também deve considerar que a maioria dos grandes projetos de software contém tantas unidades de compilação que a abordagem "executar vários compiladores em paralelo" é totalmente suficiente para manter todos os seus núcleos ocupados (e, em alguns casos, até um farm de servidores inteiro). Além disso, em grandes tarefas de compilação, a E / S do disco pode ter tanto gargalo quanto o trabalho real de compilação.
Tudo isso dito, eu sei de um compilador que paralela o trabalho de geração e otimização de código. O compilador Rust pode dividir o trabalho de back-end (LLVM, que na verdade inclui otimizações de código que são tradicionalmente consideradas "meio-fim") entre vários threads. Isso é chamado de "unidades de geração de código". Em contraste com as outras possibilidades de paralelização discutidas acima, isso é econômico porque:
fonte
A compilação é um problema "embaraçosamente paralelo".
Ninguém se importa com a hora de compilar um arquivo. As pessoas se preocupam com o tempo de compilar 1000 arquivos. E para 1000 arquivos, cada núcleo do processador pode compilar um arquivo de cada vez, mantendo todos os núcleos totalmente ocupados.
Dica: "make" usa vários núcleos se você der a opção de linha de comando correta. Sem isso, ele compilará um arquivo após o outro em um sistema com 16 núcleos. O que significa que você pode compilar 16 vezes mais rápido com uma alteração de uma linha nas suas opções de compilação.
fonte