2017-09-19 6 views
1

J'essaye de paralléliser une "boucle for" de mon code C/OpenMP, après déchargement de l'appel sur la carte Intel MIC (Xeon Phi). J'utilise "#pragma omp parallel for" et il compile bien quand j'utilise une variable entière comme "variable de contrôle de boucle". Sur mon code j'utilise un tableau flottant comme "variable de contrôle de boucle" et ensuite j'obtiens l'erreur "la condition de boucle parallèle ne teste pas la variable de contrôle de boucle".ICC compilateur - erreur: condition de boucle parallèle ne teste pas la variable de contrôle de boucle

Code avec aucune erreur:

#define MAX_DIMENSIONS 10 

unsigned long long i,y=0; 

#pragma offload target(mic) in(i,y) 
{ 
    #pragma omp parallel for 
    for(i=0;i<10;i++) 
     /* code here */ 
} 

Code avec erreur:

#define MAX_DIMENSIONS 10 

float x[MAX_DIMENSIONS]; 
unsigned long long i,y=0; 

#pragma offload target(mic) in(x[MAX_DIMENSIONS],i,y) 
{ 
    #pragma omp parallel for 
    for(x[0]=0.000000; x[0]<10.000000; x[0]+=1.000000) 
     /* code here */ 
} 

Est-il possible de conserver cette notation de tableau flottant dans « boucle » pour réussir la parallélisation en utilisant OpenMP ?

+0

Copie possible de [OpenMP parallel pour avec plage à virgule flottante] (https: // stackoverflow.com/questions/14418908/openmp-parallel-for-with-floating-point-range) – osgx

Répondre

2

Vous pouvez mettre en œuvre le travail de partage manuellement comme celui-ci

#pragma omp parallel 
{ 
    float a = 0., b = 10.; 
    float step = 1.; 
    int N = (b-a)/step; 
    int ithread = omp_get_thread_num(); 
    int nthreads = omp_get_num_threads(); 
    float t0 = (ithread+0)*N/nthreads + a; 
    float t1 = (ithread+1)*N/nthreads + a; 
    for(float x=t0; x<t1; x += step) { 
     //code 
    } 
} 

Cela équivaudrait à

#pragma omp parallel for 
for(float x=a; x<b; x += step) 

si la construction omp for flottante itérateurs a appuyé points. Pour les autres horaires tels que dynamique, vous devez les implémenter différemment. Notez qu'il est possible que le code parallèle et le code séquentiel ne donnent pas le même résultat par ex. si (b-a)/step a une partie fractionnaire (mais (10.-0)/1. = 10. est correct). Par conséquent, il est probablement préférable de changer votre code pour utiliser des itérateurs entiers pour être sûr.

+0

Fait N fois d'incrément float (' float x; pour (; i osgx

+1

@osgx, je pense qu'il y a plusieurs cas où ce n'est pas équivalent en réalité. L'une des plus importantes est que sum (x) sur n termes n'est pas en général le même que x x (c'est-à-dire que l'addition répétée n'est pas équivalente à la multiplication) pour l'arithmétique en virgule flottante. Pour les entiers ce n'est pas un problème mais pour les flottants c'est. Je voulais juste donner une réponse pour montrer qu'il est possible de faire du partage de travail avec des itérateurs à virgule flottante avec OpenMP si on veut vraiment faire ça. –

+0

Je voulais vraiment travailler avec des itérateurs à virgule flottante avec OpenMP et cette solution fonctionne parfaitement sur mon code. C'était exactement ce dont j'avais besoin. Je vous remercie! – wasilis

4

OpenMP nécessite variable de boucle pour être de type entier:

http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=68

The syntax of the loop construct is as follows:

#pragma omp for ... 
for-loops 

...

Specifically, all associated for-loops must have canonical loop form (see Section 2.6 on page 53).

3 The iteration count for each associated loop is computed before entry to the outermost loop. If execution of any associated loop changes any of the values used to compute any of the iteration counts, then the behavior is unspecified.

6 The integer type (or kind, for Fortran) used to compute the iteration count for the collapsed loop is implementation defined.

Vous ne pouvez pas utiliser des variables de type flottant dans la construction en boucle OpenMP. Votre première boucle a i entier qui est correct et la seconde a float variable typée qui est incorrecte. sous forme de boucle Canonical défini dans « 2.6 Canonique forme de boucle » - http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=62 comme

for (init-expr; test-expr; incr-expr) structured-block 
... 
var - One of the following: 
* A variable of a signed or unsigned integer type. 
* For C++, a variable of a random access iterator type. 
* For C, a variable of a pointer type 

incr-expr One of the following: 
... 
* var += incr 

incr A loop invariant integer expression 

et votre deuxième boucle n'a pas la forme canonique et ne peut être mis en parallèle.

#pragma omp parallel for 
for(x[0]=0.000000; x[0]<10.000000; x[0]+=1.000000) 

Il sera difficile de compilateur pour obtenir boucle nombre d'itérations à l'avance avec des valeurs en virgule flottante de var et INCR: certaines constantes décimales ne peuvent pas être représentées exactement au format virgule flottante (par exemple, 0,2 à virgule flottante est 0f3FC999999999999A et 0,1 + 0,2 est 0,30000000000000004 dans de nombreuses langues, vérifiez https://0.30000000000000004.com/).

Vous pouvez essayer tableau d'entiers ou long s ou long long s:

#define MAX_DIMENSIONS 10 

long long x[MAX_DIMENSIONS]; 
unsigned int i,y=0; 

#pragma offload target(mic) in(x[MAX_DIMENSIONS],i,y) 
{ 
    #pragma omp parallel for 
    for(x[0]=0; x[0] < 10; x[0] += 1) 
     /* code here */ 
} 

Ou vous pouvez essayer d'estimer le nombre de boucles correct pour une plage de virgule flottante avant boucle et utiliser ensuite les itérateurs entiers dans la boucle parallèle var et incr (assurez-vous de bien arrondir).

+0

En fait le code inclut plusieurs "for loops" imbriquées de cette façon, et fonctionne très bien dans une autre édition du code pour la parallélisation dans CUDA ou dans exécution en série. La seule façon d'utiliser correctement OpenMP est donc de changer la structure de mes "for loops". Merci pour votre réponse! – wasilis

+1

wasilis, vérifiez aussi http://www.openmp.org/wp-content/uploads/openmp-4.5.pdf#page=62 "2.6 Formulaire de boucle canonique", c'est la définition de la forme de boucle requise après '#pragma omp pour ', et seulement autorisé sont: type entier, type d'itérateur à accès aléatoire (C++), et type de pointeur (et incrément du type ptrdiff_t) – osgx