O que pode estar causando o travamento ao compilar em vários núcleos?


17

Ontem eu estava tentando compilar o pacote ROOT a partir do código-fonte. Desde que eu estava compilando em uma máquina monstro de 6 núcleos, decidi ir em frente e construir usando vários núcleos usando make -j 6. A compilação foi suave e muito rápida no início, mas em algum momento maketravou usando 100% da CPU em apenas um núcleo.

Eu pesquisei no Google e encontrei este post nos quadros de mensagens do ROOT. Desde que eu mesmo construí este computador, fiquei preocupado por não ter aplicado corretamente o dissipador de calor e a CPU estar superaquecendo ou algo assim. Infelizmente, não tenho uma geladeira aqui no trabalho onde posso colocá-la. ;-)

Instalei o lm-sensorspacote e executei make -j 6novamente, desta vez monitorando a temperatura da CPU. Embora tenha ficado alto (perto de 60 ° C), nunca passou da temperatura alta ou crítica.

Tentei correr, make -j 4mas novamente fiquei makesuspenso em algum momento durante a compilação, desta vez em um local diferente.

No final, eu compilei apenas rodando makee funcionou bem. Minha pergunta é: Por que estava pendurado? Devido ao fato de ter parado em dois pontos diferentes, acho que foi devido a algum tipo de condição de corrida, mas acho que makedeveria ser inteligente o suficiente para colocar tudo na ordem certa, pois oferece a -jopção.


4
Parece uma condição de corrida. Uma coisa que você pode fazer é anexar ao processo de execução (o que está girando) usando, por exemplo, strace -p <pid>e veja se você consegue descobrir o que ele está procurando /. O strace mostrará apenas syscalls (não chamadas de função), mas ainda poderá fornecer informações valiosas se estiver girando enquanto você olha ou procura um arquivo específico.
jlp

O tópico que você encontrou no google leva à conclusão de que ninguém foi capaz de compilá-lo -j >1.
Nils

Não relacionado à compilação paralela, mas eu tinha um makefile pendurado que demorava uma eternidade para depurar. Acontece que estava simplesmente na inicialização de uma variável, $(shell ...)estava executando um comando que estava aguardando a entrada destdin . Isso foi causado quando uma variável estava vazia e nenhum argumento do arquivo foi passado para o comando.
precisa saber é o seguinte

Respostas:


13

Não tenho uma resposta para essa questão precisa, mas posso tentar dar uma dica do que pode estar acontecendo: Faltando dependências no Makefiles.

Exemplo:

target: a.bytecode b.bytecode
    link a.bytecode b.bytecode -o target

a.bytecode: a.source
    compile a.source -o a.bytecode

b.bytecode: b.source
    compile b.source a.bytecode -o a.bytecode

Se você ligar, make targettudo será compilado corretamente. A compilação de a.sourceé realizada (arbitrariamente, mas deterministicamente) primeiro. Em seguida, a compilação b.sourceé realizada.

Mas se os make -j2 targetdois compilecomandos serão executados em paralelo. E você perceberá que as dependências do Makefile estão quebradas. A segunda compilação assume que a.bytecodejá está compilada, mas não aparece nas dependências. Portanto, é provável que ocorra um erro. A linha de dependência correta para b.bytecodedeve ser:

b.bytecode: b.source a.bytecode

Para voltar ao seu problema, se você não tiver sorte, é possível que um comando seja interrompido em um loop de 100% da CPU, devido a uma dependência ausente. Provavelmente é o que está acontecendo aqui, a dependência que faltava não pôde ser revelada por uma compilação sequencial, mas foi revelada pela sua compilação paralela.


Interessante. Você sabe se existem ferramentas disponíveis que possam executar um makefile e verificar essas dependências?
user545424

Eu não conheço nenhum. De qualquer forma, essa ferramenta só poderia encontrar erros óbvios. A menos que entenda a sintaxe de cada comando que aparece no Makefile e saiba quais são as dependências (potencialmente implícitas).
Stéphane Gimenez

2

Não sei quanto tempo você está com a máquina, mas minha primeira recomendação seria tentar um teste de memória e verificar se a memória está funcionando corretamente. Sei que muitas vezes não é a memória que é o problema, mas, se for, é melhor eliminá-lo como uma causa antes de tentar localizar outros problemas prováveis.


1

Sei que essa é uma pergunta muito antiga, mas ela ainda aparece no topo dos resultados de pesquisa, então aqui está a minha solução:

O GNU make possui um mecanismo de servidor de tarefas para garantir que o make e seus filhos recursivos não consumam mais do que o número especificado de núcleos: http://make.mad-scientist.net/papers/jobserver-implementation/

Ele se baseia em um canal compartilhado por todos os processos. Cada processo que deseja bifurcar filhos adicionais precisa primeiro consumir tokens do cano e depois abandoná-los quando terminar. Se um processo filho não retornar os tokens que consumiu, o nível superior ficará bloqueado para sempre aguardando a devolução.

https://bugzilla.redhat.com/show_bug.cgi?id=654822

Encontrei este erro ao criar binutils com o GNU make na minha caixa Solaris, onde "sed" não é GNU sed. Brincar com o PATH para fazer com que o sed == gsed tenha prioridade sobre o sistema sed corrigiu o problema. Não sei por que o sed estava consumindo tokens do cano, no entanto.


0

seu sistema pode estar ok, mas pode ser uma condição de corrida acontecendo makeao executar compilações em paralelo.

Se algo estiver errado com o seu sistema, ele travaria / trava em outros cenários, não apenas ao fazer compilações paralelas.


0

Isso pode ser uma condição de corrida, mas também se toda a compilação necessária for feita em paralelo e aguardando outras pessoas, a vinculação leva tempo na sua máquina. Eu acho que se o link aguarda a compilação necessária anterior em paralelo, você obtém alta frequência de CPU no encadeamento de link, independentemente do que compilar.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.