这是openMP的正确用法吗?(或者:我可以信任默认设置吗?)



我目前是第一次使用openMP,并对"数据成员不能是私有的"规则提出了质疑。

我想知道以下是否有效,或者它是否最终会崩溃:

class network
{
    double tau;
    void SomeFunction();
};
void network::SomeFunction()
{
    #pragma omp parallel for // <-the openMP call
    for (uint iNeu=0;iNeu<nNeurons;++iNeu)
    {
        neurons[iNeu].timeSinceSpike+=tau;  //tau is defined in some other place
        neurons[iNeu].E+=tau*tau;
    }   
}

因此,我使用的是最简单的语法,让openMP自己解决所有问题。这个版本可以编译,并且输出是正确的(到目前为止)。我之前试过的是

void network::SomeFunction()
{
    #pragma omp parallel for default(none) shared(neurons) firstprivate(tau)  // <-the openMP call
    for (uint iNeu=0;iNeu<nNeurons;++iNeu)
    {
        neurons[iNeu].timeSinceSpike+=tau; //tau is defined in some other place
        neurons[iNeu].E+=tau*tau;
    }   
}

然而,正如暗示的那样,这不会编译,可能是因为tau和神经元是网络的数据成员。

那么问题是,如果我真的只是幸运地运行了第一个版本,以及我是否必须做一些类似的事情

void network::SomeFunction()
{
    double tempTau=tau;
    vector <neuron> tempNeurons=neurons; //in realtity this copy-process would be quite involved
    #pragma omp parallel for shared(tempNeurons) firstprivate(tempTau)// <-the openMP call
    for (uint iNeu=0;iNeu<nNeurons;++iNeu)
    {
        tempNeurons[iNeu].timeSinceSpike+=tempTau;
        tempNeurons[iNeu].E+=tempTau*tempTau;
    }   
}

当然,我更喜欢使用当前版本,因为它很短,很容易阅读,但我也希望相信我的输出:)我使用的是gcc 4.6.1

希望有人能教我正确的方法。

在这个例子中,您最初所做的应该很好:

  • 原因是您根本没有修改tau成员。因此,一开始就没有理由将其保密。如果不修改,异步共享相同的值是安全的
  • 对于neurons,您正在独立修改图元。所以这里也没有问题

当您将一个变量声明为firstprivate时,它将被复制构造到所有线程中。所以shared(tempNeurons)绝对不是你想做的事情。

http://www.openmp.org/mp-documents/OpenMP3.1.pdf

2.9.1节,数据共享属性规则

  • 出现在threadprivate指令中的变量是threadprivate
  • 在构造内部的作用域中声明的具有自动存储持续时间的变量是私有的
  • 共享具有动态存储持续时间的对象
  • 静态数据成员是共享的
  • for或parallel for构造的关联for循环中的循环迭代变量是私有的
  • 具有const限定类型但没有可变成员的变量是共享的
  • 在构造内部的作用域中声明的具有静态存储持续时间的变量是共享的
...
  • for或parallel for构造的关联for循环中的循环迭代变量可以列在private或lastprivate子句中
  • 具有const限定类型且没有可变成员的变量可以列在firstprivate子句中

然而,我仍然错过了构造之外的自动变量的默认共享属性。

最新更新