Solution élégante (et typique) pour la réduction OpenMP sur les variables complexes en C++?

je me rends compte que la réduction n'est utilisable que pour les types de pods en C++. Que feriez-vous pour mettre en œuvre une réduction pour un accumulateur de type complexe?

complex<double> x(0.0,0.0), y(1.0,1.0);
#pragma omp parallel for reduction(+:x)
for(int i=0; i<5; i++)
{
    x += y;
}

(sachant que j'ai peut-être laissé quelques syntaxe). Il semble qu'une solution évidente serait de diviser les composants réels et imaginaires en doubles temporaires, puis de les accumuler. Je suppose que je cherche de l'élégance, et c'est ce qu'on dirait ... moins jolie. Serait-ce l'approche typique ici?

16
demandé sur alain.janinm 2011-08-23 19:28:55

2 réponses

typique solution de contournement en l'absence de réductions définies par l'utilisateur dans OpenMP est encore plus laid que ce que vous avez suggéré. Habituellement, avant la région parallèle, les gens créent un tableau d'au moins autant d'éléments qu'il y aura de threads dans la région, accumulent des résultats partiels séparément pour chaque thread en utilisant omp_get_thread_num() comme un index au tableau, et faire la réduction finale des résultats cumulés dans une boucle après la région parallèle.

autant que je sache, OpenMP le Comité linguistique travaille à l'ajout de réductions définies par l'utilisateur à la spécification, donc peut-être qu'il sera finalement résolu dans quelques années.

9
répondu Alexey Kukanov 2011-08-24 06:24:52

Désolé, OpenMP ne supporte tout simplement pas cela en ce moment. Malheureusement, vous devez faire la réduction parallèle d'une manière laide ce que vous avez déjà décrit.

cependant, si une telle réduction parallèle est vraiment fréquente, j'aimerais faire un constructeur similaire à parallel_reduce dans TBB. La mise en œuvre d'une telle construction est assez simple. Cilk plus a un objet réducteur plus puissant, mais je n'ai pas vérifié s'il supporte non POD.

POUR INFORMATION, ce type de restriction peut également être trouvés dans threadprivate pragma. J'ai testé avec VC++ 2008/2010 et les compilateurs Intel (icc). VC++ ne peut pas soutenir threadprivate avec une struct/classe a un constructeur ou un destructeur (ou une variable scalaire qui nécessite l'appel de fonction pour être initialisé), en lançant un message d'erreur: erreur C3057, "dynamique de l'initialisation de l' 'threadprivate " symboles". Vous pouvez la lire ce lien MSDN. Toutefois, la CCI est d'accord avec le cas de L'affaire C3057. Vous pouvez voir, au moins, deux majeurs les implémentations sont différents.

je suppose que supporter la réduction parallèle sur les non-POD aurait le même problème ci-dessus. Afin de soutenir la réduction parallèle, chaque section parallèle devrait attribuer une variable thread-local pour une variable de réduction. Ainsi, si une variable de réduction donnée est non-POD, ils peuvent avoir besoin d'appeler le constructeur défini par l'utilisateur.Cela rend le même problème que j'ai mentionné dans le cas de C3057.

4
répondu minjang 2011-08-23 17:56:37