2017-09-06 12 views
0

Tous les exemples de didacticiels pour openmp que je vois sont pour créer des threads pour les boucles for. Mais j'ai besoin de créer des threads pour des groupes d'instructions ordinaires qui peuvent être regroupés en fonctions. par exemple, quelque chose comme ce qui suit:créer des threads openmp pour les fonctions

#include <stdio.h> 
#include <omp.h> 
int A() { printf("in A:%d\n", omp_get_thread_num()); } 
int B() { printf("in B:%d\n", omp_get_thread_num()); } 
int D() { printf("in D:%d\n", omp_get_thread_num()); } 
int E() { printf("in E:%d\n", omp_get_thread_num()); } 
int F() { printf("in F:%d\n", omp_get_thread_num()); } 
int G() { printf("in G:%d\n", omp_get_thread_num()); } 
int H() { printf("in H:%d\n", omp_get_thread_num()); } 
int C() { 
    printf("in C:%d\n", omp_get_thread_num()); 
    #pragma omp parallel num_threads(2) 
    { 
     D(); // want to execute D,E in separate threads 
     E(); 
    } 
    F(); 
} 
main() { 
    omp_set_nested(1); 
    printf("in main:%d\n", omp_get_thread_num()); 
    G(); 
    #pragma omp parallel num_threads(3) 
    { 
     A(); // want to execute A,B,C in separate threads 
     B(); 
     C(); 
    } 
    H(); 
} 

Dans le code ci-dessus, je veux chaque fonction d'exécuter une seule fois, mais dans différents threads. (Je peux donc me tromper dans le code ci-dessus avec l'utilisation des directives, veuillez le corriger si nécessaire.)

Comment coder ce type de parallélisme imbriqué de fonctions avec openmp? Ces fonctions partageront-elles toutes les variables globales disponibles ou existe-t-il un moyen de spécifier quelles variables seront partagées par quelles fonctions? Après avoir lu la réponse de Jorge Bellon ci-dessous, j'ai codé ce qui suit, et sa sortie est affichée après le code. On dirait que le thread-0 est utilisé pour beaucoup de fonctions, ce qui n'est pas ce que je voulais - je veux que les fonctions soient exécutées en parallèle. De plus, je ne veux qu'une seule exécution pour G, donc je dois supprimer la ligne "num_threads (3)". Faites-moi savoir quelle est la solution à ce problème.

// compile this with: g++ -fopenmp 
int A() { printf("in H:%d\n", omp_get_thread_num()); sleep(1); } 
// similarly for B, D, E, F, G, H 
int C() { 
    printf("in C:%d\n", omp_get_thread_num()); sleep(1); 
    #pragma omp task 
    D(); 
    #pragma omp task 
    E(); 
    #pragma omp taskwait 
    F(); sleep(1); 
} 
main() { 
    omp_set_nested(1); 
    printf("in main:%d\n", omp_get_thread_num()); 
    #pragma omp parallel num_threads(3) 
    G(); 
    #pragma omp task 
    A(); 
    #pragma omp task 
    B(); 
    #pragma omp task 
    C(); 
    #pragma omp taskwait 
    H(); 
} 
// outputs: 
in main:0 
in G:1 
in G:0 
in G:2 
in A:0 
in B:0 
in C:0 
in D:0 
in E:0 
in F:0 
in H:0 

Répondre

1

La meilleure façon de paralléliser ce genre de code est d'utiliser OpenMP task constructions. Votre région parallèle créera un pool de threads, un thread principal créera les tâches externes et le reste des threads traitera ces tâches dès qu'elles seront disponibles. Le fait que chaque fonction soit exécutée dans un thread différent dépend entièrement de l'état du programme au moment de l'exécution. Cela signifie que certaines tâches peuvent être exécutées dans le même thread si tous les autres threads sont occupés, ce qui n'est pas particulièrement un problème.

Vous pouvez utiliser task dependences (à partir d'OpenMP 4) pour contrôler si une tâche peut être exécutée au moment de sa création.

+0

Merci. J'ai essayé votre solution, mais on dirait que je n'ai qu'un seul fil. Pls voir les détails ajoutés dans la question ci-dessus. – R71

+0

Je n'ai pas besoin que les tâches continuent au-delà d'une jointure locale, donc je n'ai pas besoin des détails des dépendances de tâches. – R71

+0

Vous devez spécifier la portée que les threads vont exécuter en parallèle. Dans le code basé sur les tâches que vous montrez, la portée parallèle est seulement 'G();'. Vous devez utiliser des crochets angulaires '{}' (voir mon exemple) pour définir que la partie parallèle inclura toutes les lignes suivantes jusqu'à la fin de la fonction principale. Pour savoir si les tâches sont exécutées en parallèle, ajoutez la valeur de retour 'get_thread_num()' à 'printf', afin de savoir quel thread exécute cette tâche. –

0

La solution suivante est implémentée avec des threads C++ 11. Une version détaillée d'openmp est encore à élaborer.

// compile this with: g++ -pthread -std=gnu++0x 
#include <stdio.h> 
#include <unistd.h> // for sleep 
#include <thread> 
#include <iostream> 
#include <sstream> 
using namespace std; 
int A() { stringstream ss; ss << this_thread::get_id(); 
      printf("in A:%s\n", ss.str().c_str()); sleep(1); } 
// similarly for B, D, E, F, G, H 
int C() { 
    stringstream ss; ss << this_thread::get_id(); 
    printf("in C:%s\n", ss.str().c_str()); sleep(1); 
    std::thread thread_1(D); 
    std::thread thread_2(E); 
    thread_1.join(); 
    thread_2.join(); 
    F(); sleep(1); 
} 
main() { 
    printf("in main\n"); 
    G(); 
    std::thread thread_1(A); 
    std::thread thread_2(B); 
    std::thread thread_3(C); 
    thread_1.join(); 
    thread_2.join(); 
    thread_3.join(); 
    H(); 
} 
// outputs: 
in main 
in G:0x600000060 
in A:0x60005aa10 
in B:0x60005ab10 
in C:0x60005ae40 
in D:0x60005af40 
in E:0x60005b040 
in F:0x60005ae40 
in H:0x600000060