Une réduction parallèle suppose que l'opération correspondante est associative. Cette hypothèse est violée pour l'ajout de nombres à virgule flottante. Vous pourriez vous demander pourquoi je m'en soucie. Eh bien, cela rend les résultats moins reproductibles. Et cela empire lorsque le recuit simulé est utilisé pour optimiser (ou ajuster les paramètres) sur des sous-programmes produisant de tels résultats non reproductibles.
Quels sont les moyens courants de résoudre ce problème? Que dire des stratégies suivantes?
- Ne vous souciez pas de la non-reproductibilité.
- N'utilisez pas la réduction parallèle avec des nombres à virgule flottante et l'addition.
- Créez des lots de travaux de taille appropriée de manière reproductible et effectuez la réduction finale à la main.
- Utilisez une précision plus élevée pour l'ajout (mais tous les compilateurs n'offrent pas des types à virgule flottante de précision supérieure).
parallel-computing
reproducibility
Thomas Klimpel
la source
la source
Réponses:
Une réduction implémentée à l'aide
MPI_Allreduce()
est reproductible tant que vous utilisez le même nombre de processeurs, à condition que l'implémentation respecte la note suivante figurant à la section 5.9.1 de la norme MPI-2.2.Si vous devez garantir la reproductibilité à tout prix, vous pouvez suivre les instructions du paragraphe suivant:
Dans le schéma plus large des choses, des algorithmes efficaces pour la plupart des applications tirent parti de la localité. Étant donné que l'algorithme est vraiment différent lorsqu'il est exécuté sur un nombre différent de processus, il n'est tout simplement pas pratique de reproduire exactement les résultats lorsqu'il est exécuté sur un nombre différent de processus. Une exception possible est multigrille avec Jacobi amorti ou lisseurs polynomiaux (par exemple Chebyshev), où il est possible que cette méthode simple fonctionne très bien.
Avec le même nombre de processus, il est souvent avantageux pour la performance de traiter les messages dans l'ordre de leur réception (par exemple en utilisant
MPI_Waitany()
), ce qui introduit le non-déterminisme. Dans de tels cas, vous pouvez implémenter deux variantes, la plus rapide qui reçoit dans n'importe quel ordre et une "débogage" qui reçoit dans un ordre statique. Cela nécessite que toutes les bibliothèques sous-jacentes soient également écrites pour offrir ce comportement.Pour le débogage dans certains cas, vous pouvez isoler une partie d'un calcul qui n'offre pas ce comportement reproductible et l'exécuter de manière redondante. Selon la façon dont les composants ont été conçus, ce changement peut être une petite quantité de code ou très intrusif.
la source
Pour la plupart, je répète la réponse de Jed. Cependant, il existe une solution différente: étant donné la taille des nombres à virgule flottante normaux, vous pouvez stocker chaque nombre dans un nombre à virgule fixe de 4 000 bits environ. Donc, si vous faites une réduction sur les nombres à virgule flottante ainsi intégrés, vous obtenez un calcul exact, quelle que soit l'associativité. (Désolé, je n'ai pas la référence à qui a eu cette idée.)
la source
Vous pouvez implémenter un algorithme de réduction numériquement stable en MPI de la même manière que vous pouvez le faire en série. Il peut bien sûr y avoir un impact sur les performances. Si vous pouvez vous permettre de répliquer le vecteur, utilisez simplement MPI_Gather et effectuez la réduction numérique stable en série à la racine. Dans certains cas, vous constaterez peut-être que l'atteinte des performances n'est pas un gros problème.
Une autre solution consiste à utiliser des accumulateurs larges comme décrit ici . Vous pouvez le faire avec MPI en tant que réduction définie par l'utilisateur, bien qu'il utilisera beaucoup plus de bande passante.
Un compromis pour ce qui précède consiste à utiliser la somme compensée. Voir les références «sommation Kahan» pour plus de détails. «La précision et la stabilité des algorithmes numériques » de Higham est une excellente ressource sur ce sujet.
la source
Pour résoudre le problème dans le contexte des threads sur un système de mémoire partagée, j'ai écrit cette page qui explique ce que nous faisons dans l'affaire. II: http://dealii.org/developer/doxygen/deal.II/group__threads.html #MTWorkStream
la source
Je voudrais souligner qu'au lieu d'utiliser une arithmétique de plus grande précision pour l'addition, il y a la possibilité d'utiliser une sommation compensée (voir [1]). Cela pourrait augmenter la précision de la sommation sans avoir à recourir à des types de données plus importants.
[1] Higham, NJ La précision de la sommation à virgule flottante. SIAM Journal on Scientific Computing 14, 783–799 (1993).
la source