Bonjour,
Nous avons rencontré un problème qui n'était pas facile à comprendre, que j'aimerais partager ici au cas où ça puisse être utile à quelqu'un (et au cas où des solutions existeraient). Nous avons eu de manière répétable des core dump systématiques sur un exécutable C++ "maison" compilé sur le cluster, mais seulement sur certains nœuds (cpu-node-72 à cpu-node-78).
Les erreurs sont du style:
srun: error: cpu-node-74: task 0: Illegal instruction (core dumped)
Le plantage n'est pas reproductible avec un exécutable compilé avec les symboles de débuggage, donc difficile de creuser exactement où le problème a lieu.
Après quelques heures de tentatives de débuggage, je me suis aperçu que les noeuds 72 à 78 n'étaient pas identiques aux autres :
Intel(R) Xeon(R) CPU E5-2650 v2 @ 2.60GHz
Alors que j'ai
Intel(R) Xeon(R) CPU E5-2695 v3 @ 2.30GHz
pour les autres noeuds (et Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz pour le master).
Et le problème disparait si je retire l'option -march=native du compilateur. Il s'agit donc bien d'une incompatibilité des binaires compilés sur le le nœud master quand ils sont exécutés sur les nœuds 72-78. On ne peut pas exclure à la base que ça ne fait que révéler une gestion hasardeuse des pointeurs de fonctions dans mon code, mais en tout cas l'erreur est révélée par le changement de CPU.
J'avoue que je ne m'attendais pas à des incompatibilités binaires entre exécutables compilés sur des Xeon aussi similaires, mais pour information : c'est possible.
Question 1: est-ce que ces différences d'architectures sont documentées quelque part?
Question 2: faut-il renoncer aux optimisations cpu-spécifiques sur le cluster? Sinon, quel socle commun peut-on espérer? (Intel? x86?) Est-ce que l'homogénéité du hardware est dans le cahier des charges, ou est-ce qu'il est possible que la nouvelle génération de nœuds soit sur une architecture complètement différente (ARM?).
Question 3: savez-vous s'il est possible d'indiquer à slurm d'utiliser des exécutables différents en fonction des nœuds? Ou d'exploiter un espace disque non-mutualisé, spécifique au nœud? (par exemple, pour compiler avant d'exécuter?).
Deux solutions semblent fonctionner :
Solution 1: compiler sans l'option -march=native (je n'ai pas mesuré l'impact sur le temps d'exécution).
Solution 2: exclure les nœuds problématiques avec --exclude.
Le problème avec la solution 2 c'est qu'elle risque de devenir de plus en plus compliquée à mettre en place avec la croissance du cluster et la multiplication des petites différences entre les nœuds.