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

发布于 2025-01-05 11:54:16 字数 1463 浏览 2 评论 0原文

我目前是第一次使用 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

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

I am presently using openMP for the first time, and have hit my head against the "data members cannot be private"-rule.

I would like to know whether the below is valid, or if it will eventually break:

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;
    }   
}

So, I am using the minimal syntax, and letting openMP figure out everything on its own. This version compiles, and the output is correct (so far).
What I tried before that was

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;
    }   
}

However, as hinted, that won't compile, presumably because tau and neurons are data members of network.

The question then is, if I have really just been lucky in my runs of the first version, and whether I have to do something like

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;
    }   
}

Naturally, I would much prefer to stick with the present version, as it is so short and easy to read, but I would also like to trust my output :)
I am using gcc 4.6.1

Hope someone can educate me on the proper way to do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

勿忘初心 2025-01-12 11:54:16

在此示例中,您最初所做的事情应该没问题:

  • 原因是您根本没有修改 tau 成员。所以一开始就没有理由将其设为私有。如果未修改,异步共享相同的值是安全的。
  • 至于神经元,您正在独立修改元素。所以这里也没有问题。

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

In this example, what you are initially doing should be fine:

  • The reason is that you aren't modifying the tau member at all. So there's no reason to make it private in the first place. It's safe to asynchronously share the same value if it isn't modified.
  • As for neurons, you are modifying the elements independently. So there's no problem here either.

When you declare a variable as firstprivate, it gets copy constructed into all the threads. So shared(tempNeurons) is definitely not what you want to do.

羁绊已千年 2025-01-12 11:54:16

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

第 2.9.1 节,数据共享属性规则

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

但是,我仍然怀念构造外部自动变量的默认共享属性。

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

Section 2.9.1, Data-sharing Attribute Rules

  • Variables appearing in threadprivate directives are threadprivate.
  • Variables with automatic storage duration that are declared in a scope inside the construct are private.
  • Objects with dynamic storage duration are shared.
  • Static data members are shared.
  • The loop iteration variable(s) in the associated for-loop(s) of a for or parallel for construct is (are) private.
  • Variables with const-qualified type having no mutable member are shared.
  • Variables with static storage duration that are declared in a scope inside the construct are shared.
...
  • The loop iteration variable(s) in the associated for-loop(s) of a for or parallel for construct may be listed in a private or lastprivate clause.
  • Variables with const-qualified type having no mutable member may be listed in a firstprivate clause.

However, I yet miss the default sharing attribute for automatic variables outside a construct.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文