OpenMP - start a new thread in each iteration of the loop

I'm having trouble adjusting my thinking in accordance with OpenMP principles.

Roughly speaking, I want:

for(int i=0; i<50; i++) { doStuff(); thread t; t.start(callback(i)); //each time around the loop create a thread to execute callback } 

I think I know how this will be done in C ++ 11, but I need to do something similar with OpenMP.

+4
source share
2 answers

Closest to what you want is OpenMP tasks, available in compatible OpenMP v3.0 compilers and later. It looks like this:

 #pragma omp parallel { #pragma omp single for (int i = 0; i < 50; i++) { doStuff(); #pragma omp task callback(i); } } 

This code will make the loop run in only one thread, and it will create 50 OpenMP tasks that will call callback() with different parameters. Then he will wait for the completion of all tasks before leaving the parallel area. Tasks will be selected (possibly randomly) by the idle threads that will be executed. OpenMP imposes an implicit barrier at the end of each parallel region, because its fork model provides that only the main thread runs outside the parallel regions.

Here is an example program ( ompt.cpp ):

 #include <stdio.h> #include <unistd.h> #include <omp.h> void callback (int i) { printf("[%02d] Task stated with thread %d\n", i, omp_get_thread_num()); sleep(1); printf("[%02d] Task finished\n", i); } int main (void) { #pragma omp parallel { #pragma omp single for (int i = 0; i < 10; i++) { #pragma omp task callback(i); printf("Task %d created\n", i); } } printf("Parallel region ended\n"); return 0; } 

Compilation and execution:

 $ g++ -fopenmp -o ompt.x ompt.cpp $ OMP_NUM_THREADS=4 ./ompt.x Task 0 created Task 1 created Task 2 created [01] Task stated with thread 3 [02] Task stated with thread 2 Task 3 created Task 4 created Task 5 created Task 6 created Task 7 created [00] Task stated with thread 1 Task 8 created Task 9 created [03] Task stated with thread 0 [01] Task finished [02] Task finished [05] Task stated with thread 2 [04] Task stated with thread 3 [00] Task finished [06] Task stated with thread 1 [03] Task finished [07] Task stated with thread 0 [05] Task finished [08] Task stated with thread 2 [04] Task finished [09] Task stated with thread 3 [06] Task finished [07] Task finished [08] Task finished [09] Task finished Parallel region ended 

Note that tasks are not performed in the same order in which they were created.

GCC does not support OpenMP 3.0 in versions older than 4.4. Unrecognized OpenMP directives are silently ignored, and as a result, the executable will have the following code:

 $ g++-4.3 -fopenmp -o ompt.x ompt.cpp $ OMP_NUM_THREADS=4 ./ompt.x [00] Task stated with thread 3 [00] Task finished Task 0 created [01] Task stated with thread 3 [01] Task finished Task 1 created [02] Task stated with thread 3 [02] Task finished Task 2 created [03] Task stated with thread 3 [03] Task finished Task 3 created [04] Task stated with thread 3 [04] Task finished Task 4 created [05] Task stated with thread 3 [05] Task finished Task 5 created [06] Task stated with thread 3 [06] Task finished Task 6 created [07] Task stated with thread 3 [07] Task finished Task 7 created [08] Task stated with thread 3 [08] Task finished Task 8 created [09] Task stated with thread 3 [09] Task finished Task 9 created Parallel region ended 
+7
source

For example, see http://en.wikipedia.org/wiki/OpenMP .

#pragma omp for

- your friend. OpenMP doesn't need you to think about streaming. You simply declare (!) That you want to run in parallel, and the OpenMP-compatible compiler performs the necessary transformations in your code at compile time.

The OpenMP specifications are also very useful. They explain well what can be done and how: http://openmp.org/wp/openmp-specifications/

Your sample might look like this:

 #pragma omp parallel for for(int i=0; i<50; i++) { doStuff(); thread t; t.start(callback(i)); //each time around the loop create a thread to execute callback } 

Everything in the for loop runs in parallel. You should pay attention to data dependency. The doStuff () function is executed sequentially in your pseudo-code, but will be executed in parallel in my example. You also need to specify which variables are private threads and something like this, which will also go into the #pragma statement.

0
source

All Articles