PGI_ACC_TIME
データ転送を 1 回だけにした場合のプロファイル
Accelerator Kernel Timing data
/home/kato/GPGPU/OpenMP/DOUBLE/OpenACC/jacobi2.F jacobi
205: region entered 100 times
time(us): total=1915950 init=3 region=1915947 kernels=1893866 data=0
w/o init: total=1915947 max=19442 min=19148 avg=19159 207: kernel launched 100 times
grid: [640x625] block: [8x8]
time(us): total=519232 max=5197 min=5169 avg=5192 215: kernel launched 100 times
grid: [640x625] block: [8x8]
time(us): total=1317873 max=13186 min=13172 avg=13178 223: kernel launched 100 times
grid: [1] block: [256]
time(us): total=56761 max=569 min=566 avg=567 /home/kato/GPGPU/OpenMP/DOUBLE/OpenACC/jacobi2.F
jacobi
199: region entered 1 time
time(us): total=2122461 init=87485 region=2034976 data=112926
w/o init: total=2034976 max=2034976 min=2034976 avg=2034976
データ転送時間(0秒)
kernels構⽂の領域の情報
データ構⽂の領域のプロファイル情報、1回のみ
データ転送時間(0.11秒)
3つのkernel の存在
次は、この時間をチューニングする
OpenACC 実行性能 サマリー
OpenMP
性能 とOpenACC
性能 時間(
秒)
倍率1 core スレッド (without SSE vector) -O3 26.19
1 core
スレッド(with SSE vector) -fastsse 13.15
OpenMP 4 core
スレッド並列性能-mp -fastsse 8.74 x 1.0
OpenACC (
対象ループにkernels
構文のみ挿入) 17.95
OpenACC (
繰返ループの外側にdata
構文を挿入) 2.32 x 3.7
(倍精度演算)
OpenMP
性能: Intel(R) Core(TM) i7 CPU 920 @ 2.67GHz (Nehalem) 4core OpenACC
性能: (Host)
同上: (GPU) NVIDIA GeForce GTX 580
Loop Directives で並列動作を調整
error = 10.0 * tol k = 1
!$acc data copy(u(1:n,1:m))
!$acc+ copyin(f(1:n,1:m)) create(uold(1:n,1:m)) do while (k.le.maxit .and. error.gt. tol)
error = 0.0
* Copy new solution into old
!$acc kernels do j=1,m
do i=1,n
uold(i,j) = u(i,j) enddo
enddo
!$acc loop gang, vector(8) do j = 2,m-1
!$acc loop gang, vector(8) do i = 2,n-1
resid = (ax*(uold(i-1,j) + uold(i+1,j))
& + ay*(uold(i,j-1) + uold(i,j+1))
& + b * uold(i,j) - f(i,j))/b u(i,j) = uold(i,j) - omega * resid error = error + resid*resid end do
enddo
!$acc end kernels
* Error check k = k + 1
error = sqrt(error)/dble(n*m)
enddo ! End iteration loop
!$acc end data Accelerator並列領域の開始
Accelerator並列領域の終了
コンパイラは、自動的に対象並列ループを CUDAのThread-block/Grid に
分割マッピングする
ブロック分割等の mapping を 明⽰的に変更することが可能
gang, vector
の並列スケジューリングを変えて 試行錯誤が必要
より良い性能を出すには、
Accelerator ループ・マッピングを変更する
!$acc loop gang(16) vector(16) ( 235) do j = 2,m-1
!$acc loop gang(16) vector(16) ( 237) do i= 2,n-1
( 238) resid = (ax*(uold(i-1,j) + uold(i+1,j)) ( 239) & + ay*(uold(i,j-1) + uold(i,j+1)) ( 240) & + b * uold(i,j) - f(i,j))*b1b ( 241) u(i,j) = uold(i,j) - omega * resid ( 242) error = error + resid*resid ( 243) end do
( 244) enddo
!$acc end region jacobi:
217, Generating local(uold(:,:)) Generating local(resid) Generating copyin(f(:n,:m)) Generating copy(u(:n,:m)) 235, Loop is parallelizable 237, Loop is parallelizable
Accelerator kernel generated
235, !$acc loop gang(16), vector(16) ! blockidx%y threadidx%y 237, !$acc loop gang(16), vector(16) ! blockidx%y threadidx%y
CC 1.3 : 26 registers; 2176 shared, 36 constant, 0 local memory bytes; 50% occupancy CC 2.0 : 26 registers; 2056 shared, 144 constant, 0 local memory bytes; 66% occupancy 242, Sum reduction generated for error
loop scheduling 節を変更
例えば、Grid size (16 x16)
Block size (16 x16)
実行プロファイル情報で性能評価
235, !$acc loop gang(16), vector(16) ! blockidx%y threadidx%y 237, !$acc loop gang(16), vector(16) ! blockidx%x threadidx%x 235, !$acc loop gang, vector(8) ! blockidx%y threadidx%y
237, !$acc loop gang, vector(8) ! blockidx%x threadidx%x
237: kernel launched 100 times grid: [16x16] block: [16x16]
time(us): total=729351 max=7365 min=7223 avg=7293
全体の実行時間:
1.32
秒237: kernel launched 100 times
grid: [640x625] block: [8x8]
time(us): total=1318241 max=13189 min=13176 avg=13182
loop scheduling(grid/block size)の変更で性能が変わる全体の実行時間:2.32秒
Device Name: GeForce GTX 580 (上記は倍精度計算)
μ
秒OpenACC 実行性能 サマリー
OpenMP
性能 とOpenACC
性能 時間(
秒)
倍率1 core スレッド (without SSE vector) -O3 26.19
1 core
スレッド(with SSE vector) -fastsse 13.15
OpenMP 4 core
スレッド並列性能-mp -fastsse 8.74 x 1.0
OpenACC (
対象ループにkernels
構文のみ挿入) 17.95
OpenACC (
繰返ループの外側にdata
構文を挿入) 2.32 x 3.7
OpenACC (対象ループを loop 節で並列 mapping 調整) 1.32 x 6.6
(倍精度演算)
OpenMP
性能: Intel(R) Core(TM) i7 CPU 920 @ 2.67GHz (Nehalem) 4core OpenACC
性能: (Host)
同上: (GPU) NVIDIA GeForce GTX 580
プログラム全体にスコープ範囲を広げる
subroutine driver (u,f)
* dx - grid spacing in x direction
* dy - grid spacing in y direction (配列宣⾔等は省略)
* Initialize data cpu0 = second()
!$acc data copy (u,f)
call initialize (n,m,alpha,dx,dy,u,f)
* Solve Helmholtz equation
call jacobi (n,m,dx,dy,alpha,relax,u,f,tol,mits)
* Check error between exact solution
call error_check (n,m,alpha,dx,dy,u,f)
!$acc end data
cpu1 = second()
* Printout Elapsed time
elapsed = (cpu1 -cpu0) * t_ac print '(/,1x,a,F10.3/)', &
‘ Elpased Time (Initialize + Jacobi solver + Check) : ',elapsed return
end
u()
とf()
配列が、プログラム全体で 使用されるu()
とf()
配列が、プログラム全体で 使用される各手続上では、
u, f
配列に係わる 計算処理をGPU kernel 化するだけ
各手続上では、u, f
配列に係わる 計算処理をGPU kernel 化するだけ u()
とf()
配列 をCopyin to GPU u()
とf()
配列 をCopyin to GPU
u() と f() 配列 を Copyout to Host
u() と f() 配列 を Copyout to Host
コンパイラ・フィードバック情報
driver:
108, Generating copy(f(:,:)) Generating copy(u(:,:)) (以下、省略)
initialize:
152, Generating present(u(:,:)) Generating present(f(:,:)) (以下、省略)
jacobi:
215, Generating present_or_copyin(f(:,:)) Generating present_or_copy(u(:,:)) Generating local(resid)
Generating local(uold(1:n,1:m)) (以下、省略)
error_check:
275, Generating present(u(:,:)) (以下、省略)
(データ構文に関するもののみ抽出) subroutine initialize (n,m,alpha,dx,dy,u,f) real*8 u(n,m),f(n,m),dx,dy,alpha
!$acc kernels copyin(dx,dy,alpha) present(u,f)
!$acc loop gang private(xx,yy) do j = 1,m
!$acc loop vector(256) do i = 1,n
xx = -1.0 + dx * real(i-1) ! -1 < x < 1 yy = -1.0 + dy * real(j-1) ! -1 < y < 1 u(i,j) = 0.0
f(i,j) = -alpha *(1.0-xx*xx)*(1.0-yy*yy)
& - 2.0*(1.0-xx*xx)-2.0*(1.0-yy*yy) enddo
enddo
!$acc end kernels return
u()
とf()
配列に関しては、既にu()
とf()
配列に関しては、既にpresent
節の意味OpenACC 実行性能 サマリー
OpenMP
性能 とOpenACC
性能 時間(
秒)
倍率1 core スレッド (without SSE vector) -O3 26.19
1 core
スレッド(with SSE vector) -fastsse 13.15
OpenMP 4 core
スレッド並列性能-mp -fastsse 8.74 x 1.0
OpenACC (
対象ループにkernels
構文のみ挿入) 17.95
OpenACC (
繰返ループの外側にdata
構文を挿入) 2.32 x 3.7
OpenACC (対象ループを loop 節で並列 mapping 調整) 1.32 x 6.6
OpenACC (main
プログラム上にdata
構文& present
節使用) 1.23 x 7.1 (倍精度演算)
OpenMP
性能: Intel(R) Core(TM) i7 CPU 920 @ 2.67GHz (Nehalem) 4core OpenACC
性能: (Host)
同上: (GPU) NVIDIA GeForce GTX 580
ポーティング・開発時における便利なツール等
• NVIDIA Visual Profiler
ストリーム、イベント等挙動の視覚的な把握 詳細なカーネル特性の把握
• PGI 環境変数
• ACC_NOTIFY
kernel 動作の実行時履歴の出力
• PGI_ACC_DEBUG
実行時の CUDA システムコールのイベントログ出力
NVIDIA Visual Profiler を使う
[kato@photon29]$ make jacobi4.exe
pgfortran -o jacobi4.exe jacobi4.F -fastsse -acc -ta=nvidia:cuda4.1 [kato@photon29]$ which nvvp
/usr/local/cuda/bin/nvvp
[kato@photon29]$ nvvp (NVIDIA Visual Profiler の起動)
実行モジュール
jacobi4.exe の指定 CUDA toolkit 4.1 を使用するように 指示する
起動
コンパイル
NVIDIA Visual Profiler 4.1
を使用するNVIDIA CUDA Visual Profiler(1)
データコピーが頻繁!
データコピーが頻繁!
GPU GPU
特性、全体性能特性特性、全体性能特性この
stream
全体の挙動が色別で分かるデータ転送(カーキー色)が卓越
この
stream
全体の挙動が色別で分かるデータ転送(カーキー色)が卓越
NVIDIA CUDA Visual Profiler(2)
Compute kernels
の実行が主体Compute kernels
の実行が主体Kernel
の実行特性Kernel
の実行特性この
stream
全体の挙動が色別で分かるカーネル実行(ピーコックブルー色)が卓越
この
stream
全体の挙動が色別で分かるカーネル実行(ピーコックブルー色)が卓越
NVIDIA CUDA Visual Profiler(3)
Kernel の実行特性 Kernel の実行特性 Timeline
の詳細Timeline
の詳細個々のイベント特性の詳細 個々のイベント特性の詳細