OpenMP: невозможно распараллелить вложенные циклы for

Я хочу распараллелить цикл с внутренним циклом внутри него. Мой код выглядит так:

    #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])

            }
    }

Я измеряю время, затраченное проком на вычисление этого цикла. Это то же самое для нескольких потоков, что и для одного потока. Когда я меняю пункт

private(jb,ib)

за

private(jb)

Все меняется. Я имею в виду, что для нескольких потоков процесс вычисляется быстрее, чем для одного потока. В чем проблема?


person Pelsono    schedule 26.10.2011    source источник
comment
Здесь особо нечего рассказывать — что такое packWT, multBlock, a и т. д.? -- но вам определенно нужно, чтобы этот ib был закрытым, иначе потоки будут перезаписывать один и тот же индекс цикла. Причина, по которой это быстрее без частного (ib), вероятно, заключается в том, что многие ib пропускаются без него...   -  person Jonathan Dursi    schedule 26.10.2011
comment
действительно, без private(ib) я получаю неправильные результаты.. До сих пор не знаю, почему время одинаково для многих потоков и одного потока...   -  person Pelsono    schedule 26.10.2011
comment
Причин может быть много, но никто из нас не сможет вам ничего сказать без дополнительной информации.   -  person Jonathan Dursi    schedule 26.10.2011
comment
Я уже проверил, что это не зависит от того, что функции работают в тонких циклах.   -  person Pelsono    schedule 26.10.2011
comment
Кажется, это зависит от компилятора... Тот же код работает под окнами в Visual Studio, но на Mac и Linux с gcc это не очень хорошо. Я компилирую это с помощью команды: g++ -O0 -fopenmp -msse2 ...   -  person Pelsono    schedule 26.10.2011


Ответы (1)


Проблема в том, что ваши внутренние циклы for не имеют канонической формы. Следовательно, openmp не может распараллелить циклы и добиться ускорения невозможно. Петли должны выглядеть, как на следующем рисунке. Где start, idx и inc нельзя изменять во время параллельной части кода. каноническая форма цикла for

Кажется, я определил вашу проблему. Вы вызываете эти функции:

  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 в локальную переменную и передайте локальную переменную функции.

person tune2fs    schedule 27.10.2011