Aller au contenu principal
Ce projet est en phase bêta. Tu as trouvé un bug ? Ouvrir un ticket GitHub. Une question ou une idée ? Pose ta question dans Discussions — tes retours sont les bienvenus !
Quelle est la qualité de la traduction sur cette page ?

Prise en charge de l'accélération multi-processus et multi-threads

Cette page décrit dans quelle mesure qiskit-addon-sqd prend en charge l'accélération multi-threads et multi-processus, ainsi que les hypothèses sur lesquelles un développeur de calcul haute performance (HPC) peut s'appuyer lorsqu'il intègre ce paquet dans une charge de travail accélérée.

L'hypothèse du thread unique​

Sauf indication contraire, les API de ce paquet sont destinées à être appelées depuis un seul thread. Les API de haut niveau exposées par ce paquet ne sont pas garanties réentrantes, et les utilisateurs finaux ne doivent pas les invoquer depuis un autre thread que le thread principal.

Exécution collective multi-processus​

Ce paquet prend en charge l'accélération collective multi-processus dans le style programme unique, données multiples (SPMD), dans lequel le programme entier est lancé sous forme de plusieurs processus isolés qui s'exécutent avec une synchronisation globale explicite et une communication entre eux (par exemple, mpirun -n 128 python my_program.py). Comme le style SPMD se combine proprement avec les ordonnanceurs de tâches et d'autres logiciels parallèles et passe à l'échelle jusqu'à un grand nombre de processus, c'est le modèle recommandé pour les charges de travail haute performance et à grande échelle, et c'est le sujet de cette page.

Bien que ce paquet soit conçu pour s'adapter à différents backends d'exécution collective, son implémentation actuelle cible MPI, l'API standard de transmission de messages pour les systèmes HPC. Quelle que soit l'implémentation, ce paquet suppose qu'un seul thread contrôle chaque processus. Dans le cas de MPI, cela correspond à MPI_THREAD_FUNNELED ou moins.

Si une fonction prend en charge l'exécution collective, sa documentation doit le préciser. Si la documentation ne mentionne pas l'exécution collective, la fonction n'a pas de sémantique collective et doit être appelée uniquement depuis le processus de contrôle.

La valeur de retour et la sémantique de synchronisation spécifiques d'une fonction collective sont documentées avec la fonction elle-même. En général, cette documentation doit indiquer clairement :

  • Si la fonction est destinée à être appelée indépendamment par chaque processus sur ses propres données locales, ou collectivement par tous les processus.

  • Comment ses arguments doivent concorder entre les processus.

  • Comment sa valeur de retour est délivrée : si le résultat n'existe que sur le processus de contrôle, si tous les processus reçoivent la même valeur, ou si chaque processus reçoit un descripteur vers une partie locale d'une structure de données distribuée.

Une seule fonction prend actuellement en charge l'appel collectif depuis tous les processus : diagonalize_fermionic_hamiltonian(). Lorsqu'elle est invoquée collectivement, l'étape du solveur de vecteurs propres est celle où tous les processus participent et fournissent du travail, de sorte qu'une implémentation de solveur peut utiliser tous les processus. Les autres parties de la boucle de récupération de configurations n'ont pas d'implémentation distribuée et s'exécutent uniquement sur le processus de contrôle (rang 0).

Chaque sous-espace d'une itération est transmis au solveur de vecteurs propres en un seul appel, de sorte qu'une implémentation est libre de répartir les processus en groupes et de diagonaliser plusieurs sous-espaces en parallèle. La façon dont un solveur utilise les processus qui lui sont accessibles est une propriété de ce solveur.

Certaines implémentations de solveurs de vecteurs propres existantes exigent que le programme appelant s'exécute en dehors d'un environnement MPI/SPMD, car elles lancent et gèrent elles-mêmes leurs propres processus parallèles en interne, par exemple en invoquant mpirun au nom de l'utilisateur. Ce mode est pratique pour le travail interactif et dans les notebooks et reste pris en charge ; ses exigences vis-à-vis du programme appelant sont décrites dans la référence de l'API de la fonction diagonalize_fermionic_hamiltonian().

Gestion des erreurs dans un contexte multi-processus​

Une fonction appelée collectivement depuis tous les processus ne doit pas lever d'exception ni interrompre un seul processus, car cela laisserait les autres processus bloqués dans une impasse ou dans un état incohérent. À la place, la gestion des erreurs suit une sémantique d'arrêt sur défaillance (fail-stop) pour le contexte d'exécution dans son ensemble : en cas d'erreur, l'implémentation doit être prête à interrompre collectivement tout le contexte d'exécution (par exemple, en utilisant MPI_Abort).

L'API ne peut pas garantir un signalement coordonné des erreurs ni une remise collective des exceptions entre les processus, car les implémentations de MPI n'offrent pas de telles garanties. Une implémentation peut en plus tenter de rendre une erreur visible à tous les processus participants, par exemple en faisant lever une exception par chaque processus, mais cela ne peut être fourni qu'au mieux et ne doit pas être utilisé pour garantir la correction ou la reprise.

Ce sont des propriétés qu'une implémentation collective est autorisée à avoir, et non des garanties sur une implémentation particulière. Dans ce paquet, la seule étape collective est le solveur de vecteurs propres (voir la section précédente) ; son implémentation par défaut n'est pas distribuée, ces considérations s'appliquent donc à un solveur de vecteurs propres collectif personnalisé fourni par l'utilisateur.