OpenMPによるPGI AcceleratorのマルチGPU化

出典: トータル・ディスクロージャ・サイト(事実をありのままに)

以前紹介した、PGI Acceleratorは、マルチGPUに対応しているようであるが、マルチGPU絡みの情報が不足している。今回は、OpenMPを用いて、PGI AcceleratorのプログラムをマルチGPU並列化するテストを行うことにした。

目次

マルチGPUのAPIについて

通常のCUDAのAPIである、cudaSetDeviceでは、PGI AcceleratorをマルチGPUに対応させることは、現状では不可能なようである。代わりとなるPGI AcceleratorのAPIは、以下のものである。なお、以下のAPIは、accel_libモジュールに含まれているので、事前にuseする必要がある。

acc_get_num_devices
システムに搭載されているGPUの数を返す。第1引数には、定数「acc_device_nvidia」を渡す。
acc_set_device_num
PGI Acceleratorが使うGPUを指定する。第1引数にGPU番号を入力し、第2引数に定数「acc_device_nvidia」を渡す。GPU番号は、最初のGPUが0で、以下1ずつ増えていく通し番号である。

プログラム例

簡単な行列積計算のPGI Acceleratorプログラムを、OpenMPを使って並列化する。並列化していないバージョンが、

      PROGRAM MATMUL_MULTIGPU
      USE OMP_LIB
      USE ACCEL_LIB
      IMPLICIT NONE
      INTEGER I,J,K,N
      PARAMETER(N=4000)
      REAL A(N,N),B(N,N)
      REAL*8 T1,T2,SUM

      DO 20 J=1,N
         DO 10 I=1,N
            A(I,J)=REAL(I*N+J)/REAL(N*N)
 10      CONTINUE
 20   CONTINUE
      CALL CPU_TIME(T1)
C$ACC REGION COPYIN(A), COPYOUT(B)
C$ACC DO PARALLEL PRIVATE(I,J,K)
      DO 50 J=1,N
         DO 40 I=1,N
            B(I,J)=0.0
            DO 30 K=1,N
               B(I,J)=B(I,J)+A(I,K)*A(K,J)
 30         CONTINUE
 40      CONTINUE
 50   CONTINUE
C$ACC END REGION
      CALL CPU_TIME(T2)
      WRITE(*,*)T2-T1,'SEC'
      SUM=0.0
      DO 70 J=1,N
         DO 60 I=1,N
            SUM=SUM+B(I,J)
 60      CONTINUE
 70   CONTINUE
      WRITE(*,*)'CHECKSUM =',SUM
      STOP
      END PROGRAM MATMUL_MULTIGPU

であるところ、並列化して、

      PROGRAM MATMUL_MULTIGPU
      USE OMP_LIB
      USE ACCEL_LIB
      IMPLICIT NONE
      INTEGER I,J,K,N
      PARAMETER(N=4000)
      REAL A(N,N),B(N,N)
      REAL*8 T1,T2,SUM
      INTEGER NGPU,IOMP,NOMP,JMIN,JMAX
      DO 20 J=1,N
         DO 10 I=1,N
            A(I,J)=REAL(I*N+J)/REAL(N*N)
 10      CONTINUE
 20   CONTINUE
      CALL CPU_TIME(T1)
      NGPU=ACC_GET_NUM_DEVICES(ACC_DEVICE_NVIDIA)
C$OMP PARALLEL DEFAULT(NONE),NUM_THREADS(NGPU)
C$OMP& SHARED(N,A,B,ACC_DEVICE_NVIDIA)
C$OMP& PRIVATE(I,J,K,IOMP,NOMP,JMIN,JMAX)
      IOMP=OMP_GET_THREAD_NUM()
      NOMP=OMP_GET_NUM_THREADS()
      CALL ACC_SET_DEVICE_NUM(IOMP,ACC_DEVICE_NVIDIA)
      JMIN=IOMP*N/NOMP+1
      JMAX=(IOMP+1)*N/NOMP
C$ACC REGION COPYIN(A), COPYOUT(B(1:N,JMIN:JMAX))
C$ACC DO PARALLEL PRIVATE(I,J,K)
      DO 50 J=JMIN,JMAX
         DO 40 I=1,N
            B(I,J)=0.0
            DO 30 K=1,N
               B(I,J)=B(I,J)+A(I,K)*A(K,J)
 30         CONTINUE
 40      CONTINUE
 50   CONTINUE
C$ACC END REGION
C$OMP END PARALLEL
      CALL CPU_TIME(T2)
      WRITE(*,*)T2-T1,'SEC'
      SUM=0.0
      DO 70 J=1,N
         DO 60 I=1,N
            SUM=SUM+B(I,J)
 60      CONTINUE
 70   CONTINUE
      WRITE(*,*)'CHECKSUM =',SUM
      STOP
      END PROGRAM MATMUL_MULTIGPU

のような、acc_get_num_devicesでGPUの数を得た後、OpenMPでその数だけスレッドを走らせ、acc_get_device_numでOpenMPのスレッド番号のGPUを指定し、計算を行うプログラムとする。

実行環境

CPU: 6コア Xeon X5690 3.47 GHz × 2
GPU: Tesla M2090 × 4
OS: Windows 7 Professional SP1
コンパイラ: PGI Accelerator Workstation 11.10
GPUドライバ: バージョン276.42

実行結果

並列化前が

    1.824000000000000      SEC
 CHECKSUM =    16017339253.05869

であったところ、マルチGPUでは

    0.697000000000000      SEC
 CHECKSUM =    16017339253.05869

となり、1.824秒:0.697秒 = 約2.62倍の並列化効果が、マルチGPU化によって出ていることがわかる。


この記事へのコメントをお寄せください

  • サイトへの書き込みに差し支えございましたら トータルディスクロージャーサイトサポート係へメールをお送りください
  • トータル・ディスクロージャ・サイトに投稿された文章と画像は、すべてその著作権がHPCシステムズ株式会社に帰属し、HPCシステムズ株式会社が著作権を所有することに同意してください。
  • あなたの文章が他人によって自由に編集、配布されることを望まない場合は、投稿を控えてください。
  • コメントを書き込む場合は名前にひらがなを織り交ぜてください。
  • あなたの投稿する文章と画像はあなた自身によって書かれたものであるか、パブリック・ドメインかそれに類する自由なリソースからの複製であることを約束してください。あなたが著作権を保持していない作品を許諾なしに投稿してはいけません!

<comments hideform="false" />


Comments

ノート:OpenMPによるPGI AcceleratorのマルチGPU化

個人用ツール