Si recuerdo el curso de mi compilador correctamente, el compilador típico tiene el siguiente esquema simplificado:
- Un analizador léxico escanea (o activa alguna función de escaneo) el código fuente carácter por carácter
- La cadena de caracteres de entrada se compara con el diccionario de lexemas para verificar su validez.
- Si el lexema es válido, se clasifica como el token al que corresponde
- El analizador valida la sintaxis de la combinación de tokens; ficha por ficha .
¿Es teóricamente factible dividir el código fuente en cuartos (o cualquier denominador) y multiprocesar el proceso de escaneo y análisis? ¿Existen compiladores que utilizan subprocesos múltiples?
multithreading
compiler
parsing
8protones
fuente
fuente
Respuestas:
Los grandes proyectos de software generalmente están compuestos por muchas unidades de compilación que se pueden compilar de manera relativamente independiente, por lo que la compilación a menudo se paraleliza con una granularidad muy aproximada invocando al compilador varias veces en paralelo. Esto sucede a nivel de los procesos del sistema operativo y es coordinado por el sistema de compilación en lugar del compilador propiamente dicho. Me doy cuenta de que esto no es lo que pediste, pero eso es lo más parecido a la paralelización en la mayoría de los compiladores.
¿Porqué es eso? Bueno, gran parte del trabajo que realizan los compiladores no se presta fácilmente a la paralelización:
Después de esto, se vuelve un poco más fácil. La verificación y optimización de tipos y la generación de código podrían, en principio, ser paralelas a la granularidad de la función. Todavía sé de pocos compiladores que hagan esto, tal vez porque hacer cualquier tarea tan grande al mismo tiempo es bastante desafiante. También debe tener en cuenta que los proyectos de software más grandes contienen tantas unidades de compilación que el enfoque "ejecutar un montón de compiladores en paralelo" es completamente suficiente para mantener todos sus núcleos ocupados (y en algunos casos, incluso una granja de servidores completa). Además, en tareas de compilación grandes, la E / S de disco puede ser un cuello de botella tanto como el trabajo real de compilación.
Dicho todo esto, conozco un compilador que paraleliza el trabajo de generación y optimización de código. El compilador Rust puede dividir el trabajo de back-end (LLVM, que en realidad incluye optimizaciones de código que tradicionalmente se consideran "de gama media") entre varios subprocesos. Esto se llama "unidades code-gen". En contraste con las otras posibilidades de paralelización discutidas anteriormente, esto es económico porque:
fuente
La compilación es un problema "vergonzosamente paralelo".
A nadie le importa el tiempo para compilar un archivo. La gente se preocupa por el momento de compilar 1000 archivos. Y para 1000 archivos, cada núcleo del procesador puede compilar felizmente un archivo a la vez, manteniendo todos los núcleos totalmente ocupados.
Consejo: "make" usa múltiples núcleos si le da la opción de línea de comando correcta. Sin eso, compilará un archivo tras otro en un sistema de 16 núcleos. Lo que significa que puede compilarlo 16 veces más rápido con un cambio de una línea a sus opciones de compilación.
fuente