замедление параллельной подпрограммы при вызове внутри цикла - PullRequest
0 голосов
/ 25 июня 2019

Я распараллелил подпрограмму. У него очень хороший тест: ускорение 4X на четырехъядерном процессоре. У меня есть два разных источника: serial.f и paral.f. Сравнение производится с запуском их с терминала и печатью прошедшего времени настенных часов. Внутри каждого исходного кода есть только вызов ассоциированной подпрограммы. Но когда я изменяю источники следующим образом:

serial.f :

do i=1,100
    call serial
end do 

и вот так

 paral.f :

 do i=1,100
      call paral
 end do

производительность снижается до скорости 0,96 X: параллельная версия хуже, чем серийная! Код можно найти в , почему вызов N раз последовательной подпрограммы быстрее, чем вызов N раз параллельной версии одной подпрограммы Для получения serial.f просто прокомментируйте блок, содержащий парал вызова. Для получения paral.f просто прокомментируйте блок, содержащий серию вызовов. Я спрашиваю: это общая проблема? Как я могу решить это, чтобы поддерживать 4-кратное ускорение обслуживания цикла? Пожалуйста, обратите внимание : (1) Я пытался перевести на C, а время, тесты и проблемы остались прежними (2) Я пытался перевести на современный фортран, и сроки, критерии и проблемы остались прежними (3) Я перепробовал все виды трюков и переписывания кода. Я уверен, что проблема не в том, как подпрограмма распараллелена (я достиг 4 X), а в том, что она вызывается слишком много раз внутри цикла. Спасибо.

РЕДАКТИРОВАТЬ :: В соответствии с просьбой я публикую программу, написанную на современном фортране, которая описывает те же проблемы:

program main


use omp_lib

implicit none

integer ( kind = 4 ), parameter :: m = 5000
integer ( kind = 4 ), parameter :: n = 5000
integer ( kind = 4 ) i
integer ( kind = 4 ) j
integer ( kind = 4 ) nn
real ( kind = 8 ) u(m,n)
real ( kind = 8 ) w(m,n)
real ( kind = 8 ) wtime,h

call random_seed()


do j=1,n
  do i=1,m
    call random_number(u(i,j))
  end do
end do


wtime = omp_get_wtime ( )

do nn=1,100

!$omp parallel do default(none) shared(u, w) private(i,j)

do j = 2, n - 1
  do i = 2, m - 1
    w(i,j) = 0.25D+00 * ( u(i-1,j) + u(i+1,j) + u(i,j-1) + u(i,j+1) )
  end do
end do

!$omp end parallel do

end do

wtime = omp_get_wtime ( ) - wtime



h=0.0D+00
do j=1,n
  do i=1,m
    h=h+w(i,j)
  end do
end do



write ( *, '(a,g14.6)' ) '  Wall clock time serial= ', wtime
write ( *, '(a,g14.6)' ) '  h ', h

stop
end

Чтобы получить serial_with_loop.f90, просто закомментируйте директивы openmp и цикл nn. Вы также должны получить аналогичным методом parall_with_loop.f90 и serial и parall без цикла. Вы можете скомпилировать с помощью «gfortran -o name.out -fopenmp -O3 name.f90» и запустить с терминала с перенаправлением вывода в текстовый файл «name.out> time_result.txt»

...