微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenMP / OpenACC实施与gcc / PGI编译器之间的结果不一致

如何解决OpenMP / OpenACC实施与gcc / PGI编译器之间的结果不一致

我有一个较大的Fortran程序正在尝试转换,以便计算密集型部分将在使用OpenMP和/或OpenACC的NVidia GPU上运行。在开发期间,我遇到了一些问题,以了解如何在模块中声明的变量如何在GPU(以及其中一些也在cpu)上执行的子例程中使用。因此,我通过尝试并添加相应的OpenMP和OpenACC指令,创建了一个小示例并进行了研究。在此消息的末尾,我已经包括了构成我的示例的三个文件

就像我以为我已经理解了事情并且示例程序可以正常工作一样,我注意到了以下几点:

  • 我使用OpenMP指令使用gcc 10.2编译程序:
gfortran -O3 -fopenmp -Wall -Wextra test_link.f90 parameters.f90 common_vars.f90 -o test_link

结果符合预期,即数组XMO的所有元素均为1,DCP为2,IS1为3,IS2为24。

  • 我使用OpenACC指令使用PGI编译器19.10社区版编译程序:
pgfortran -O4 -acc -ta=tesla,cc35 -Minfo=all,mp,accel -Mcuda=cuda10.0 test_link.f90 common_vars.f90 parameters.f90 -o test_link

结果与上面相同。

  • 我使用OpenACC指令使用gcc 10.2编译程序:
gfortran -O3 -fopenacc -Wall -Wextra test_link.f90 parameters.f90 common_vars.f90 -o test_link

XMO,DCP和IS1数组的结果正确,但是IS2的所有元素均为0。很容易验证变量NR的值为0以获得此结果。

我的理解是,示例中的OpenMP和OpenACC版本是等效的,但我无法弄清为什么OpenACC版本仅适用于PGI编译器而不适用于gcc。

如果可能,请提供不需要在代码中进行更改而仅在指令中进行更改的解决方案。正如我提到的,我的原始代码要大得多,包含更多的模块变量,并在要在GPU上执行的代码调用了更多的子例程。对该代码进行更改将更加困难,显然,我更愿意仅在确实必要时进行更改。

提前谢谢!

我的示例文件如下。

File parameters.f90
MODULE ParaMETERS
  IMPLICIT NONE
  INTEGER,ParaMETER :: MAX_SOURCE_POSITIONS = 100
END MODULE ParaMETERS
File common_vars.f90
MODULE COMMON_VARS
  USE ParaMETERS
  IMPLICIT NONE

!$OMP DECLARE TARGET TO(NR)
  INTEGER :: NR
!$ACC DECLARE copYIN(NR)

END MODULE COMMON_VARS
File test_link.f90
      SUbroUTINE test()
       USE COMMON_VARS
        IMPLICIT NONE
!$OMP DECLARE TARGET
!$ACC ROUTINE SEQ
        INTEGER I
        I = NR
      END SUbroUTINE TEST


      PROGRAM TEST_LINK

      USE COMMON_VARS
      USE ParaMETERS

      IMPLICIT NONE

      INTERFACE
        SUbroUTINE test()
!$OMP DECLARE TARGET
!$ACC ROUTINE SEQ
        END SUbroUTINE TEST
      END INTERFACE

      REAL    :: XMO(MAX_SOURCE_POSITIONS),DCP(MAX_SOURCE_POSITIONS)
      INTEGER :: IS1(MAX_SOURCE_POSITIONS),IS2(MAX_SOURCE_POSITIONS)

      INTEGER :: X,Y,Z,MAX_X,MAX_Y,MAX_Z,ISOUR

      MAX_X = 3
      MAX_Y = 4
      MAX_Z = 5
      NR    = 6

!$OMP TARGET UPDATE TO(NR)
!$OMP TARGET MAP(TOFROM:IS1,IS2,DCP,XMO)
!$OMP TEAMS distribute ParaLLEL DO COLLAPSE(3)
!$ACC UPDATE DEVICE(NR)
!$ACC ParaLLEL LOOP GANG WORKER COLLAPSE(3) INDEPENDENT &
!$ACC copY(IS1,XMO)
      DO X = 1,MAX_X
         DO Y = 1,MAX_Y
            DO Z = 1,MAX_Z

               ISOUR = (X - 1)*MAX_Y*MAX_Z + (Y - 1)*MAX_Z + Z

               XMO(ISOUR) = 1.0
               DCP(ISOUR) = 2.0
               IS1(ISOUR) = 3
               IS2(ISOUR) = 4   * NR

               CALL test()

            ENDDO  ! End of z loop
         ENDDO     ! End of y loop
      ENDDO        ! End of x loop
!$ACC END ParaLLEL LOOP
!$OMP END TEAMS distribute ParaLLEL DO
!$OMP END TARGET

      DO X = 1,MAX_Z

               ISOUR = (X - 1)*MAX_Y*MAX_Z + (Y - 1)*MAX_Z + Z

               WRITE(*,*) 'ISOUR = ',ISOUR,'XMO = ',XMO(ISOUR),'DCP = ',DCP(ISOUR),'IS1 = ',IS1(ISOUR),'IS2 = ',IS2(ISOUR)

            ENDDO  ! End of z loop
         ENDDO     ! End of y loop
      ENDDO        ! End of x loop

      END PROGRAM TEST_LINK

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。