将指针限制为 OpenMP for 循环中的函数参数?

restrict pointers as function arguments in OpenMP for loops?

我不知道 OpenMP 是如何工作的,但我假设如果对象可以由多个线程共享,那么在并行 for 循环中调用带有受限指针参数的函数是行不通的?以下面的串行代码示例旨在对矩阵列执行加权求和:

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);
}

现在我想使用 OpenMP 并行化这个循环,例如:

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

我相信 *restrict px 仍然有效,因为指向的特定元素一次只能由一个线程访问,但是 *restrict pw 应该会引起问题,因为 w被多个线程并发访问,那么这里的restrict子句应该去掉吗?

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?

restrict关键字完全独立于使用多线程。它告诉编译器该指针指向一个 没有别名 的对象,也就是说,被函数中的任何其他指针引用。它是为了避免在 C 中使用别名。其他线程可以调用该函数不是问题。事实上,如果线程写入相同的位置,就会遇到更大的问题:竞争条件。如果多个线程在同一位置读取,这不是问题(有或没有 restrict 关键字)。编译器在编译函数mywsum时基本不关心multi-threading。它可以忽略其他线程的影响,因为没有锁、原子操作或内存屏障。

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?

应该删除它,因为它没有用,但不会因为它会导致任何问题。

使用 restrict 关键字在这里不是很有用,因为编译器可以很容易地看到没有可能的重叠。实际上,循环中唯一完成的存储是 tmp 中的一个,它是一个局部变量,输入参数不能指向 tmp,因为它是一个局部变量。事实上,如果启用优化,编译器会将 tmp 存储在寄存器中(因此实际上它甚至没有地址)。

应该记住 restrict 绑定到定义它的函数范围(即在函数 mywsum 中)。因此,在多线程上下文中内联或使用函数对 restrict 关键字的结果没有影响。


我认为 &x[0][j] 是错误的,因为函数的循环遍历了 n 项并且指针开始指向第 j 项。这意味着循环访问项 x[0][j+n-1] 理论上会导致 out-of-bound 次访问。实际上,您不会观察到任何错误,因为 2D C 数组在内存中是扁平的,并且 &x[0][n] 应该等于 &x[1][0] 在您的情况下。结果肯定不是你想要的。