B10 - functions in parallel regions
- just because an OpenMP loop is parallelized correctly doesn't mean the functions called inside it are safe to execute concurrently
- functions can be called from inside a thread
- issues can arise if the function accesses shared data
thread-safe
- a function that can be called concurrently by multiple threads without causing incorrect behaviour due to unsynchronized shared state
// thread-safe
int square(int x) {
int result = x * x;
return result;
}
//not thread-safe
int counter = 0; // global variable
void increment() {
counter++; //concurrent increments cause data race
}
- OpenMP data-sharing clauses do not automatically make every variable used by a called function private
int x = 10;
void work() {
int y = 5;
x += y;
}
#pragma omp parallel private(x)
{
work(); // x in the function will not be private
}
threadprivategives each thread its own copy of a global or static variable
#include <stdio.h>
#include <omp.h>
int counter = 0;
#pragma omp threadprivate(counter)
void increment() {
counter++;
}
int main() {
#pragma omp parallel num_threads(4)
{
increment();
printf("Thread %d: counter = %d\n",
omp_get_thread_num(), counter);
}
return 0;
}
threadprivatevariables have special initialization and persistence rules.- a global initialized to zero is initialized for each thread, but a thread's copy may persist across parallel regions under the conditions specified by OpenMP
// thread-safe if len(a) >= 100
void update(int a[], int i) {
a[i] = a[i] + 1; // each iteration modifies a different element
}
// not thread-safe
void update(int a[], int i) {
a[i] = a[i] + a[i-1]; // a[i-1] is modified by a different thread
}
-
for the second function, although every call receives different indices, the operations are not independent
-
hence, it is important to examine the function's code
-
branches out of parallel regions are not allowed
int main() {
#pragma omp parallel
{
return 0; // invalid
}
}