我编译(使用GCC和PGI编译器)并在两个不同的平台(基于Haswell和Skylake)上运行一个小的Fortran / OpenMP程序,只是为了感受性能的差异。我不知道如何解释结果 - 这对我来说是个谜。
这是一个小程序(取自Nvidia开发人员网站,略有改编)。
PROGRAM main
use, intrinsic :: iso_fortran_env, only: sp=>real32, dp=>real64
use, intrinsic :: omp_lib
implicit none
real(dp), parameter :: tol = 1.0d-6
integer, parameter :: iter_max = 1000
real(dp), allocatable :: A(:,:), Anew(:,:)
real(dp) :: error
real(sp) :: cpu_t0, cpu_t1
integer :: it0, it1, sys_clock_rate, iter, i, j
integer :: N, M
character(len=8) :: arg
call get_command_argument(1, arg)
read(arg, *) N !!! N = 8192 provided from command line
call get_command_argument(2, arg)
read(arg, *) M !!! M = 8192 provided from command line
allocate( A(N,M), Anew(N,M) )
A(1,:) = 1
A(2:N,:) = 0
Anew(1,:) = 1
Anew(2:N,:) = 0
iter = 0
error = 1
call cpu_time(cpu_t0)
call system_clock(it0)
do while ( (error > tol) .and. (iter < iter_max) )
error = 0
!$omp parallel do reduction(max: error) private(i)
do j = 2, M-1
do i = 2, N-1
Anew(i,j) = (A(i+1,j)+A(i-1,j)+A(i,j-1)+A(i,j+1)) / 4
error = max(error, abs(Anew(i,j)-A(i,j)))
end do
end do
!$omp end parallel do
!$omp parallel do private(i)
do j = 2, M-1
do i = 2, N-1
A(i,j) = Anew(i,j)
end do
end do
!$omp end parallel do
iter = iter + 1
end do
call cpu_time(cpu_t1)
call system_clock(it1, sys_clock_rate)
write(*,'(a,f8.3,a)') "...cpu time :", cpu_t1-cpu_t0, " s"
write(*,'(a,f8.3,a)') "...wall time:", real(it1 it0)/real(sys_clock_rate), " s"
END PROGRAM
我使用的两个平台是:
在每个平台上,我用
编译了Fortran程序我显然在每个平台上独立编译程序(我只移动.f90文件;我没有移动任何二进制文件)
我在4个可执行文件中每个运行5次(每个平台2个),收集以秒为单位测量的墙壁时间(由程序打印出来)。 (好吧,我多次进行了整个测试,下面的时间肯定是代表性的)
顺序执行。使用以下程序编译的程序
计时(最好的5个):
多线程执行(8个主题)。编制的程序:
计时(最好的5个):
使用OpenMP进行编译时,我使用omp_get_num_threads()检查了并行区域中的线程数,实际上总是有8个线程,如预期的那样。
有几件事我不明白:
我如何从这些结果中找出一些意义?