在 OpenMP 中计算矩阵的条目
Computing entries of a matrix in OpenMP
我是 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;
}
有人可以向我解释如何解决这个问题吗?
根据例如这个
http://supercomputingblog.com/openmp/tutorial-parallel-for-loops-with-openmp/
在并行部分之外声明变量是危险的。
可以通过显式地将内部循环的循环变量设为私有来解除它。
为此,请更改此
#pragma omp parallel for shared(A)
到
#pragma omp parallel for private(j) shared(A)
这种情况下的问题是 j
在线程之间 共享 ,这会扰乱内循环的控制流。默认情况下,在并行区域之外声明的变量是 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
变量未初始化,即使它们在并行区域之外具有有效值。因此,我强烈推荐隐式默认方法,除非有必要进行高级使用。
我是 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;
}
有人可以向我解释如何解决这个问题吗?
根据例如这个
http://supercomputingblog.com/openmp/tutorial-parallel-for-loops-with-openmp/
在并行部分之外声明变量是危险的。
可以通过显式地将内部循环的循环变量设为私有来解除它。
为此,请更改此
#pragma omp parallel for shared(A)
到
#pragma omp parallel for private(j) shared(A)
这种情况下的问题是 j
在线程之间 共享 ,这会扰乱内循环的控制流。默认情况下,在并行区域之外声明的变量是 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
变量未初始化,即使它们在并行区域之外具有有效值。因此,我强烈推荐隐式默认方法,除非有必要进行高级使用。