GNU Make

Compilando código em paralelo usando Make

Compilando código em paralelo usando Make

Quem quer que você pergunte sobre como construir um software de maneira adequada, apresentará Make como uma das respostas. Em sistemas GNU / Linux, GNU Make [1] é a versão de código aberto do Make original que foi lançado há mais de 40 anos - em 1976. Faça trabalhos com um Makefile - um arquivo de texto simples estruturado com esse nome que pode ser melhor descrito como o manual de construção para o processo de construção de software. O Makefile contém uma série de rótulos (chamados de alvos) e as instruções específicas necessárias para serem executadas para construir cada alvo.

Simplesmente falando, Make é uma ferramenta de construção. Segue a receita de tarefas do Makefile. Ele permite que você repita as etapas de forma automatizada em vez de digitá-las em um terminal (e provavelmente cometer erros ao digitar).

A Listagem 1 mostra um Makefile de exemplo com os dois destinos "e1" e "e2", bem como os dois destinos especiais "all" e "clean.”Executar“ make e1 ”executa as instruções para o destino“ e1 ”e cria o arquivo vazio um. Executar “make e2” faz o mesmo para o destino “e2” e cria o arquivo vazio dois. A chamada de "fazer tudo" executa as instruções para o destino e1 primeiro e e2 depois. Para remover os arquivos um e dois criados anteriormente, basta executar a chamada “make clean.”

Listagem 1

todos: e1 e2
e1:
toque em um
e2:
toque em dois
limpar:
rm um dois

Running Make

O caso comum é que você escreve seu Makefile e então apenas executa o comando “make” ou “make all” para construir o software e seus componentes. Todos os alvos são construídos em ordem serial e sem qualquer paralelização. O tempo total de construção é a soma do tempo necessário para construir cada alvo.

Esta abordagem funciona bem para projetos pequenos, mas leva muito tempo para projetos médios e grandes. Esta abordagem não está mais atualizada, pois a maioria dos cpus atuais são equipados com mais de um núcleo e permitem a execução de mais de um processo ao mesmo tempo. Com essas ideias em mente, verificamos se e como o processo de construção pode ser paralelizado. O objetivo é simplesmente reduzir o tempo de construção.

Faça melhorias

Existem algumas opções que temos - 1) simplificar o código, 2) distribuir as tarefas individuais em nós de computação diferentes, construir o código lá e coletar o resultado a partir daí, 3) construir o código em paralelo em uma única máquina e 4) combinar as opções 2 e 3.

Opção 1) nem sempre é fácil. Requer vontade de analisar o tempo de execução do algoritmo implementado e conhecimento sobre o compilador, i.e., como o compilador traduz as instruções da linguagem de programação em instruções do processador.

A opção 2) requer acesso a outros nós de computação, por exemplo, nós de computação dedicados, máquinas não utilizadas ou menos usadas, máquinas virtuais de serviços em nuvem como AWS ou poder de computação alugado de serviços como LoadTeam [5]. Na realidade, esta abordagem é usada para construir pacotes de software. Debian GNU / Linux usa a chamada rede Autobuilder [17], e RedHat / Fedors usa Koji [18]. O Google chama seu sistema de BuildRabbit e é perfeitamente explicado na palestra de Aysylu Greenberg [16]. distcc [2] é o chamado compilador C distribuído que permite a você compilar código em diferentes nós em paralelo e configurar seu próprio sistema de construção.

A opção 3 usa paralelização no nível local. Esta pode ser a opção com melhor custo-benefício para você, pois não requer hardware adicional como na opção 2. O requisito para executar Make em paralelo é adicionar a opção -j na chamada (abreviação de -jobs). Isso especifica o número de trabalhos que são executados ao mesmo tempo. A lista abaixo pede para fazer para executar 4 trabalhos em paralelo:

Listagem 2

$ make --jobs = 4

De acordo com a lei de Amdahl [23], isso reduzirá o tempo de construção em quase 50%. Lembre-se de que essa abordagem funciona bem se os alvos individuais não dependerem uns dos outros; por exemplo, a saída da meta 5 não é necessária para construir a meta 3.

No entanto, há um efeito colateral: a saída das mensagens de status para cada alvo Make parece arbitrária e não pode mais ser atribuída claramente a um alvo. A ordem de saída depende da ordem real de execução do trabalho.

Definir a ordem de execução

Existem declarações que ajudam a compreender quais alvos dependem uns dos outros? sim! O Makefile de exemplo na Listagem 3 diz o seguinte:

* para construir o destino “todos”, execute as instruções para e1, e2 e e3

* target e2 requer que target e3 seja construído antes

Isso significa que os alvos e1 e e3 podem ser construídos em paralelo, primeiro, então e2 segue assim que a construção de e3 for concluída, finalmente.

Listagem 3

todos: e1 e2 e3
e1:
toque em um
e2: e3
toque dois
e3:
toque três
limpar:
rm um dois três

Visualize as dependências do Make

A ferramenta inteligente make2graph do projeto makefile2graph [19] visualiza as dependências do Make como um gráfico acíclico direcionado. Isso ajuda a entender como os diferentes alvos dependem uns dos outros. Make2graph produz descrições de gráficos em formato de ponto que você pode transformar em uma imagem PNG usando o comando de ponto do projeto Graphviz [22]. A chamada é a seguinte:

Listagem 4

$ make all -Bnd | make2graph | dot -Tpng -o graph.png

Em primeiro lugar, Make é chamado com o destino “all” seguido pelas opções “-B” para construir incondicionalmente todos os destinos, “-n” (abreviação de “-dry-run”) para fingir que está executando as instruções por destino, e “ -d ”(“ -debug ”) para exibir informações de depuração. A saída é canalizada para make2graph que canaliza sua saída para o ponto que gera o gráfico do arquivo de imagem.png em formato PNG.


O gráfico de dependência de compilação para a listagem 3

Mais compiladores e sistemas de construção

Como já explicado acima, o Make foi desenvolvido há mais de quatro décadas. Ao longo dos anos, a execução de tarefas em paralelo tornou-se cada vez mais importante, e o número de compiladores e sistemas de construção especialmente projetados para atingir um nível mais alto de paralelização cresceu desde então. A lista de ferramentas inclui:

A maioria deles foi projetada com paralelização em mente e oferece um resultado melhor em relação ao tempo de construção do que o Make.

Conclusão

Como você viu, vale a pena pensar em construções paralelas, pois isso reduz significativamente o tempo de construção até um certo nível. Ainda assim, não é fácil de conseguir e vem com certas armadilhas [3]. Recomenda-se analisar seu código e seu caminho de construção antes de entrar em construções paralelas.

Links e referências

Como mostrar o contador de FPS em jogos Linux
Os jogos Linux tiveram um grande impulso quando a Valve anunciou o suporte Linux para o cliente Steam e seus jogos em 2012. Desde então, muitos jogos ...
Como baixar e jogar Sid Meier's Civilization VI no Linux
Introdução ao jogo Civilization 6 é uma versão moderna do conceito clássico introduzido na série de jogos Age of Empires. A ideia era bastante simples...
Como instalar e jogar Doom no Linux
Introdução ao Doom A série Doom teve origem nos anos 90 após o lançamento do Doom original. Foi um sucesso instantâneo e, a partir desse momento, a sé...