Comment déterminer le nombre maximum à passer à l'option make -j?

31

Je veux compiler aussi vite que possible. Allez comprendre. Et souhaite automatiser le choix du numéro suivant l' -joption. Comment puis-je choisir cette valeur par programme, par exemple dans un script shell?

La sortie est-elle nprocéquivalente au nombre de threads avec lesquels je peux compiler?

make -j1 make -j16

tarabyte
la source

Réponses:

34

nprocdonne le nombre de cœurs / threads de processeur disponibles, par exemple 8 sur un processeur quadricœur prenant en charge le SMT bidirectionnel.

Le nombre de travaux que vous pouvez exécuter en parallèle avec l' makeutilisation de l' -joption dépend d'un certain nombre de facteurs:

  • la quantité de mémoire disponible
  • la quantité de mémoire utilisée par chaque maketravail
  • la mesure dans laquelle les maketravaux sont liés aux E / S ou au processeur

make -j$(nproc) est un bon endroit pour commencer, mais vous pouvez généralement utiliser des valeurs plus élevées, tant que vous n'épuisez pas votre mémoire disponible et ne commencez pas à battre.

Pour les builds vraiment rapides, si vous avez assez de mémoire, je recommande d'utiliser un tmpfs, de cette façon la plupart des jobs seront liés au CPU et make -j$(nproc)fonctionneront aussi vite que possible.

Stephen Kitt
la source
3
et ccachepour une reconstruction ultérieure, mais ceci est OT
solsTiCe
1
Est-ce que l'utilisation de quelque chose comme GNU parallel serait utile ici?
terdon
Si j'utilise un tmpfs, est-ce que je serai limité à une taille de répertoire toujours inférieure à la taille de ma RAM physique?
tarabyte
2
Ce n'est pas une bonne réponse, mais dans l'esprit strict de la question de déterminer par programme la valeur "j" la plus rapide, vous pouvez boucler j de 1 à une limite supérieure raisonnable (2x nproc ??) et encapsuler la marque dans un timeappel. Nettoyez les résultats, faites mousser et répétez le rinçage - et finissez par trier les valeurs fois / j.
Jeff Schaller
3
@terdon No. Make consiste à résoudre les dépendances, ce qui signifie que les travaux doivent toujours être exécutés dans un certain ordre. Le parallèle GNU s'en fiche. D'un autre côté, décider quels travaux peuvent être exécutés en parallèle et lesquels ne le sont pas est un problème difficile. Tous les programmes qui offraient des versions parallèles ont pris des années avant de devenir quelque peu utilisables.
lcd047
6

Malheureusement, même différentes parties d'une même build peuvent être optimales avec des valeurs de facteur j conflictuelles, selon ce qui est en cours de construction, comment, quelles ressources système sont le goulot d'étranglement à ce moment-là, ce qui se passe sur la machine de build, ce qui se passe dans le réseau (si vous utilisez des techniques de build distribuées), l'état / l'emplacement / les performances des nombreux systèmes de mise en cache impliqués dans une build, etc.

La compilation de 100 petits fichiers C peut être plus rapide que la compilation d'un seul gros fichier, ou vice versa. Construire un petit code très alambiqué peut être plus lent que de construire d'énormes quantités de code simple / linéaire.

Même le contexte de la construction est important - l'utilisation d'un facteur aj optimisé pour les builds sur des serveurs dédiés affinés pour des builds exclusifs et non superposés peut donner des résultats très décevants lorsqu'ils sont utilisés par des développeurs construisant en parallèle sur le même serveur partagé (chaque build peut prendre plus temps que tous combinés si sérialisés) ou sur des serveurs avec différentes configurations matérielles ou virtualisés.

Il y a aussi l'aspect de l'exactitude de la spécification de construction. Les constructions très complexes peuvent avoir des conditions de concurrence provoquant des échecs de construction intermittents avec des taux d'occurrence qui peuvent varier énormément avec l'augmentation ou la diminution du facteur j.

Je peux continuer encore et encore. Le fait est que vous devez réellement évaluer votre build dans votre contexte même pour lequel vous voulez que le facteur j soit optimisé. Le commentaire de @Jeff Schaller s'applique: itérez jusqu'à ce que vous trouviez le meilleur ajustement. Personnellement, je commencerais par la valeur nproc, j'essaierais d'abord vers le haut et vers le bas uniquement si les tentatives vers le haut montrent une dégradation immédiate.

Cela pourrait être une bonne idée de mesurer d'abord plusieurs constructions identiques dans des contextes supposés identiques juste pour avoir une idée de la variabilité de vos mesures - si elle est trop élevée, cela pourrait compromettre votre effort d'optimisation entier (une variabilité de 20% éclipserait complètement une amélioration de 10% / lecture de dégradation dans la recherche du facteur j).

Enfin, à mon humble avis , il est préférable d'utiliser un serveur de travail (adaptatif) s'il est pris en charge et disponible au lieu d'un facteur j fixe - il offre systématiquement de meilleures performances de construction dans une plus large gamme de contextes.

Dan Cornilescu
la source
bien mis en ce qui concerne les dépendances de la construction sous-jacente. pouvez-vous commenter le fait de ne pas passer de nombre fixe avec le -jparamètre? par exemplemake -j
tarabyte
4
make -jgénérera autant de travaux que les dépendances le permettent comme une bombe fourchette ( superuser.com/questions/927836/… ); la construction va au mieux dépenser plus de CPU pour gérer les processus que pour les exécuter ( superuser.com/questions/934685/… ) et dans les constructions très parallèles, le système manquera de mémoire / swap ou pid #s et la construction échouera .
Dan Cornilescu
3

La façon la plus simple est d'utiliser nproccomme ceci:

make -j`nproc`

La commande nprocrenverra le nombre de cœurs sur votre machine. En l'enveloppant dans les ticks, la nproccommande s'exécutera en premier, renverra un numéro et ce numéro sera transmis make.

Vous pouvez avoir une expérience anecdotique où le nombre de cœurs + 1 entraîne des temps de compilation plus rapides. Cela a davantage à voir avec des facteurs tels que les retards d'E / S, d'autres retards de ressources et d'autres contraintes de disponibilité des ressources.

Pour ce faire nproc+1, essayez ceci:

make -j$((`nproc`+1))
010110110101
la source
0

Si vous souhaitez écrire une makecommande pour utiliser autant de travailleurs parallèles que vous avez de CPU virtuels, je suggère d'utiliser:

nproc | xargs -I % make -j%

Qui peut être écrite soit comme une commande autonome, soit comme une RUNdirective à l'intérieur Dockerfile(car Docker ne prend pas en charge les commandes imbriquées)

Maksym Ganenko
la source