Home > database >  restrict pointers as function arguments in OpenMP for loops?
restrict pointers as function arguments in OpenMP for loops?

Time:05-31

I don't know how OpenMP works, but I presume calling a function with restricted pointer arguments inside a parallel for loop doesn't work if the objects could be shared by multiple threads? Take the following example of serial code meant to perform a weighted sum across matrix columns:

const int n = 10; 
const double x[n][n] = {...};  // matrix, containing some numbers
const double w[n] = {...};     // weights, containing some numbers

// my weighted sum function
double mywsum(const double *restrict px, const double *restrict pw, const int n) {
    double tmp = 0.0;
    for(int i = 0; i < n;   i) tmp  = px[i] * pw[i];
    return tmp;
}

double res[n]; // results vector
const double *pw = &w[0]; // creating pointer to w 

// loop doing column-wise weighted sum
for(int j = 0; j < n;   j) {
    res[j] = mywsum(&x[0][j], pw, n);
}

Now I want to parallelize this loop using OpenMP, e.g.:

#pragma omp parallel for
for(int j = 0; j < n;   j) {
    res[j] = mywsum(&x[0][j], pw, n);
}

I believe the *restrict px could still be valid as the particular elements pointed to can only be accessed by one thread at a time, but the *restrict pw should cause problems as the elements of w are accessed concurrently by multiple threads, so the restrict clause should be removed here?

CodePudding user response:

I presume calling a function with restricted pointer arguments inside a parallel for loop doesn't work if the objects could be shared by multiple threads?

The restrict keyword is totally independent of using multiple threads. It tells the compiler that the pointer target an object that is not aliased, that is, referenced by any other pointers in the function. It is meant to avoid aliasing in C. The fact that other threads can call the function is not a problem. In fact, if threads write in the same location, you have a much bigger problem: a race condition. If multiple threads read in the same location, this is not a problem (with or without the restrict keyword). The compiler basically does not care about multi-threading when the function mywsum is compiled. It can ignore the effect of other threads since there is no locks, atomic operations or memory barriers.

I believe the *restrict px could still be valid as the particular elements pointed to can only be accessed by one thread at a time, but the *restrict pw should cause problems as the elements of w are accessed concurrently by multiple threads, so the restrict clause should be removed here?

It should be removed because it is not useful, but not because it cause any issue.

The use of the restrict keyword is not very useful here since the compiler can easily see that there is no possible overlapping. Indeed, the only store done in the loop is the one of tmp which is a local variable and the input arguments cannot point on tmp because it is a local variable. In fact, compilers will store tmp in a register if optimizations are enabled (so it does not even have an address in practice).

One should keep in mind that restrict is bound to the function scope where it is define (ie. in the function mywsum). Thus, inlining or the use of the function in a multithreaded context have no impact on the result with respect to the restrict keyword.


I think &x[0][j] is wrong because the loop of the function iterate over n items and the pointer starts to the j-th item. This means the loop access to the item x[0][j n-1] theoretically causing out-of-bound accesses. In practice you will observe no error because 2D C array are flatten in memory and &x[0][n] should be equal to &x[1][0] in your case. The result will certainly not what you want.

  • Related