我对 openMP 很陌生,但我正在尝试编写一个简单的程序来并行生成矩阵的条目,即对于 N × M 矩阵 A,令 A(i,j) = i*j。下面包含一个最小的示例:
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc,
char **argv)
{
int i, j, N, M;
N = 20;
M = 20;
int* A;
A = (int*) calloc(N*M, sizeof(int));
// compute entries of A in parallel
#pragma omp parallel for shared(A)
for (i = 0; i < N; ++i){
for (j = 0; j < M; ++j){
A[i*M + j] = i*j;
}
}
// print parallel results
for (i = 0; i < N; ++i){
for (j = 0; j < M; ++j){
printf("%d ", A[i*M + j]);
}
printf("\n");
}
free(A);
return 0;
}
结果并不总是正确的。理论上,我只是并行化外层循环,for 循环的每次迭代都不会修改其他迭代将修改的条目。但我不知道如何将其转换为 openMP。当对向量数组执行类似的过程(即只有一个 for 循环)时,似乎没有问题,例如
#pragma omp parallel for
for (i = 0; i < N; ++i)
{
v[i] = i*i;
}
有人可以向我解释如何解决这个问题吗?
本案的问题在于j
is shared线程之间的冲突会扰乱内循环的控制流。默认情况下,在并行区域之外声明的变量是shared而在并行区域内声明的变量是private.
遵循一般规则尽可能在本地声明变量。在 for 循环中这意味着:
#pragma omp parallel for
for (int i = 0; i < N; ++i) {
for (int j = 0; j < M; ++j) {
这使得对代码的推理变得更加容易 - 并且 OpenMP 代码默认情况下大部分都是正确的。 (笔记A
默认情况下是共享的,因为它是在外部定义的)。
或者您可以手动指定private(i,j) shared(A)
- 这更明确,可以帮助初学者。然而,它会造成冗余并且也可能很危险:private
即使变量在并行区域之外具有有效值,它们也未初始化。因此,除非高级使用需要,否则我强烈建议使用隐式默认方法。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)