两个平台(GCC和PGI编译器)上的Fortran / OpenMP比较。意外执行时间

时间:2017-03-10 09:51:03

标签: multithreading fortran openmp gfortran pgi

我编译(使用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

我使用的两个平台是:

  • Intel i7-4770 @ 3.40GHz(Haswell),32 GB RAM / Ubuntu 16.04.2 LTS
  • Intel i7-6700 @ 3.40GHz(Skylake),32 GB RAM / Linux Mint 18.1(~Ubuntu 16.04)

在每个平台上,我用

编译了Fortran程序
  • GCC gfortran 6.2.0
  • PGI pgfortran 16.10社区版

我显然在每个平台上独立编译程序(我只移动.f90文件;我没有移动任何二进制文件)

我在4个可执行文件中每个运行5次(每个平台2个),收集以秒为单位测量的墙壁时间(由程序打印出来)。 (好吧,我多次进行了整个测试,下面的时间肯定是代表性的)

  1. 顺序执行。使用以下程序编译的程序

    • gfortran -Ofast main.f90 -o gcc-seq
    • pgfortran -fast main.f90 -o pgi-seq

    计时(最好的5个):

    • Haswell&gt; gcc-seq:150.955,pgi-seq:165.973
    • Skylake&gt; gcc-seq:277.400,pgi-seq:121.794
  2. 多线程执行(8个主题)。编制的程序:

    • gfortran -Ofast -fopenmp main.f90 -o gcc-omp
    • pgfortran -fast -mp = allcores main.f90 -o pgi-omp

    计时(最好的5个):

    • Haswell&gt; gcc-omp:153.819,pgi-omp:151.459
    • Skylake&gt; gcc-omp:113.497,pgi-omp:107.863
  3. 使用OpenMP进行编译时,我使用omp_get_num_threads()检查了并行区域中的线程数,实际上总是有8个线程,如预期的那样。

    有几件事我不明白:

    • 使用GCC编译器:为什么Skylake OpenMP具有实质性的好处(277 vs 113 s),而在Haswell它没有任何好处? (150 vs 153 s)Haswell发生了什么?
    • 使用PGI编译器:为什么OpenMP在两个平台上都有这么小的好处(如果有的话)?
    • 关注顺序运行,为什么Haswell和Skylake之间的执行时间有如此巨大的差异(特别是当程序是用GCC编译的时候)?为什么这种差异仍然如此重要 - 但Haswell和Skylake的角色发生逆转! - 何时启用OpenMP?
    • 此外,当启用OpenMP并使用GCC时,cpu时间总是远大于挂起时间(正如我所料),但是当使用PGI时,cpu和wall时间总是相同的,然后是程序使用了多个线程。

    我如何从这些结果中找出一些意义?

0 个答案:

没有答案
相关问题