Parallèle pendant un certain temps en utilisant OpenMP sur C

J’essaie de faire un parallèle pendant un moment, quelque chose comme ça:

while(!End){ for(...;...;...) // the parallel for ... // serial code } 

La boucle for est la seule section parallèle de la boucle while. Si je fais cela, j’ai beaucoup de frais généraux:

 cycles = 0; while(!End){ // 1k Million iterations aprox #pragma omp parallel for for(i=0;i<N;i++) // the parallel for with 256 iteration aprox if(time[i] == cycles){ if (wbusy[i]){ wbusy[i] = 0; wfinished[i] = 1; } } // serial code ++cycles; } 

Chaque itération de la boucle for est indépendante les unes des autres.

Il existe des dépendances entre le code série et le code parallèle.

Donc, normalement, il n’est pas nécessaire de s’inquiéter de la mise en boucle de régions parallèles, car les implémentations openmp modernes sont assez efficaces pour utiliser des éléments tels que les équipes de threads et tant que le travail est long, tout va bien. Mais ici, avec un nombre de boucles extérieures de ~ 1e9 et un nombre de boucles intérieures de ~ 256 – et très peu de travail effectué par itération – les frais généraux sont probablement comparables ou inférieurs au volume de travail effectué et les performances en souffriront.

Donc, il y aura une différence notable entre ceci:

 cycles = 0; while(!End){ // 1k Million iterations aprox #pragma omp parallel for for(i=0;i 

et ça:

 cycles = 0; #pragma omp parallel while(!End){ // 1k Million iterations aprox #pragma omp for for(i=0;i 

Mais vraiment, cette parsing sur le tableau temporel à chaque itération est malheureusement à la fois (a) lente et (b) pas assez de travail pour occuper plusieurs cœurs - elle nécessite beaucoup de mémoire. Avec plus de deux threads, les performances seront moins bonnes qu'en série, même sans surcharge, uniquement à cause des conflits de mémoire. Certes, ce que vous avez posté ici n'est qu'un exemple, pas votre vrai code, mais pourquoi ne pré-traitez-vous pas le tableau temporel pour pouvoir vérifier si la prochaine tâche est prête à être mise à jour:

 #include  #include  struct tasktime_t { long int time; int task; }; int stime_compare(const void *a, const void *b) { return ((struct tasktime_t *)a)->time - ((struct tasktime_t *)b)->time; } int main(int argc, char **argv) { const int n=256; const long int niters = 100000000l; long int time[n]; int wbusy[n]; int wfinished[n]; for (int i=0; i 

C'est environ 5 fois plus rapide que la version série de l'approche de numérisation (et beaucoup plus rapide que les versions OpenMP). Même si vous mettez constamment à jour les tableaux time / wbusy / wfinished dans le code série, vous pouvez suivre leurs temps d’achèvement à l’aide d’une file d' attente prioritaire, chaque mise à jour prenant O (ln (N)) au lieu d'parsingr chaque itération prenant O N) le temps.