#c #c #parallel-processing #openmp
#c #c #параллельная обработка #openmp
Вопрос:
Я хочу распараллелить цикл с внутренним циклом внутри него. Мой код выглядит так:
#pragma omp parallel for private(jb,ib) shared(n, Nb, lb, lastBlock, jj, W, WT) schedule(dynamic) //private(ib, jb) shared(n, Nb, lb, lastBlock, jj, W, WT) //parallel for loop with omp
for(jb=0; jb<Nb; jb )
{
int lbh = (jb==Nb-1) ? lastBlock : lb;
int ip = omp_get_thread_num();
packWT(a, n, lb, s, jb, colNr, WT[ip], nr); //pack WWT[jb]
for(ib=jb; ib<Nb; ib )
{
int lbv = (ib==Nb-1) ? lastBlock : lb;
multBlock_2x4xk(a, n, jj ib*lb, jj jb*lb, W ib*lb*lb, WT[ip], lb, lbv, lbh); //MULT BLOCK - 2x4xK (W[jb]*W[ib])
}
}
Я измеряю время, которое proc потратил на вычисление этих циклов. Это то же самое для нескольких потоков, что и для одного потока. Когда я изменяю предложение
private(jb,ib)
для
private(jb)
Все меняется. Я имею в виду, что для нескольких потоков proc вычисляется быстрее, чем для одного потока. В чем проблема?
Комментарии:
1. Здесь не так много, чтобы продолжить — что такое packWT, multBlock, a и т. Д.? — но вам определенно нужно, чтобы ib был закрытым, иначе потоки будут перезаписывать один и тот же индекс цикла. Причина, по которой это быстрее без private(ib), вероятно, заключается в том, что многие ib пропускаются без него…
2. действительно, без private (ib) я получаю неправильные результаты.. Все еще не знаю, почему время одинаково для многих потоков и одного потока…
3. Причин может быть много, но никто из нас не сможет вам ничего сказать без дополнительной информации.
4. Я уже проверил, что это не зависит от того, что функции winthin циклы.
5. Похоже, это зависит от компилятора… Тот же код выполняется под Windows в Visual Studio, но на mac и Linux с gcc это не очень хорошо. Я компилирую это с помощью команды: g -O0 -fopenmp -msse2 …
Ответ №1:
Проблема в том, что ваши внутренние циклы for не имеют канонической формы. Поэтому openmp не удается распараллелить циклы, и ускорение не может быть достигнуто. Циклы должны выглядеть как на следующем рисунке. Где start , idx и inc не разрешается изменять во время параллельной части кода.
Я думаю, что я определил вашу проблему. Вы вызываете эти функции:
packWT(a, n, lb, s, jb, colNr, WT[ip], nr); packWT(a, n, lb, s, jb, colNr, WT[ip], nr);
multBlock_2x4xk(a, n, jj ib*lb, jj jb*lb, W ib*lb*lb, WT[ip], lb, lbv, lbh);
где одним аргументом является переменная цикла jb, поскольку jb может быть изменен внутри функции (в зависимости от объявления функции), компилятор решает не распараллеливать цикл.
Чтобы избежать этого, скопируйте переменную jb в локальную переменную и передайте локальную переменную функции.