Qu'est-ce qui pourrait provoquer le blocage de make lors de la compilation sur plusieurs cœurs?

17

Hier, j'essayais de compiler le package ROOT à partir des sources. Comme je le compilais sur une machine monstre à 6 cœurs, j'ai décidé d'aller de l'avant et de construire en utilisant plusieurs cœurs en utilisant make -j 6. La compilation s'est déroulée en douceur et très rapidement au début, mais à un moment donné, elle a été makesuspendue en utilisant 100% de CPU sur un seul cœur.

J'ai fait quelques recherches sur Google et j'ai trouvé ce message sur les babillards électroniques de ROOT. Depuis que j'ai construit cet ordinateur moi-même, je craignais de ne pas avoir correctement appliqué le dissipateur thermique et le processeur surchauffait ou quelque chose. Malheureusement, je n'ai pas de réfrigérateur ici au travail où je peux le coller. ;-)

J'ai installé le lm-sensorspackage et exécuté à make -j 6nouveau, cette fois en surveillant la température du processeur. Bien qu'elle soit devenue élevée (près de 60 ° C), elle n'a jamais dépassé la température élevée ou critique.

J'ai essayé de courir, make -j 4mais j'ai de nouveau makesuspendu pendant la compilation, cette fois à un endroit différent.

En fin de compte, j'ai compilé juste en cours d'exécution makeet cela a bien fonctionné. Ma question est: pourquoi était-elle suspendue? En raison du fait qu'il s'est arrêté à deux endroits différents, je suppose que cela était dû à une sorte de condition de course, mais je pense qu'il makedevrait être assez intelligent pour tout mettre dans le bon ordre car il offre l' -joption.

user545424
la source
4
Cela ressemble à une condition de course. Une chose que vous pourriez faire est d'attacher au processus make en cours d'exécution (celui qui tourne) en utilisant, par exemple, strace -p <pid>et voir si vous pouvez découvrir ce qu'il cherche / cherche. strace ne vous montrera que les appels système (pas les appels de fonction), mais il pourrait toujours vous donner des informations précieuses s'il tourne en regardant ou pour un fichier particulier.
jlp
Le fil que vous avez trouvé via google conduit à la conclusion que personne n'a pu le compiler -j >1.
Nils
Pas lié à la compilation parallèle, mais j'avais un makefile suspendu qui prenait une éternité à déboguer. Il s'avère que c'était simplement lors de l'initialisation d'une variable, $(shell ...)exécutait finalement une commande qui attendait l'entrée destdin . Cela était dû au fait qu'une variable était vide et qu'aucun argument de fichier n'était transmis à la commande.
jozxyqk

Réponses:

13

Je n'ai pas de réponse à ce problème précis, mais je peux essayer de vous donner un indice de ce qui peut se produire: Dépendances manquantes dans les Makefiles.

Exemple:

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

Si vous appelez, make targettout se compilera correctement. La compilation de a.sourceest effectuée (arbitrairement, mais de façon déterministe) en premier. Ensuite, la compilation de b.sourceest effectuée.

Mais si vous les make -j2 targetdeux compilecommandes seront exécutées en parallèle. Et vous remarquerez en fait que les dépendances de votre Makefile sont brisées. La deuxième compilation suppose qu'elle a.bytecodeest déjà compilée, mais elle n'apparaît pas dans les dépendances. Une erreur est donc susceptible de se produire. La ligne de dépendance correcte pour b.bytecodedoit être:

b.bytecode: b.source a.bytecode

Pour revenir à votre problème, si vous n'êtes pas chanceux, il est possible qu'une commande se bloque dans une boucle 100% CPU, en raison d'une dépendance manquante. C'est probablement ce qui se passe ici, la dépendance manquante n'a pas pu être révélée par une génération séquentielle, mais elle a été révélée par votre génération parallèle.

Stéphane Gimenez
la source
Intéressant. Savez-vous s'il existe des outils disponibles pouvant exécuter un makefile et vérifier ces dépendances?
user545424
Je n'en connais aucun. En tout cas, un tel outil ne pouvait que trouver des erreurs évidentes. Sauf s'il comprend la syntaxe de chaque commande qui apparaît dans le Makefile et sait quelles sont les dépendances (potentiellement implicites).
Stéphane Gimenez
2

Je ne sais pas depuis combien de temps vous avez la machine, mais ma première recommandation serait d'essayer un test de mémoire et de vérifier que la mémoire fonctionne correctement. Je sais que ce n'est souvent pas la mémoire qui est le problème, mais si c'est le cas, il est préférable de l'éliminer en tant que cause avant d'essayer de trouver d'autres problèmes probables.

killermist
la source
1

Je me rends compte que c'est une très vieille question, mais elle apparaît toujours en haut des résultats de recherche, alors voici ma solution:

GNU make dispose d'un mécanisme de serveur de travail pour garantir que make et ses enfants récursifs ne consomment pas plus que le nombre spécifié de cœurs: http://make.mad-scientist.net/papers/jobserver-implementation/

Il s'appuie sur un canal partagé par tous les processus. Chaque processus qui veut créer des enfants supplémentaires doit d'abord consommer des jetons du tuyau, puis les abandonner une fois terminé. Si un processus enfant ne retourne pas les jetons qu'il a consommés, la marque de niveau supérieur se bloque pour toujours en attendant leur retour.

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

J'ai rencontré cette erreur lors de la construction de binutils avec GNU make sur ma boîte Solaris, où "sed" n'est pas GNU sed. Jouer avec PATH pour que sed == gsed soit prioritaire sur le système sed a résolu le problème. Je ne sais pas pourquoi sed consommait des jetons de la pipe, cependant.

Fazal Majid
la source
0

votre système peut être correct, mais il peut s'agir d'une situation de concurrence critique makelors de l'exécution de builds en parallèle.

Si quelque chose ne va pas avec votre système, il se bloquerait / planterait pour d'autres scénarios, pas seulement lors des builds parallèles.

fduff
la source
0

Cela pourrait être une condition de concurrence, mais aussi si toute la compilation nécessaire se fait en parallèle et en attendant d'autres, la liaison prend votre temps sur votre machine. Je pense que si la liaison attend la compilation nécessaire précédente en parallèle, alors vous obtenez une fréquence de processeur élevée sur le lien de liaison tout ce que vous compilez.

MahmutBulut
la source