Распараллеливание OpenMP двух циклов с условием на индексы - PullRequest
0 голосов
/ 29 октября 2019

Я пытался распараллелить код, содержащий такой двойной цикл do. Это точно не эффективно, но сейчас это не большая проблема. Выходной тау является NaN. Это первая проблема.

Вторая проблема заключается в том, что компилятор Intel выдает фатальную ошибку с числом потоков, меньшим, чем максимальное число потоков (равно 8 для моей машины).

Как можно решить эти проблемы?

            !$omp parallel do   private(i,j,    ro11,ro21,ro12,ro22,        &
                                                u11,u21,u12,u22,            &
                                                v11,v21,v12,v22,            &
                                                es11,es21,es12,es22,        &
                                                p11,p21,p12,p22,            &
                                                te11,te21,te12,te22,        &
                                                emu11,emu21,emu12,emu22)    &
                            shared(i1l, i2l, j1l, j2l, emumax, tauv, tauvij, ro, u, v, es) 
            do i=i1l+2,i2l-2,2
                do j=j1l+2,j2l-2,2
                    if (i.le.niii.and.i.ge.0.and.j.ge.0.and.j.le.nj.or.&
                        i.le.ni.and.i.ge.niik.and.j.gt.njjv.and.j.le.nj.or.&
                        i.le.ni.and.i.ge.niik.and.j.ge.0.and.j.lt.njjn&
                        .or.i.gt.niii.and.i.lt.niik.and.j.gt.njj0+i-niii&
                        .or.i.gt.niii.and.i.lt.niik.and.j.lt.njj0-i+niii) then
                    ro11=ro(i-1,j-1)
                    ro21=ro(i+1,j-1)
                    ro12=ro(i-1,j+1)
                    ro22=ro(i+1,j+1)
                    u11=u(i-1,j-1)
                    u21=u(i+1,j-1)
                    u12=u(i-1,j+1)
                    u22=u(i+1,j+1)
                    v11=v(i-1,j-1)
                    v21=v(i+1,j-1)
                    v12=v(i-1,j+1)
                    v22=v(i+1,j+1)
                    es11=es(i-1,j-1)
                    es21=es(i+1,j-1)
                    es12=es(i-1,j+1)
                    es22=es(i+1,j+1)
                    p11=(es11-0.5*ro11*(u11*u11+v11*v11))*ga1
                    p21=(es21-0.5*ro21*(u21*u21+v21*v21))*ga1
                    p12=(es12-0.5*ro12*(u12*u12+v12*v12))*ga1
                    p22=(es22-0.5*ro22*(u22*u22+v22*v22))*ga1
                    te11=p11/ro11   
                    te21=p21/ro21
                    te12=p12/ro12
                    te22=p22/ro22
                    emu11=te11**1.5*(1.0+s1)/(te11+s1)
                    emu21=te21**1.5*(1.0+s1)/(te21+s1)
                    emu12=te12**1.5*(1.0+s1)/(te12+s1)
                    emu22=te22**1.5*(1.0+s1)/(te22+s1)
                    emumax=emu11
                    if (emu21.gt.emumax) then
                        emumax=emu21
                    end if
                    if (emu12.gt.emumax) then
                        emumax=emu12
                    end if
                    if (emu22.gt.emumax) then
                        emumax=emu22
                    end if
                    tauvij=re*flkv*hx*hx/emumax
                    if (tauvij .le. tauv) then
                        tauv=tauvij
                    endif
                endif
                enddo
            enddo
            !$omp end parallel do

1 Ответ

0 голосов
/ 30 октября 2019

Дело в том, что он выполняется без ошибок, но DoMP-цикл OpenMP вычисляется медленнее, чем последовательный ...

Из вашего воспроизводимого примера :

1.) Ваш код использует только 1 поток (?) В регионе OpenMP:

  ! Set number of threads
  nthreads = 1
  call omp_set_num_threads(nthreads)
  print *, 'The number of threads are used is ', omp_get_max_threads ( )

Я бы избегал call omp_set_num_threads(). Insted, укажите количество потоков с переменной среды OMP_NUM_THREADS. Для машины unix: export OMP_NUM_THREADS=<number of threads>

2.) В вашем «воспроизводимом» примере в параллельном цикле (строка 312) отсутствуют частные / общие объявления? Из того, что вы написали выше, исправьте:

!$omp parallel do default(private) shared(i1l, i2l, j1l, j2l, emumax, tauv, tauvij, ro, u, v, es)

При всем вышеперечисленном результат, который я получаю со своей машины (4c / 4t) с использованием компилятора GNU Fortran, равен:

...
Executed time in SEQ code is   60.2720146    
...
Executed time in OMP code is   27.1342430 
...