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.

user545424
fonte
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.

Stéphane Gimenez
fonte
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.

killermist
fonte
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.

Fazal Majid
fonte
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.

fduff
fonte
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.

MahmutBulut
fonte