Обмен информацией через (c ++) openmp между различными потоками - PullRequest
2 голосов
/ 04 января 2012

Я относительно новичок в параллельном программировании и хочу выполнить следующую задачу в c ++ с помощью openmp.

У меня есть несколько (скажем, 4) относительных сложных объектов / вычислений.Все они похожи, но слишком сложны, чтобы распараллелить каждый из них (поэтому они запускаются последовательно).Поэтому моя идея заключалась в том, чтобы использовать разные потоки / процессоры для каждого из них, то есть я хочу распределить вычисления по моим ядрам.Хотя это может быть не самым эффективным использованием параллелизма в этом контексте, его может быть проще всего достичь (из-за высокой сложности каждого вычисления).

Хотя это будет работать

#pragma omp parallel
{
    #pragma omp for
    for(int i = 0; i < 4; i++)
    {
       obj[i].calculate();    
    }
}

Я хочу обмениваться дополнительной информацией между этими объектами, например, целое число (или более сложный объект) «а» следует изменять во время каждого вычисления (хотя я не могу предсказать, когда и как часто, но особенно чаще, чем один раз).Если он изменен, информация также должна быть включена в расчеты друг друга.В то время как конкретный обмен информацией (опять же) является относительно сложным, это делается также и методами «вычисления» (неявно).В общем случае это должно выглядеть так, как указано выше, с дополнительным целым числом «a», которое записывается и читается всеми методами расчета:

int a;
#pragma omp parallel
{
   #pragma omp for
   for(int i = 0; i < 4; i++)
   {
       obj[i].calculate();    
   }
}

Итак, мой вопрос: как я могу предотвратить данные?гонка "на" а "?Имеется в виду, как я могу сгенерировать объект, к которому каждый раз может обращаться только один поток, не вдаваясь в детали самих методов «вычисления»?Предлагает ли openmp такую ​​функциональность, а если нет, то какая библиотека это делает?

С наилучшими пожеланиями и заранее спасибо!

Ответы [ 2 ]

1 голос
/ 04 января 2012

Судя по вашему описанию, я не уверен, поможет ли вам параллельное выполнение вообще, когда каждый поток должен ждать обновления информации a.

В любом случае, вы можете обновлять переменные без условия гонки с помощью директив flush, atomic и critical. Лучший выбор во многом зависит от того, какие потоки нужно обновить a или получить обновление a.

critical: все потоки выполняют код, но каждый из них одновременно

atomic: память защищена от множественных записей и внутренне заменена на critical

flush: обновляет общие переменные и неявно вызывается critical

Наконец, barrier гарантирует, что все потоки достигли одной и той же точки в коде.

Я хочу обменяться дополнительной информацией между этими объектами, для Например, целое число (или более сложный объект) «а» следует изменить во время каждого расчета (хотя я не могу предсказать, когда и как часто, но особенно чаще, чем один раз).

Это утверждение немного раздражает, потому что вы должны знать, когда вам нужно обновить a. Когда вы это сделаете, вам нужно иметь барьер во всех потоках, обновить a в критической секции и продолжить выполнение параллельно. Так сколько потоков обновляется a? Главный поток или все они?

Если только один поток должен обновить a, тогда другой вариант - директива single. Его код выполняется только одним потоком с неявным барьером и неявным сбросом после выполнения. Это общие параметры для правильного обновления вашего сложного объекта a во всех потоках. Удачи.

0 голосов
/ 04 января 2012

Конечно, вы понимаете, что метод calculate не имеет доступа к переменной a в коде, который вы разместили. Если вы хотите работать так, как вы, вы можете написать свою функцию вычисления в строке и использовать критический раздел всякий раз, когда вы изменяете a:

int a;
#pragma omp parallel
{
   #pragma omp for
   for(int i = 0; i < 4; i++)
   {
       // code of calculate
       #pragma omp critical
       {
           // modify a
       }
       // other code
   }
}
...