[openmp] omp parallel vs. omp parallel for

What is the difference between these two?

[A]

#pragma omp parallel
{ 
    #pragma omp for
    for(int i = 1; i < 100; ++i)
    {
        ...
    }
}

[B]

#pragma omp parallel for
for(int i = 1; i < 100; ++i)
{
   ...
}

This question is related to openmp

The answer is


There are obviously plenty of answers, but this one answers it very nicely (with source)

#pragma omp for only delegates portions of the loop for different threads in the current team. A team is the group of threads executing the program. At program start, the team consists only of a single member: the master thread that runs the program.

To create a new team of threads, you need to specify the parallel keyword. It can be specified in the surrounding context:

#pragma omp parallel
{
   #pragma omp for
   for(int n = 0; n < 10; ++n)
   printf(" %d", n);
}

and:

What are: parallel, for and a team

The difference between parallel, parallel for and for is as follows:

A team is the group of threads that execute currently. At the program beginning, the team consists of a single thread. A parallel construct splits the current thread into a new team of threads for the duration of the next block/statement, after which the team merges back into one. for divides the work of the for-loop among the threads of the current team.

It does not create threads, it only divides the work amongst the threads of the currently executing team. parallel for is a shorthand for two commands at once: parallel and for. Parallel creates a new team, and for splits that team to handle different portions of the loop. If your program never contains a parallel construct, there is never more than one thread; the master thread that starts the program and runs it, as in non-threading programs.

https://bisqwit.iki.fi/story/howto/openmp/


These are equivalent.

#pragma omp parallel spawns a group of threads, while #pragma omp for divides loop iterations between the spawned threads. You can do both things at once with the fused #pragma omp parallel for directive.


Although both versions of the specific example are equivalent, as already mentioned in the other answers, there is still one small difference between them. The first version includes an unnecessary implicit barrier, encountered at the end of the "omp for". The other implicit barrier can be found at the end of the parallel region. Adding "nowait" to "omp for" would make the two codes equivalent, at least from an OpenMP perspective. I mention this because an OpenMP compiler could generate slightly different code for the two cases.


I am seeing starkly different runtimes when I take a for loop in g++ 4.7.0 and using

std::vector<double> x;
std::vector<double> y;
std::vector<double> prod;

for (int i = 0; i < 5000000; i++)
{
   double r1 = ((double)rand() / double(RAND_MAX)) * 5;
   double r2 = ((double)rand() / double(RAND_MAX)) * 5;
   x.push_back(r1);
   y.push_back(r2);
}

int sz = x.size();

#pragma omp parallel for

for (int i = 0; i< sz; i++)
   prod[i] = x[i] * y[i];

the serial code (no openmp ) runs in 79 ms. the "parallel for" code runs in 29 ms. If I omit the for and use #pragma omp parallel, the runtime shoots up to 179ms, which is slower than serial code. (the machine has hw concurrency of 8)

the code links to libgomp


Here is example of using separated parallel and for here. In short it can be used for dynamic allocation of OpenMP thread-private arrays before executing for cycle in several threads. It is impossible to do the same initializing in parallel for case.

UPD: In the question example there is no difference between single pragma and two pragmas. But in practice you can make more thread aware behavior with separated parallel and for directives. Some code for example:

#pragma omp parallel
{ 
    double *data = (double*)malloc(...); // this data is thread private

    #pragma omp for
    for(1...100) // first parallelized cycle
    {
    }

    #pragma omp single 
    {} // make some single thread processing

    #pragma omp for // second parallelized cycle
    for(1...100)
    {
    }

    #pragma omp single 
    {} // make some single thread processing again

    free(data); // free thread private data
}