2015-09-18 4 views
-1

Je souhaite utiliser la directive reduction dans openmp, mais cela ne fonctionne pas. Erreur de compilation dit:Comment utiliser la variable vectorielle de réduction dans OpenMP?

"réduction: 'parallèle' OpenMP facteur vide dans la directive" (Visual Studio communautaire 2015)

ou

« réduction:^variable scalaire nécessaire "

Ceci est mon code (octet est unsigned char)

void RotXOR (const Byte *s, int n, Byte *t) 
{ 
    int i = 0, q; 
    q = n/8; n %= 8; 

    #pragma omp parallel for private(i) reduction() 
    for (i = 0; i < 16; i++) { 
     t[(q + i) % 16] ^= (s[i] >> n); 

     if (n != 0) { 
      t[(q + i + 1) % 16] ^= (s[i] << (8 - n)); 
     } 
    } 
} 

Répondre

1

De OpenMP 4.0 P171 standard pour C/C++:

Les tableaux ne peuvent pas apparaître dans une clause de réduction.

La seule façon de le faire serait de créer un tableau local par thread « tt » initialisées à 0, pour calculer le dessus et mettre à jour t avec tt atomiquement à la sortie de la section parallèle. Mais indépendamment de cela, puisque votre compte de déclenchement de boucle n'est que de 16, le temps de parallélisation serait bien supérieur à tout gain potentiel, donc, de mon point de vue, c'est juste une impasse.


EDIT: c'est ce que j'avais à l'esprit:

void RotXOR(const Byte *s, int n, Byte *t) { 
    int q = n/8; 
    n %= 8; 

    #pragma omp parallel 
    { 
     int tt[] = { 0, 0, 0, 0, 
        0, 0, 0, 0, 
        0, 0, 0, 0, 
        0, 0, 0, 0 }; 
     #pragma omp for 
     for (int i = 0; i < 16; i++) { 
      tt[(q + i) % 16] ^= (s[i] >> n); 
      if (n != 0) { 
       tt[(q + i + 1) % 16] ^= (s[i] << (8 - n)); 
      } 
     } 
     #pragma omp critical 
     for (int i = 0; i < 16; i++) { 
      t[i] ^= tt[i]; 
     } 
    } 
} 

Et je dit que je ne pense pas beaucoup d'amélioration de la performance (le cas échéant) parce que le nombre de voyage étant très petit, pas beaucoup de travail peut être réparti entre les threads pour cacher le surcoût de la gestion des threads, et la réduction finale séquentielle. Pendant que j'écrivais cette solution, une autre me venait à l'esprit, mais je ne sais pas laquelle des deux fonctionnerait le mieux ... Je soupçonne que la deuxième version sera encore pire que la première en raison des lourdes charges de synchronisation et faux partage de t, mais je ne suis pas sûr ...

void RotXOR(const Byte *s, int n, Byte *t) { 
    int q = n/8; 
    n %= 8; 

    #pragma omp parallel for 
    { 
     for (int i = 0; i < 16; i++) { 
      int idx = (q + i) % 16; 
      int val = s[i] >> n; 
      #pragma omp atomic 
      t[idx] ^= val; 
      if (n != 0) { 
       idx = (q + i + 1) % 16; 
       val = s[i] << (8 - n); 
       #pragma omp atomic 
       t[idx] ^= val; 
      } 
     } 
    } 
} 

et enfin, puisque la valeur de n est connue lors de l'entrée, je suppose que la suppression de la déclaration if de la boucle serait une bonne idée , même si cela implique d'écrire un peu plus de code.

+0

Merci pour la réponse, edting! Mais j'ai une autre question, vous voulez dire, comme ce code ?? oh je ne sais pas bloc de code dans le commentaire :( \t temp octet [16 * 17]; \t #pragma omp parallèle privé (i) \t for (i = 0; i <16; i ++) { \t \t temp [(q + i)% 16] = t [(q + i)% 16]; \t \t temp [(q + i)% 16]^= (s [i] >> n); \t \t #pragma omp critique \t \t { \t \t \t t [(q + i)% 16] = temp [(q + i)% 16]; \t \t} –

+0

Merci pour votre réponse et préoccupation! c'est très utile! Merci encore! –