Usage of openMP Shared clause in C++ - c++

According to this
All variables defined outside a parallel construct become shared when the parallel region is encountered.
I am wondering what would be the usage of openMP Shared clause while developing in C++.

Even if variables are shared by default, the default can be changed by the default() clause. When you have default(none) or default(private) you have to declare shared variables explicitly.
There many many uses for shared variables.
A large array is typically used shared and different threads are operating on a different part of the array.
Or a configuration parameter which you are only reading, not modifying, that can be shared.
Or a global variable defining some state or a flag even if you are changing that under some condition. You would have it shared and change it in a critical or single section.

Related

C++ plugin loaded in runtime with static global variable

I have a library loaded in runtime. The library contains const static variable e.g. std::map of objects.
I load and unload this library multiple times in runtime using multiple threads.
And GCC thread sanitizer complains that threads have data races regarding this object. E.g. while one thread removes the object, second one creates new one - they conflict with the std::map. I wonder if shared library loaded multiple times have the same addresses for global variables, functions?
Have can I make the code thread safe in this case?
Where can I read about it?

OpenMP race condition while reading from pointer

I know that reading from a shared variable in OpenMP does not cause a race condition, because every thread has it's own copy of that variable.
But if the shared variable is a pointer (e.g. to a container), then every thread only gets a copy of the pointer.
If I now read from the location the pointer is pointing to (my container), can there be race conditons or does OpenMP somehow take care of this?
Is it better to share a copy of the container itself, instead of a pointer to it, among threads?
Just reading from a variable cannot produce a race condition: it doesn't matter whether the variable is shared or not. To produce a race condition you need to have two or more threads trying to modify the same instance of a variable at the same time.
Then, assuming that your threads are reading and modifying a certain variable, if you make this variable shared you will still have a race condition since all the threads share the same instance. I guess that in your first paragraph you wanted to say private, as #ilotXXI pointed out.
About your question about privatizing a pointer, if two o more instances of that pointer point to the same data and they modify it, you will have a race condition (each thread has a private version of the pointer but not a private version of the data).
Note that changing from one data-sharing clause to another may change the behavior of your application. Thus, in general, when you are parallelizing an application, what you have to do first is to analyze which kind of data accesses your application is performing. Once you know that, you have to think which data-sharing clauses and which synchronization constructs (if needed) you should use to keep the original behavior of your application.

Are local variables in procedures automatically private when using OpenMP?

I am relatively new to using OpenMP with Fortran 90. I know that local variables in called subroutines are automatically private when using a parallel do loop. Is the same true for functions that are called from the parallel do loop? Are there any differences between external functions and functions defined in the main program?
I would assume that external functions behave the same as subroutines, but I am specifically curious about functions in main program. Thanks!
The local variables of a procedure (function or subroutine) called in the OpenMP parallel region are private if the procedure is recursive, or an equivalent compiler option is enabled (mostly it is automatic when enabling OpenMP) provided the variable is not save.
If it has the save attribute (explicit or implicit from an initialization) it is shared between all invocations. It doesn't matter if you call it from a worksharing construct (omp do, omp sections,...) or directly from the omp parallel region.
It also doesn't matter whether the procedure is external, a module procedure or internal (which you confusingly call "in the main program").

the behavior of omp critical with nested level of parallelism

Considering the following scenario:
Function A creates a layer of OMP parallel region, and each OMP thread make a call to a function B, which itself contain another layer of OMP parallel region.
Then if within the parallel region of function B, there is a OMP critcal region, then, does that region is critical "globally" with respect to all threads created by function A and B, or it is merely locally to function B?
And what if B is a pre-bulit function (e.g. static or dynamic linked libraries)?
Critical regions in OpenMP have global binding and their scope extends to all occurrences of the critical construct that have the same name (in that respect all unnamed constructs share the same special internal name), no matter where they occur in the code. You can read about the binding of each construct in the corresponding Binding section of the OpenMP specification. For the critical construct you have:
The binding thread set for a critical region is all threads. Region execution is restricted to a single thread at a time among all the threads in the program, without regard to the team(s) to which the threads belong.
(HI: emphasis mine)
That's why it is strongly recommended that named critical regions should be used, especially if the sets of protected resources are disjoint, e.g.:
// This one located inside a parallel region in fun1
#pragma omp critical(fun1)
{
// Modify shared variables a and b
}
...
// This one located inside a parallel region in fun2
#pragma omp critical(fun2)
{
// Modify shared variables c and d
}
Naming the regions eliminates the chance that two unrelated critical construct could block each other.
As to the second part of your question, to support the dynamic scoping requirements of the OpenMP specification, critical regions are usually implemented with named mutexes that are resolved at run-time. Therefore it is possible to have homonymous critical regions in a prebuilt library function and in your code and it will work as expected as long as both codes are using the same OpenMP runtime, e.g. both were built using the same compiler suite. Cross-suite OpenMP compatibility is usually not guaranteed. Also if in B() there is an unnamed critical region, it will interfere with all unnamed critical regions in the rest of the code, no matter if they are part the same library code of belong to the user code.

Parallelizing a library with lots of global variables

I'm currently using QT (4) to parallelize a non-threadsafe library that's written in C by non-programmers, and thus has a lot of global variables. The threads don't need to interact or share data, they each just call a bunch of methods of the library and then at the end the library gives an output that is used further.
The problem is, though, that global variables are per default shared between threads, causing the library to crash in different places. There are two ways to fix this:
Refactor the entire library to not use global variables (ouch), or find a way to make global variables non-shared, or find a third magic way.
Is the latter an option with QT or standard (C++01) C++?
Using thread local storage is a way to make global variables non-shared. Starting point for that, with links to details for different implementations:
http://en.wikipedia.org/wiki/Thread-local_storage
You can't "unshare" global variables. The only available option for parallelization (bar refactoring) is to have multiple processes instead of multiple threads. Preferably pooled.
Create a singleton that is responsible for synchronizing the access to the global variables. The global variables become members of the new singleton class and can be accessed by methods that have the same names as your current global variables so you don't need to change code all over the place.