Я распараллелил подпрограмму. У него очень хороший тест: ускорение 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»