5

I was wondering if there is any reason for preferring the private(var) clause in OpenMP over the local definition of (private) variables, i.e.

int var;
#pragma omp parallel private(var)
{
    ...
}

vs.

#pragma omp parallel
{
    int var;
    ...
}

Also, I'm wondering what's the point of private clauses then. This question was partially explained in OpenMP: are local variables automatically private?, but I don't like the answer since even C89 doesn't bar you from defining variables in the middle of functions as long as they are in the beginning of a scope (which is automatically the case when you enter a parallel region). So even for old-fashion C-programmers this shouldn't make any difference. Should I consider this as syntactic sugar that allows for a "define-variables-in-the-beginning-of-your-function" style as used in the good old days?

By the way: In my opinion the second version also prevents programmers from using private variables after the parallel region in the hope that it may contain something useful so another -1 for the private clause.

But since I'm quite new to OpenMP I don't want to question anything without having a good explanation for it. Thanks in advance for your answers!

andreee
  • 3,626
  • 16
  • 33
  • Possible duplicate of http://stackoverflow.com/questions/22790175/why-do-people-declare-iterated-values-before-loop-for-openmp (tldr, the first is C, the second is C++.) – IdeaHat May 27 '14 at 13:28
  • @MadScienceDreams: Loop variables in OpenMP `#pragma omp for` are automatically private. I understand that the link you referred to is related to a technical issue. This is why I was asking about "syntactic sugar". Is the private clause only for completeness or is there a real difference to defining variables within the parallel region? – andreee May 27 '14 at 13:35
  • 1
    possible duplicate of [OpenMP: are local variables automatically private?](http://stackoverflow.com/questions/6358375/openmp-are-local-variables-automatically-private) – Andro May 27 '14 at 13:43
  • 2
    "only for completeness" is misleading: you CANNOT (could not is probably more accurate) declare the variables inside the for loop in ANSI C. You HAD to declare them all up front. They HAD to have the private(var) declared in order to be private in the loop. – IdeaHat May 27 '14 at 13:45
  • @MadScienceDreams, that's not entirely correct. You could define them in a parallel region before the for loop without using a private construct. But you would not be able to use the shorthand `#pragma omp parallel for`. – Z boson May 27 '14 at 14:12
  • 1
    @andreee, in regards to your point that the second version is less error prone I agree. It's one of the reason I prefer it. Sometimes your option is to not change the code and be more error prone or change the code and be less error prone. You can't have it both ways in this case. – Z boson May 28 '14 at 08:06

1 Answers1

8

It's not just syntactic sugar. One of the features of OpenMP strives for is to not change the serial code if the code is not compiled with OpenMP. Any construct you use as part of a pragma is ignored if you don't compile with OpenMP. Doing this you can use things like private, firstprivaate, collapse, and parallel for without changing your code. Changing the code can affect for example how the code is optimized by the compiler.

If you have code like

int i,j;
#pragma omp parallel for private(j)
for(i = 0; i < n; i++) {
      for(j = 0; j < n; j++) {
   }
}

The only way to do this without private in C89 is to change the code by defining j inside the parallel section e.g:

int i,j;
#pragma omp parallel
{
    int j;
    #pragma omp for
    for(i = 0; i < n; i++) {
           for(j = 0; j < n; j++) {
        }
    }
}

Here's a C++ example with firstprivate. Let's say you have a vector which you want to be private. If you use firstprivate you don't have to change your code but if you declare a private copy inside the parallel region you do change your code. If you compile that without OpenMP it makes a unnecessary copy.

vector<int> a;
#pragma omp parallel {
    vector<int> a_private = a;
}

This logic applies to many other constructs. For example collapse. You could manually fuse a loop which changes your code or you can use collapse and only fuse it when compiled with OpenMP.

However, having said all that, in practice I find often that I need to change the code anyway to get the best parallel result so I usually define everything in parallel sections anyway and don't use features such as private, firstprivate, or collapse (not to mention that OpenMP implementations in C++ often struggle with non-POD anyway so it's often better to do it yourself).

Community
  • 1
  • 1
Z boson
  • 29,230
  • 10
  • 105
  • 195
  • 1
    +1. Indeed, achieving reasonable performance with minimal code changes is what drives OpenMP's development. – Hristo 'away' Iliev May 27 '14 at 20:08
  • @HristoIliev, I only figured this out recently. In fact, it was while writing my answer I realized that the purpose of `parallel for` was not to just to make the code shorter. – Z boson May 28 '14 at 08:09
  • 1
    @Zboson, thank you very much for this explanation. I think I will understand it even better after having some more experience with OpenMP, but this makes definitely more sense now. +1 :) – andreee May 28 '14 at 13:49
  • "The only way to do this..." is a bit too strongly worded :) You can actually declare `j` inside the `i`-loop and leave the declaration of `i` outside the parallel region. – Hristo 'away' Iliev Oct 16 '14 at 11:08
  • @HristoIliev, oh good point. Though in this case my general statement that you have to change the code is correct (you have to move `j` inside). – Z boson Oct 16 '14 at 11:12
  • I don't get it. Why don't you just declare the iteration variables ì,j` inside the initializationStatement? Like `for(int i=0; ...)` – handy Mar 20 '21 at 17:02
  • 1
    @handy because C89 does not allow that https://stackoverflow.com/a/1287867/2542702 – Z boson Apr 08 '21 at 07:04