gpt4 book ai didi

c - 平行区域上的矩阵元素之和导致 OpenMP 上的错误答案

转载 作者:太空宇宙 更新时间:2023-11-04 01:43:41 25 4
gpt4 key购买 nike

我在我的大学里做一个事件,需要填充 [2000][2000] 个元素的矩阵,然后以并行方式计算所有元素的总和,这些元素是 5 的倍数。

起初我尝试使用 5 x 5 矩阵,我对元素进行了部分求和 (sumP),然后将它们的所有元素添加到一个名为 Sum 的变量上到一个临界区域。

在我的大学计算机上,当值必须低于 100 时,部分和正在接收 thrash 值(如 36501);我注意到它只发生在矩阵的 [0][i](第 0 行)。

#include <stdio.h>
#include <stdlib.h>
#include <omp.h>

#define N 5


int main() {
int i, j, k, l;
int sum = 0;
int sumP = 0;
int A[N][N];
printf("sumP : %i\n", sumP );
printf("sum: %i\n", sum);
#pragma omp parallel shared (A) private (i, j)
{
#pragma omp for
for (i = 0; i < N; i++) {
for(j = 0; j < N; j++){
A[i][j] = i%5;
printf("Number: %i, pos[%i][%i]\n", A[i][j], i, j);
}
}
}

#pragma omp parallel shared(A, sum) private (k, l, sumP)
{
#pragma omp for
for (k = 0; k < N; k++) {
for (l = 0; l < N; l++){
if (A[l][k] % 5 == 0 && A[l][k] != 0){
sumP = sumP + A[k][l];
printf("numero: %i, pos [%i],[%i] sumP: %i\n", A[k][l], k, l, sumP);
}
}
}
#pragma omp critical
sum += sumP;

}
//printf("sumP: %i\n", sumP);
printf("sum: %i\n", sum);

return (0);
}

我测试了它,在“for”语句之间将 sumP 的值声明为 0,它起作用了:

#pragma omp parallel shared(A, soma) private (k, l, somap2)
{
#pragma omp for
for (k = 0; k < N; k++) {
sumP = 0;
for (l = 0; l < N; l++){

当我在家对其进行测试时,它无需将 sumP 声明为 0(在部分和“sumP”上)就可以工作,就像我在上面所做的那样,但现在最终的 Sum 结果不正确...

最佳答案

您观察到此行为是因为 OpenMP 中的 private 变量未初始化。准确地说,它们的初始化就像您拥有一个没有显式初始化的局部变量一样。这意味着它们最初的值(value)是不确定的。您会在不同的系统上观察到不同的行为,因为编译器、选项和操作系统的某些组合以不同方式使用此“未定义”。您的代码在任何情况下都是不正确的,即使它有时会产生正确的结果。

现在您可以在尝试时将此设置设为零。但是,我通常建议改为尽可能将变量声明为局部变量。这使得对(并行)代码的推理变得更加容易,并且您可以省略“私有(private)/共享”声明。所以你的代码看起来像这样:

#pragma omp parallel
{
int sumP = 0;
#pragma omp for
for (int k = 0; k < N; k++) {
for (int l = 0; l < N; l++) {
if (A[l][k] % 5 == 0 && A[l][k] != 0) {
sumP = sumP + A[k][l];
printf("numero: %i, pos [%i],[%i] sumP: %i\n", A[k][l], k, l, sumP);
}
}
}
#pragma omp critical
sum += sumP;
}

除此之外,还有另一种方法可以通过归约来大幅简化此代码:

#pragma omp parallel for reduction(+:sum)
for (int k = 0; k < N; k++) {
for (int l = 0; l < N; l++) {
if (A[l][k] % 5 == 0 && A[l][k] != 0) {
sum += A[k][l];
}
}
}

编译器基本上会为你做同样的事情(但更好)并且代码更清晰。

关于c - 平行区域上的矩阵元素之和导致 OpenMP 上的错误答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57984116/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com