Código de compilação em paralelo usando make

Código de compilação em paralelo usando make

Quem você pergunta como criar software corretamente criará como uma das respostas. Nos sistemas GNU/Linux, o GNU Make [1] é a versão de código aberto da marca original que foi lançada 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 do processo de construção de software. O Makefile contém vários rótulos (chamados alvos) e as instruções específicas necessárias para serem executadas para construir cada destino.

Simplesmente falando, Make é uma ferramenta de construção. Segue a receita de tarefas do Makefile. Ele permite repetir as etapas de maneira automatizada, em vez de digitá -las em um terminal (e provavelmente cometendo erros durante a digitação).

A Listagem 1 mostra um exemplo makefile com os dois alvos "E1" e "E2", bem como os dois alvos especiais "todos" e "limpos.”Executar“ Make E1 ”executa as instruções para o destino“ E1 ”e cria o arquivo vazio um. A execução "Make E2" faz o mesmo para o destino "E2" e cria o arquivo vazio dois. A chamada de "Make All" executa as instruções para o alvo E1 primeiro e E2 Next. Para remover os arquivos criados anteriormente um e dois, basta executar a chamada “Faça limpo.”

Listagem 1

Tudo: 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, em seguida. Todos os alvos são incorporados em ordem em série e sem paralelização. O tempo total de construção é a soma do tempo necessário para construir todos os alvos.

Essa abordagem funciona bem para projetos pequenos, mas leva muito tempo para projetos médios e maiores. Essa abordagem não está mais atualizada, pois a maioria das CPUs atuais está equipada com mais de um núcleo e permite a execução de mais de um processo de cada vez. Com essas idéias em mente, analisamos se e como o processo de construção pode ser paralelo. 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 únicas em diferentes nós de computação, 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 e 4) Combine opções 2 e 3.

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

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, essa abordagem é usada para criar pacotes de software. O Debian GNU/Linux usa a chamada Rede Autobuilder [17], e Redhat/Fedors usa Koji [18]. O Google chama seu sistema BuildRabbit e é perfeitamente explicado na palestra de Aysylu Greenberg [16]. O DISTCC [2] é o chamado compilador C distribuído que permite 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 a melhor relação custo-benefício para você, pois não requer hardware adicional, como na opção 2. O requisito de execução para fazer em paralelo é adicionar a opção -j na chamada (curta para -jobs). Isso especifica o número de trabalhos que são executados ao mesmo tempo. A listagem abaixo pede fazer para executar 4 empregos 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 únicos não dependem um do outro; Por exemplo, a saída do alvo 5 não é necessária para construir o alvo 3.

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

Definir fazer a ordem de execução

Existem declarações que ajudam a entender quais metas dependem um do outro? Sim! O exemplo makefile na Listagem 3 diz o seguinte:

* Para construir o Target "All", execute as instruções para E1, E2 e E3

* O alvo E2 exige que o alvo E3 seja construído antes

Isso significa que os alvos E1 e E3 podem ser construídos em paralelo, primeiro, depois o E2 segue assim que a construção de E3 é concluída, finalmente.

Listagem 3

Todos: e1 e2 e3
E1:
toque em um
E2: E3
Toque em dois
E3:
Toque em três
limpar:
rm um dois três

Visualize as dependências de fazer

O projeto Clever Tool Make2graph do Makefile2graph [19] Project visualiza as dependências de fazer como um gráfico acíclico direcionado. Isso ajuda a entender como os diferentes alvos dependem um do outro. Descrições gráficas do Make2Graph Saidações no formato DOT que você pode transformar em uma imagem PNG usando o comando DOT do projeto GraphViz [22]. A chamada é a seguinte:

Listagem 4

$ Make All -Bnd | make2graph | Gráfico de dot -tpng -o.png

Em primeiro lugar, o Make é chamado com o alvo "tudo", seguido pelas opções "-b" para construir incondicionalmente todos os alvos, "-n" (abreviação de "-dry-run") para fingir que a execução das instruções por destino e " -d ”(“ -debug ”) para exibir informações de depuração. A saída é canalizada para make2graph que transa sua saída para o ponto que gera o gráfico de arquivo.PNG em formato PNG.


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

Mais compiladores e sistemas de construção

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

  • Bazel [20]
  • Cmake [4]: ​​abreviados
  • distmake [12]
  • Distribuído Sistema Make (DMS) [10] (parece estar morto)
  • Dmake [13]
  • LSF faz [15]
  • Apache Maven
  • Méson
  • Ninja Build
  • Nmake [6]: Faça o Microsoft Visual Studio
  • Pydoit [8]
  • Qmake [11]
  • refazer [14]
  • SCONS [7]
  • WAF [9]

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 fazer.

Conclusão

Como você já viu, vale a pena pensar em construções paralelas, pois reduz significativamente o tempo de aumentar o tempo até um determinado nível. Ainda assim, não é fácil de alcançar 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

  • [1] GNU Make Manual: Execução paralela, https: // www.gnu.org/software/make/manual/html_node/paralelo.html
  • [2] DISTCC: https: // github.com/distcc/distcc
  • [3] John Graham-Cumming: as armadilhas e os benefícios da GNU fazem paralelização, https: // www.cmcrossroads.com/artigo/armadilhas e benefícios
  • [4] Cmake, https: // cmake.org/
  • [5] LoadTeam, https: // www.LoadTeam.coma
  • [6] Nmake, https: // docs.Microsoft.com/en-us/cpp/build/reference/nmake-reference?View = MSVC-160
  • [7] SCONS, https: // www.SCONS.org/
  • [8] Pydoit, https: // pydoit.org/
  • [9] WAF, https: // gitlab.com/ta1024/waf/
  • [10] Sistema de Make Distributed (DMS), http: // www.NONGNU.org/dms/índice.html
  • [11] Qmake, https: // doc.Qt.io/qt-5/qmake-manual.html
  • [12] Distmake, https: // Sourceforge.rede/projetos/distmake/
  • [13] Dmake, https: // docs.oráculo.com/cd/e19422-01/819-3697/dmake.html
  • [14] Refazer, https: // refazer.ReadThEdocs.io/en/mais recente/
  • [15] LSF Make, http: // sunray2.mit.Edu/kits/plataforma-lsf/7.0.6/1/guias/kit_lsf_guide_source/print/lsf_make.pdf
  • [16] AYSYLU GREENBERG: Construindo um sistema de construção distribuído no Google Scale, GoTo Conference 2016, https: // gotocon.com/dl/goto-chicago-2016/slides/aysylugreenberg_buildingadistributedbuildsystematgoglescale.pdf
  • [17] Debian Build System, Autobuilder Network, https: // www.Debian.org/desenvolvimento/buildd/index.en.html
  • [18] Koji - RPM Building and Racking System, https: // pagure.io/koji/
  • [19] Makefile2graph, https: // github.com/lindenb/makefile2graph
  • [20] Bazel, https: // bazel.construir/
  • [21] Tutorial Makefile, https: // makefiletutorial.coma
  • [22] Graphviz, http: // www.GraphViz.org
  • [23] Lei de Amdahl, Wikipedia, https: // pt.Wikipedia.org/wiki/amdahl%27s_law