это правильное использование OpenMP?(или: можно ли доверять настройкам по умолчанию?) - PullRequest
3 голосов
/ 14 февраля 2012

В настоящее время я впервые использую 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;
    }   
}

Однако, как намекнул, это не скомпилируется, вероятно потому, что тау и нейроны являются членами данных сети.

Тогда возникает вопрос: действительно ли мне просто повезло в моих прогонах первой версии, и должен ли я сделать что-то вроде

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

Надеюсь, кто-то может научить меня, как правильно это сделать.

Ответы [ 2 ]

2 голосов
/ 14 февраля 2012

В этом примере все, что вы изначально делаете, должно быть в порядке:

  • Причина в том, что вы вообще не изменяете член tau. Так что в первую очередь нет причин делать это приватным. Безопасно асинхронно использовать одно и то же значение, если оно не изменено.
  • Что касается neurons, вы модифицируете элементы независимо. Так что здесь тоже нет проблем.

Когда вы объявляете переменную как firstprivate, она получает копию, встроенную во все потоки. Так что shared(tempNeurons) определенно не , что вы хотите сделать.

0 голосов
/ 14 февраля 2012

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

Раздел 2.9.1, Правила атрибутов совместного использования данных

  • Переменные, появляющиеся в директивах threadprivate, являются threadprivate.
  • Переменные сДлительность автоматического хранения, объявленная в области внутри конструкции, является частной.
  • Объекты с динамической продолжительностью хранения являются общими.
  • Статические члены-данные являются общими.
  • Итерация циклапеременная (и) в связанном цикле (ах) for или параллельной конструкции for является (являются) приватной.
  • Переменные с константным типом, не имеющие изменяемого члена, являются общими.
  • Переменные со статической продолжительностью хранения, объявленные в области внутри конструкции, являются общими.
...
  • Переменная (и) итерации цикла в связанном для-loop (s) для for или параллельные для конструкции могут быть перечислены в предложении private или lastprivate.
  • Переменные с константным типом, не имеющие изменяемого члена, могут быть перечислены в firstpПредложение rivate.

Однако мне пока не хватает атрибута общего доступа по умолчанию для автоматических переменных вне конструкции.

...