2016-12-12 8 views
-3

Я использую OpenMP на вложенном цикле, который работает как этотзамена #pragma OMP критической (C++)

#pragma omp parallel shared(vector1) private(i,j) 
{ 
#pragma omp for schedule(dynamic) 
    for (i = 0; i < vector1.size(); ++i){ 

     //some code here 

     for (j = 0; j < vector1.size(); ++j){ 

      //some other code goes here 
     #pragma omp critical 
     A+=B; 
     } 
    C +=A; 
    } 
} 

Проблема здесь состоит в том, что мой код делает много вычислений в A+=B части код. Поэтому, делая это критическим, я не достигаю ускорения, которое я бы хотел. (На самом деле, как представляется, некоторые накладные расходы, так как моя программа занимает больше времени, чтобы выполнить ее, она записывается последовательно).

Я попытался с помощью

#pragma omp reduction private(B) reduction(+:A) 
    A+=B 

это ускоряет время выполнения, однако, кажется, что он не заботится о гоночных условиях, как п critical, так как я не получаю те же результаты А.

Есть ли альтернатива этому, я могу попробовать?

+3

Есть одна вещь, которую вы можете сделать: опубликуйте [минимальный, полный и проверяемый пример] (http://stackoverflow.com/help/mcve), потому что только с вашим псевдокодом мы мало что можем сделать, чтобы помочь вам , – Gilles

+0

Возможно, вы правы, но в то же время сокращение() не заботится о гоночных условиях? –

+1

Конечно, это так, вы знаете, что делают «критические» и «сокращения»? Кажется, вы случайно применяете идеи, которые полностью меняют смысл программы. 'A' и' B' не определены, поэтому совершенно невозможно догадаться, что вы имеете в виду под этим фрагментом. Нет такой вещи, как «прагма, заботясь о состоянии гонки», это ручная работа, вы несете ответственность за структурирование кода, чтобы они не появлялись. То есть ничто не заботится об этом, они гарантированно не появятся. – luk32

ответ

1

Если вы не хотите, чтобы ваш класс Vector3 был потокобезопасным или переписал ваши операции для использования с std::atomic<Vector3>, оба из которых по-прежнему будут иметь недостатки в производительности (хотя это и не так серьезно, как использование критической секции) , вы можете имитировать behaviour of OpenMP reduction:

#pragma omp parallel // no need to declare variables declared outside/inside as shared/private 
{ 

    Vector3 A{}, LocalC{}; // both thread-private 

    #pragma omp for schedule(dynamic) 
    for (i = 0; i < vector1.size(); ++i){ 

     //some code here 

     for (j = 0; j < vector1.size(); ++j){ 

      //some other code goes here 

      A += B; // does not need a barrier 
     } 
     LocalC += A; // does not need a barrier 
    } 

    #pragma omp critical 
    C += LocalC; 
} 

NB, что это предполагает, что у вас нет доступа A для чтения в ваших «некоторый код» комментарии, но не все равно следует, если вы когда-нибудь думали о использовании reduction пункт.

+0

Да A читается во внешнем цикле (сейчас я редактировал код). Теперь, когда предложение о сокращении не может быть использовано, мой вопрос все еще остается, есть ли альтернатива? –

+0

@ j.doe Я не вижу этого в вашем вопросе. Вы уверены, что хотите прочитать обновленное значение? Чтение 'A' в многопоточной ситуации, в то время как другие потоки, написанные на нем, звучат как рецепт неприятностей. Если это действительно так, вы можете захотеть сделать это «volatile» или что-то в этом роде, но я хотел бы получить более подробную информацию о том, почему вы хотите это сделать. –

+0

Я только что обновил вопрос 'c + = A', где A читается. перед 'C + = A' у меня также есть кривая #pragma omp. но только критическое предложение на A, похоже, замедляет время выполнения, так как C не выполняет интенсивные вычисления. –