Issue #
An index outside the dimension size of an array is being used to access it, resulting in an access to a different dimension which introduces a data race in the form of an unprotected recurrence.
Relevance #
C/C++ array access syntax allows the use of indices outside the ranges array dimensions of even the array itself. Using indices corresponding to positions outside the array constitutes an out-of-memory-bounds error. Using an index outside the dimension bounds that results in accessing a valid array position in a different dimension is technically correct; however, it produces obscure code which is difficult to understand and reason about. Moreover, doing this in parallel code can introduce a data race when there is a recurrence pattern.
Actions #
Explicitly access each array dimension and ensure that the recurrence is executed correctly in parallel.
Code example #
The following code iterates over the rows in parallel and each thread iterates sequentially over the columns. However, there is an out-of-dimension-bounds access causing that a thread access an array element of a different row, which results in a data race between the corresponding threads:
void foo() {
int A[5][5];
#pragma omp parallel for
for (int i = 1; i < 5; ++i) {
for (int j = 0; j < 5; ++j) {
A[i][j] += A[i][j-1];
}
}
}
Assuming that each thread is responsible for processing a row, this can be fixed by starting the iterations over the second dimension in 1:
void foo() {
int A[5][5];
#pragma omp parallel for
for (int i = 1; i < 5; ++i) {
for (int j = 1; j < 5; ++j) {
A[i][j] += A[i][j-1];
}
}
}
Related resources #
- PWD008 examples at GitHub
- PWD007: Unprotected multithreading recurrence
- PWR014: Out-of-dimension-bounds array access