C++ OpenMP矩阵乘法给出了不一致的结果

C++ OpenMP矩阵乘法给出了不一致的结果,c++,openmp,C++,Openmp,在执行矩阵/向量乘法时,使用OpenMP并行运行代码或在单个线程中运行代码时,我会得到两个不同的值。如果我导出环境变量 $ export OMP_NUM_THREADS=1 乘法给出了相同的结果,但如果我将值设置为2或更高,乘法有时是一致的,有时是不一致的 #include <stdio.h> #include <math.h> #include <omp.h> double* parMatVecMul(double* A, double* v, int

在执行矩阵/向量乘法时,使用OpenMP并行运行代码或在单个线程中运行代码时,我会得到两个不同的值。如果我导出环境变量

$ export OMP_NUM_THREADS=1
乘法给出了相同的结果,但如果我将值设置为2或更高,乘法有时是一致的,有时是不一致的

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

double* parMatVecMul(double* A, double* v, int M, int N){
    double* C = new double[M];
    double dot;
    #pragma omp parallel for
    for (int i = 0; i<M; i++)
    {
        dot = 0;
        for (int j=0; j<N; j++)
            dot += *((A+i*N) + j) * v[j];
        C[i] = dot;
    }
    return C;
}

double* matVecMul(double* A, double* v, int M, int N){
    double* C = new double[M];
    double dot;
    for (int i = 0; i<M; i++)
    {
        dot = 0;
        for (int j=0; j<N; j++)
            dot += *((A+i*N) + j) * v[j];
        C[i] = dot;
    }
    return C;
}

int main(){
    int size = 40;
    double* mat = new double[size*size];    
    double* x_true = new double[size];
    double* b = new double[size];
    double* bx = new double[size];

    for( int iter = 0; iter < 10; iter++){  //Run code 10 times to find error

        for( int i =0; i < size; i++)       //Initialize symmetric matrix
            for( int j =0; j < size; j++){
                mat[i*size + j] = rand() / double(RAND_MAX) + 0.2;
                mat[j*size + i] = mat[i*size + j];
            }
        for( int i =0; i < size; i++){      //Make matrix diagonally dominant
            mat[i*size + i] += size;
            x_true[i] = rand() % 10 + 0.2;
        }

        double error = 0;;
        b = matVecMul(mat, x_true, size, size);
        bx = parMatVecMul(mat, x_true, size, size);
        for (int i = 0; i < size; i++)
            error += fabs(b[i] - bx[i]);
        printf("b error: %f\n", error);
    }

    return 0;
}

为什么并行操作有时不正确

给点局部作用域而不是共享作用域。在并行化函数中,
dot
上存在一个竞争——多个线程在没有协调的情况下更新它。一般来说,如果并行程序在一个线程上运行,但在多个线程上运行(不可靠),则考虑数据竞争@tim18已经告诉你如何解决这个问题了。
$ ./a.out 
b error: 0.000000
b error: 0.000000
b error: 0.000000
b error: 0.000000
b error: 0.000000
b error: 0.000000
b error: 0.000000
b error: 34.747142
b error: 0.000000
b error: 0.000000