Marca GNU

Compilar código en paralelo usando Make

Compilar código en paralelo usando Make

A quien le pregunte cómo crear software correctamente encontrará Make como una de las respuestas. En los sistemas GNU / Linux, GNU Make [1] es la versión de código abierto del Make original que se lanzó hace más de 40 años, en 1976. Realice trabajos con un Makefile: un archivo de texto sin formato estructurado con ese nombre que se puede describir mejor como el manual de construcción para el proceso de creación de software. El Makefile contiene una serie de etiquetas (llamadas objetivos) y las instrucciones específicas que se deben ejecutar para construir cada objetivo.

Simplemente hablando, Make es una herramienta de construcción. Sigue la receta de tareas del Makefile. Le permite repetir los pasos de forma automatizada en lugar de escribirlos en una terminal (y probablemente cometer errores al escribir).

El Listado 1 muestra un Makefile de ejemplo con los dos destinos "e1" y "e2", así como los dos destinos especiales "todos" y "limpio."Ejecutar" make e1 "ejecuta las instrucciones para el objetivo" e1 "y crea el archivo vacío uno. Ejecutar "make e2" hace lo mismo para el objetivo "e2" y crea el archivo vacío dos. La llamada de "make all" ejecuta las instrucciones para el objetivo e1 primero y e2 después. Para eliminar los archivos uno y dos creados previamente, simplemente ejecute la llamada "make clean."

Listado 1

todo: e1 e2
e1:
toca uno
e2:
toca dos
limpio:
rm uno dos

Ejecutando Hacer

El caso común es que usted escribe su Makefile y luego simplemente ejecuta el comando "make" o "make all" para construir el software y sus componentes. Todos los objetivos se construyen en orden en serie y sin paralelización. El tiempo total de construcción es la suma del tiempo que se requiere para construir cada objetivo.

Este enfoque funciona bien para proyectos pequeños, pero lleva bastante tiempo para proyectos medianos y grandes. Este enfoque ya no está actualizado ya que la mayoría de los cpus actuales están equipados con más de un núcleo y permiten la ejecución de más de un proceso a la vez. Con estas ideas en mente, analizamos si el proceso de construcción se puede paralelizar y cómo. El objetivo es simplemente reducir el tiempo de construcción.

Realizar mejoras

Hay algunas opciones que tenemos: 1) simplificar el código, 2) distribuir las tareas individuales en diferentes nodos de computación, construir el código allí y recopilar el resultado de allí, 3) construir el código en paralelo en una sola máquina, y 4) combine las opciones 2 y 3.

Opción 1) no siempre es fácil. Requiere la voluntad de analizar el tiempo de ejecución del algoritmo implementado y conocimiento sobre el compilador, i.mi., ¿Cómo traduce el compilador las instrucciones del lenguaje de programación en instrucciones del procesador?.

La opción 2) requiere acceso a otros nodos informáticos, por ejemplo, nodos informáticos dedicados, máquinas no utilizadas o menos utilizadas, máquinas virtuales de servicios en la nube como AWS o potencia informática alquilada de servicios como LoadTeam [5]. En realidad, este enfoque se utiliza para crear paquetes de software. Debian GNU / Linux usa la llamada red Autobuilder [17], y RedHat / Fedors usa Koji [18]. Google llama a su sistema BuildRabbit y está perfectamente explicado en la charla de Aysylu Greenberg [16]. distcc [2] es un compilador de C distribuido que le permite compilar código en diferentes nodos en paralelo y configurar su propio sistema de compilación.

La opción 3 usa la paralelización a nivel local. Esta puede ser la opción con la mejor relación costo-beneficio para usted, ya que no requiere hardware adicional como en la opción 2. El requisito para ejecutar Make en paralelo es agregar la opción -j en la llamada (abreviatura de -jobs). Esto especifica el número de trabajos que se ejecutan al mismo tiempo. La siguiente lista solicita que Make ejecute 4 trabajos en paralelo:

Listado 2

$ hacer --jobs = 4

Según la ley de Amdahl [23], esto reducirá el tiempo de construcción en casi un 50%. Tenga en cuenta que este enfoque funciona bien si los objetivos individuales no dependen unos de otros; por ejemplo, la salida del objetivo 5 no es necesaria para construir el objetivo 3.

Sin embargo, hay un efecto secundario: la salida de los mensajes de estado para cada objetivo Make parece arbitraria y ya no se pueden asignar claramente a un objetivo. El orden de salida depende del orden real de ejecución del trabajo.

Definir Hacer orden de ejecución

¿Hay declaraciones que ayuden a Make a comprender qué objetivos dependen unos de otros?? sí! El Makefile de ejemplo en el Listado 3 dice esto:

* para crear el objetivo "todos", ejecute las instrucciones para e1, e2 y e3

* el objetivo e2 requiere que el objetivo e3 se construya antes

Esto significa que los objetivos e1 y e3 se pueden construir en paralelo, primero, luego e2 sigue tan pronto como se completa la construcción de e3, finalmente.

Listado 3

todos: e1 e2 e3
e1:
toca uno
e2: e3
tocar dos
e3:
toca tres
limpio:
rm uno dos tres

Visualice las dependencias de Make

La herramienta inteligente make2graph del proyecto makefile2graph [19] visualiza las dependencias de Make como un gráfico acíclico dirigido. Esto ayuda a comprender cómo los diferentes objetivos dependen unos de otros. Make2graph genera descripciones de gráficos en formato de puntos que puede transformar en una imagen PNG usando el comando dot del proyecto Graphviz [22]. La convocatoria es la siguiente:

Listado 4

$ hacer todo -Bnd | make2graph | punto -Tpng -o gráfico.png

En primer lugar, se llama a Make con el objetivo "todos" seguido de las opciones "-B" para construir incondicionalmente todos los objetivos, "-n" (abreviatura de "-dry-run") para simular que se ejecutan las instrucciones por objetivo, y " -d ”(“ -debug ”) para mostrar información de depuración. La salida se canaliza a make2graph que canaliza su salida al punto que genera el gráfico del archivo de imagen.png en formato PNG.


El gráfico de dependencia de compilación para el listado 3

Más compiladores y sistemas de compilación

Como ya se explicó anteriormente, Make se desarrolló hace más de cuatro décadas. A lo largo de los años, la ejecución de trabajos en paralelo se ha vuelto cada vez más importante, y el número de compiladores y sistemas de compilación especialmente diseñados para lograr un mayor nivel de paralelización ha crecido desde entonces. La lista de herramientas incluye estas:

La mayoría de ellos han sido diseñados teniendo en cuenta la paralelización y ofrecen un mejor resultado en cuanto al tiempo de construcción que Make.

Conclusión

Como ha visto, vale la pena pensar en las compilaciones paralelas, ya que reduce significativamente el tiempo de compilación hasta cierto nivel. Aún así, no es fácil de lograr y tiene ciertos inconvenientes [3]. Se recomienda analizar tanto su código como su ruta de compilación antes de pasar a compilaciones paralelas.

Enlaces y referencias

Instale el último juego de estrategia de OpenRA en Ubuntu Linux
OpenRA es un motor de juego de estrategia en tiempo real libre / gratuito que recrea los primeros juegos de Westwood como el clásico Command & Conquer...
Instale el último emulador de Dolphin para Gamecube y Wii en Linux
Dolphin Emulator te permite jugar los juegos de Gamecube y Wii que elijas en computadoras personales con Linux (PC). Al ser un emulador de juegos de ...
Cómo usar GameConqueror Cheat Engine en Linux
El artículo cubre una guía sobre el uso del motor de trucos GameConqueror en Linux. Muchos usuarios que juegan juegos en Windows a menudo usan la apli...