OpenMP: Quel est l'avantage de l'imbrication des parallélisations?
De ce que je comprends, #pragma omp parallel
et de ses variations fondamentalement exécuter le bloc suivant dans un certain nombre de threads simultanés, ce qui correspond au nombre de Processeurs. Lorsque imbriquée parallelizations - parallèle dans parallèle, parallèle à l'intérieur de fonction parallèle etc. - ce qui se passe à l'intérieure de la parallélisation?
Je suis nouveau sur OpenMP, et le cas que j'ai en tête est plutôt trivial - multiplication d'un vecteur par une matrice. Ceci est fait en deux boucles for imbriquées. En supposant que le nombre de Processeurs est plus petit que le nombre d'éléments dans le vecteur, est-il un avantage en essayant de lancer la boucle interne en parallèle? Sera le nombre total de threads être plus grand que le nombre de Processeurs, ou la boucle intérieure être exécutées de manière séquentielle?
source d'informationauteur eran
Vous devez vous connecter pour publier un commentaire.
(1) parallélisme Imbriqué dans OpenMP:
http://docs.oracle.com/cd/E19205-01/819-5270/aewbc/index.html
Vous devez activer le parallélisme imbriqué par la mise en
OMP_NESTED
ouomp_set_nested
parce que de nombreuses implémentations de désactiver cette fonctionnalité par défaut, même certaines implémentations ne prend pas en charge parallélisme imbriqué entièrement. Si cette option est activée, chaque fois que vous rencontrezparallel for
OpenMP créer le nombre de threads que défini dansOMP_NUM_THREADS
. Donc, si 2-niveau de parallélisme, le nombre total de threads serait N^2, où N =OMP_NUM_THREADS
.Tel parallélisme imbriqué sera la cause de la surcharge, (c'est à dire, le nombre de occupé fils est plus grand que les carottes), ce qui peut dégrader l'accélération. Dans un cas extrême, où le parallélisme imbriqué est appelée récursivement, les threads peuvent être bouffés (par exemple, la création de 1000 threads), et l'ordinateur déchets juste le temps pour le changement de contexte. Dans de tels cas, vous pouvez contrôler le nombre de threads de manière dynamique par la mise en
omp_set_dynamic
.(2) Un exemple de matrice-vecteur de multiplication: le code devrait ressembler à:
En général, la parallélisation de boucles internes tandis que les boucles externes sont possibles est mauvais à cause de la fourche/joindre à la surcharge de threads. (bien que beaucoup d'OpenMP implémentations de pré-créer des threads, il nécessite encore à l'expédition des tâches à des fils et à l'appel implicite de la barrière, à la fin de parallèle)
Votre préoccupation est le cas de N < nombre de CPU. Oui, oui, dans ce cas, l'accélération serait limitée par N, et de laisser parallélisme imbriqué aura certainement des avantages.
Cependant, le code serait la cause de la surcharge si N est suffisamment grand. Je pense simplement que les solutions suivantes:
omp_set_dynamic
. Mais, s'il vous plait soyez sûr de savoir commentomp_set_dynamic
contrôle le nombre de threads et de l'activité des threads. Les mises en œuvre peuvent varier.Pour quelque chose comme dense algèbre linéaire, où toutes les possibilités de parallélisme est déjà couché nu dans un lieu à nice à l'échelle pour les boucles, vous n'avez pas besoin imbriquée parallism -- si vous ne souhaitez protéger contre le boîtier de l'avoir (dire) vraiment étroites matricies où le leader de la dimension peut être plus petit que le nombre de noyaux, puis tous vous avez besoin est la l'effondrement directive qui théoriquement s'aplatit les boucles multiples en un seul.
Parallélisme imbriqué est pour le cas où le parallélisme n'est pas tous exposés à la fois -- dites que vous voulez faire 2 simultanée fonction des évaluations, chaque de ce qui pourrait être utile d'utiliser les 4 cœurs, et vous avez un 8 core. Vous appelez la fonction dans une section parallèle, et dans la définition de la fonction, il y a des, à dire, en parallèle.
À l'extérieur au niveau de l'utilisation de la NUM_THREADS(num_groups) de la clause pour définir le nombre de threads à utiliser. Si votre boucle externe a un nombre N, et le nombre de processeurs ou cœurs de num_cores, utilisez num_groups = min(N,num_cores). Au niveau interne, vous devez définir le nombre de sous-threads pour chaque groupe de thread, de sorte que le nombre total de sous-parties est égal au nombre de cœurs. Donc, si num_cores = 8, N = 4, alors num_groups = 4. Au plus bas niveau de chaque sous-thread doit utiliser 2 fils (depuis 2+2+2+2 = 8) il faut donc utiliser la NUM_THREADS(2) de la clause. Vous pouvez collecter le nombre de sous-threads dans un tableau avec un élément par région extérieure thread (avec num_groups éléments).
Cette stratégie permet une utilisation optimale de vos cœurs. Quand N < num_cores certains imbriquée parallélisation se produit. Quand N >= num_cores le tableau de subthread compte contient tous les 1 et donc la boucle interne est effectivement série.