правильное использование внутренней функции и openmp - PullRequest
5 голосов
/ 02 ноября 2011

У меня есть цикл for, который вызывает внутреннюю функцию:

some variables
for(int i=0; i< 10000000; i++)
    func(variables)

По сути, func получает ссылку на некоторый массив A и вставляет значения в A [i] - так что я уверен, что каждыйвызов func фактически пытается вставить значение в другое место в A, и все остальные входные переменные остаются такими же, какими они были до цикла for.Так что func является потокобезопасным.

Могу ли я смело изменить код на

some variables
#pragma omp parallel for
for(int i=0; i< 10000000; i++)
    func(variables)

Из того, что я понимаю из уроков openmp, этого недостаточно, поскольку библиотеки openmp не знают, что переменныефункции func действительно поточно-ориентированы, и это приведет к попыткам выполнить синхронизацию, что приведет к замедлению работы, и мне потребуется объявить переменные закрытыми и т. д. Но на самом деле при попытке кода, приведенного выше, кажется, что он действительно работает быстрее ипараллельно - это как и ожидалось?Я просто хотел убедиться, что я ничего не пропустил.

Объявление func:

 func(int i, int client_num, const vector<int>& vec)

Ответы [ 2 ]

4 голосов
/ 02 ноября 2011

Прежде всего, OpenMP не может волшебным образом определить зависимость от вашего кода.Вы несете ответственность за правильность кода для распараллеливания.

Для безопасного распараллеливания цикла for func не должно иметь зависимостей потока, переносимых в цикле , или зависимости между итерациямиособенно для чтения-после-записи.Кроме того, вы должны проверить, что нет статических переменных.(На самом деле, в этом коротком ответе гораздо сложнее записать условия безопасного распараллеливания.)


Ваше описание func говорит о том, что func запишет переменную в другое место.Если это так, вы можете безопасно распараллелить, поставив pragma omp parallel for, если другие вычисления не зависят от запрета распараллеливания.

Ваш прототип func: func(int i, int client_num, const vector<int>& vec)

Существует vector, но это константа, поэтому vec не должно иметь никакой зависимости.Одновременное чтение из разных потоков безопасно.

Однако вы говорите, что вывод отличается.Это означает, что что-то было не так.Невозможно сказать, в чем проблемы.Показ прототипа функции никогда не помогает;нам нужно знать, какие вычисления выполняются func.

Тем не менее, некоторые шаги для диагностики:

  • Проверьте зависимость в вашем коде.Вы не должны иметь зависимости, показанные ниже.Обратите внимание, что массив A имеет зависимость переноса цикла, которая предотвратит распараллеливание:

for (int k = 1; k <N; ++k) A[k] = A[k-1]+1;

  • Проверка func является повторно входящей или поточно-ориентированной,В основном статические и глобальные переменные могут убить ваш код.Если это так, вы можете решить эту проблему путем приватизации .В OpenMP вы можете объявить эти переменные в предложении private.Также в OpenMP есть threadprivate прагма.
1 голос
/ 02 ноября 2011

Вы нигде не меняете свою переменную цикла i, поэтому для компилятора не составит труда ее распараллелить.Поскольку i копируется только в вашу функцию, ее нельзя изменить снаружи.

Единственное, что вам нужно, это убедиться, что вы пишете внутри своих функций только в позиции A [i] и читаете только из позиций A [я].В противном случае вы можете получить условия гонки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...