如何使用openMP使这段代码线程安全?

时间:2012-12-05 21:38:06

标签: c++ thread-safety openmp pragma

如果删除#pragma omp parallel for,下面显示的示意图代码工作正常,但是这样就可以编译代码,但是在执行二进制文件时,我会收到*** glibc detected *** ./testBin: double free or corruption (!prev): 0x0c43d8d8 ***core dumped等错误。我猜这是因为多个线程试图写入变量omega, ell, ....lineVec。我该如何解决?有没有办法告诉它变量是共享的?或者通常只有另一种方法可以并行执行此循环。我对`openmp完全不熟悉,这是我第一次使用它。

#include <omp.h>


int main( int argc , char **argv )
{ 
 vector <vector<string>> fileVec;
 //some code that reads in a CSV file lines into elements of fileVec

//variables constituting a line:
//my_float has been typedef to be a high precision class in real code
my_float omega;
my_float ell;

my_float init1Real;
my_float init1Imag;
my_float dinit1Real;
my_float dinit1Imag;

my_float init2Real;
my_float init2Imag;
my_float dinit2Real;
my_float dinit2Imag;

#pragma omp parallel for private(lineVec,fileVec,ell,omega,init1Real,init1Imag,dinit1Real,dinit1Imag,init2Real,init2Imag,dinit2Real,dinit2Imag)
 for (size_t i=0; i< fileVec.size(); i++) 
    { 

        lineVec=fileVec[i];


         ell=lineVec[0];
         omega=lineVec[1];

         init1Real=lineVec[2];
         init1Imag=lineVec[3];
         dinit1Real=lineVec[4];
         dinit1Imag=lineVec[5];
         init2Real=lineVec[6];
         init2Imag=lineVec[7];
         dinit2Real=lineVec[8];
         dinit2Imag=lineVec[9];


        // cout<<"OUTPUT ell=" << ell<< " omega=" << omega <<" init1Real="<<init1Real<<endl;

         //do some other calc involving these variables

    }     
   }

2 个答案:

答案 0 :(得分:6)

从共享的fileVec 中读取线程安全。只有my_float类型的变量应该被设置为private甚至更好 - 在循环内声明:

int main(int argc, char **argv)
{
    vector<vector<string>> fileVec;

    //some code that reads in a CSV file lines into elements of fileVec

    #pragma omp parallel for private(lineVec)
    for (size_t i = 0; i < fileVec.size(); i++)
    {
        lineVec = fileVec[i];

        //my_float has been typedef to be a high precision class in real code

        my_float ell = lineVec[0];
        my_float omega = lineVec[1];

        my_float init1Real = lineVec[2];
        my_float init1Imag = lineVec[3];
        my_float dinit1Real = lineVec[4];
        my_float dinit1Imag = lineVec[5];
        my_float init2Real = lineVec[6];
        my_float init2Imag = lineVec[7];
        my_float dinit2Real = lineVec[8];
        my_float dinit2Imag = lineVec[9];

        cout << "OUTPUT ell=" << ell << " omega=" << omega
             << " init1Real=" << init1Real << endl;

        //do some other calc involving these variables
    }
}

我在这里看不到任何比赛,除非my_float不是线程安全的,或者//do some other calc involving these variables中隐藏了其他内容。

请注意,对于最近的OpenMP版本,您甚至可以使用迭代器来遍历向量,因为它提供了一个随机访问迭代器:

typedef vector<vector<string>>::const_iterator iterType;

#pragma omp parallel for private(lineVec)
for (iterType it = lineVec.begin(); it != lineVec.end(); it++)
{
    ...
}

答案 1 :(得分:1)

你编写它的方式,openmp将创建一些线程并在每个线程之间划分for循环的迭代总数。通过这样做,它将尝试对不同线程共享的向量执行并行读取。您可以更改数据共享属性,(请参阅the OpenMP Wiki about data sharing attribute clauses,在此microsoft doc中您有一个很好的示例如何执行此操作。例如,要将lineVec和fileVec声明为“private”,请使用:< / p>

#pragma omp parallel private(lineVec, fileVec)

此外,cout不是线程安全的,从多个线程调用cout也需要序列化。