50
パフォーマンス解析ツール 長岡技術科学大学 電気電子情報工学専攻 出川智啓

パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Embed Size (px)

Citation preview

Page 1: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

パフォーマンス解析ツール

長岡技術科学大学 電気電子情報工学専攻 出川智啓

Page 2: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

今回の内容

2015/05/20GPGPU実践プログラミング302

プロファイリング

Compute Profiler (Nsight)

Warpと並列実行の制約

Occupancy Calculator

ベクトル和のプロファイリング

Page 3: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

プログラムの挙動

2015/05/20GPGPU実践プログラミング303

経験的なプログラム高速化手法

スレッド数は128か256 メモリはアドレス順にアクセス

プログラム内部で挙動がどのように変化するか

パフォーマンスカウンタ機能による確認

プロファイリング

Page 4: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

プロファイリング

2015/05/20GPGPU実践プログラミング304

パフォーマンスカウンタの数値を出力

プログラム実行時の挙動の記録

ボトルネックの特定

プロファイラ

コマンドラインで実行するプロファイラ

Compute Profiler nvprof(CUDA 5以降)

GUIから操作するプロファイラ

Compute Visual Profiler Nsight

Page 5: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Compute Profiler

2015/05/20GPGPU実践プログラミング305

CUDAの実行環境に組み込まれたプロファイラ

環境変数を設定するだけで有効化

使い方

1. 環境変数の設定 $ export CUDA_PROFILE=1

2. プログラムの実行 $./a.out

3. プロファイル結果(標準はcuda_profile_0.log)の確認

Page 6: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Compute Profilerの環境変数

2015/05/20GPGPU実践プログラミング306

CUDA_PROFILE  1でプロファイル実行,0でプロファイル停止

CUDA_PROFILE_CONFIG プロファイル項目を記述したファイルの名前

CUDA_PROFILE_LOG 出力ファイル名(標準はcuda_profile_0.log)

CUDA_PROFILE_CSV 1で出力ファイルをCSV(カンマ区切り)形式に変更

Page 7: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

差分法のプロファイル

2015/05/20GPGPU実践プログラミング307

$ export CUDA_PROFILE=1

$ nvcc ‐arch=sm_20 differentiate.cu

$ ./a.out cuda_profile_0.logが出力される

$cat cuda_profile_0.log

Page 8: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

プロファイル結果の確認

2015/05/20GPGPU実践プログラミング308

標準で出力される値

method カーネルや関数(API)の名称

gputime GPU上で処理に要した時間(s単位)

cputime CPUで処理(=カーネル起動)に要した時間

実際の実行時間=cputime+gputime occupancy 同時実行されているWarp数と実行可能な 大

Warp数の比(一般的には1に近いほどよい)

$cat cuda_profile_0.log# CUDA_PROFILE_LOG_VERSION 2.0# CUDA_DEVICE 0 Tesla M2050# TIMESTAMPFACTOR fffff614a81cd038method,gputime,cputime,occupancymethod=[ memcpyHtoD ] gputime=[ 3285.216 ] cputime=[ 3657.000 ]method=[ _Z13differentiatePdS_ ] gputime=[ 197.408 ] cputime=[ 18.000 ] occupancy=[ 1.000 ]method=[ memcpyDtoH ] gputime=[ 3598.752 ] cputime=[ 4505.000 ]

Page 9: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

GPUの並列処理の実際

2015/05/20GPGPU実践プログラミング309

GPUのスレッドを管理

Streaming Multiprocessor内のCUDA Core数 Tesla世代 8 Fermi世代 32 Kepler世代 192 Maxwell世代 128

Warp(ウォープ)という処理の単位の導入

32スレッドをまとめて1 Warp 1 Warpごとに処理を実行

256スレッドの同時実行は不可能

Page 10: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

GPUの並列処理の実際

2015/05/20GPGPU実践プログラミング310

処理はWarp単位で実行

32スレッドごとに処理を実行

1ブロックあたりのスレッド数が256=Warp 8個

ある命令を発行すると,Warp単位で同じ命令を実行

Warp内でCUDA CoreはSIMD的に動作

複数のまとまったスレッドが同じ演算を同時に実行

SIMT(Single Instruction Multiple Threads)

厳密なSIMDではない

Page 11: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

GPUの並列処理の実際

パイプライン実行

あるWarpがグローバルメモリへアクセス,データ待ち

その他の実行可能なWarpが計算を実行

グローバルメモリへのアクセスのレイテンシを隠蔽

2015/05/20GPGPU実践プログラミング311

計算 メモリアクセス 計算Warp0

Warp1

Warp2

Warp3

実行開始 処理時間

計算 メモリアクセス 計算

計算 メモリアクセス 計算

計算 メモリアクセス

・・・

・・・

Page 12: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

GPUの並列処理の実際

2015/05/20GPGPU実践プログラミング312

Warpの同時実行

同時に実行されているWarp(Active Warp)が多いほどレイテンシ隠蔽が容易

Active Warpを多くすることで高速化

Warpの同時実行数はブロック内で使用している資源(レジスタ,共有メモリ)によって変化

占有率(Occupancy) 同時実行されているWarp数 と 実行可能な 大Warp数の比

一般的には1に近い方が高速

Page 13: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

並列実行に対する制約

2015/05/20GPGPU実践プログラミング313

GPUの構成(資源の量,スケジューラ)に起因するハードウェア的・ソフトウェア的制約

Tesla世代 Fermi世代

Warpサイズ 32スレッド

1ブロックあたりのスレッド数 512 1024

1SMあたりの 大スレッド数 1024 1536

1SMあたりのWarp数 32 48

1SMあたりのブロック数 8 8

1SMあたりの共有メモリサイズ 16384 byte 49152 byte

1SMあたりの32bitレジスタ数 16384本 32768本

https://www.softek.co.jp/SPG/Pgi/TIPS/public/accel/gpu‐accel2.html

Page 14: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

並列実行に対する制約

2015/05/20GPGPU実践プログラミング314

1ブロックあたりのスレッド数 256 1ブロックあたりのWarp数

256thread/block / 32thread/Warp = 8 Warp/block

1SMが処理するブロック数(1SMあたり 大48Warpを処理)

48 Warp/SM / 8 Warp/block =  6 block/SM(<8) 1SMあたり6ブロックを並列処理すればよい( 大8ブロック)

同時実行されるWarp数は

8 Warp/block × 6 block/SM = 48 Warp/SM. 1SMあたり 大48Warp同時実行できるので,占有率は

48 Warp/SM /48 Warp/SM = 1(=100%)

太字:利用するGPUによって決定下線:ユーザの設定により決まる値斜体:処理内容やコンパイラによって決定

Page 15: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

並列実行に対する制約

2015/05/20GPGPU実践プログラミング315

1ブロックあたりのスレッド数 64 1ブロックあたりのWarp数

64thread/block / 32thread/Warp = 2 Warp/block

1SMが処理するブロック数(1SMあたり 大48Warpを処理)

48 Warp/SM / 2 Warp/block = 24 block/SM(>8) 1SMあたり8ブロックを並列処理(24ブロックの処理は不可能)

同時実行されるWarp数は

2 Warp/block × 8 block/SM = 16 Warp/SM. 1SMあたり 大48Warp同時実行できるので,占有率は

16 Warp/SM /48 Warp/SM = 0.333(=33%)

太字:利用するGPUによって決定下線:ユーザの設定により決まる値斜体:処理内容やコンパイラによって決定

Page 16: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

並列実行に対する制約

2015/05/20GPGPU実践プログラミング316

並列実行されるブロックの数

1ブロックあたりの共有メモリやレジスタの使用量で制限

1ブロックあたりのスレッド数 Nt 1ブロックが利用する共有メモリS[byte]

49152/S [block/SM]

1スレッドが利用するレジスタR[本]32768/(Nt×R) [block/SM]

並列実行されるブロック数

min{8, 48/(Nt/32), 49152/S, 32768/(Nt×R)}

太字:利用するGPUによって決定下線:ユーザの設定により決まる値斜体:処理内容やコンパイラによって決定

Page 17: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Occupancyの計算

2015/05/20GPGPU実践プログラミング317

CUDA Occupancy Calculator NVIDIAが提供* Occupancy等の値を実行前に推定

必要な情報

GPUの世代

共有メモリのサイズ設定

64kBのうち何kBを共有メモリとするか

1ブロックあたりのスレッド数

1スレッドあたりのレジスタ使用数

1ブロックあたりの共有メモリ使用量

*http://developer.download.nvidia.com/compute/cuda/CUDA_Occupancy_calculator.xls

Page 18: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

CUDA Occupancy Calculator デモ

GPGPU実践プログラミング318 2015/05/20

Page 19: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

共有メモリやレジスタ数使用量の確認

2015/05/20GPGPU実践プログラミング319

コンパイルオプションを付加

‐Xptxas –v もしくは ‐‐ptxas‐options=‐v 実行可能バイトコードの情報を出力

$ nvcc ‐arch=sm_20 differentiate.cu ‐Xptxas ‐vptxas info    : Compiling entry function '_Z13differentiatePdS_' for 'sm_20'ptxas info    : Function properties for _Z13differentiatePdS_

0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loadsptxas info    : Used 19 registers, 48 bytes cmem[0], 12 bytes cmem[16]

使用レジスタ数 コンスタントメモリ使用量(サイズ)(コンパイラの 適化により利用)

Page 20: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

共有メモリやレジスタ数使用量の確認

2015/05/20GPGPU実践プログラミング320

共有メモリを利用したカーネル

コンスタントメモリを利用したカーネル

$ nvcc ‐arch=sm_20 differentiate_shared.cu ‐Xptxas ‐vptxas info    : Compiling entry function '_Z13differentiatePdS_' for 'sm_20'ptxas info    : Function properties for _Z13differentiatePdS_

0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loadsptxas info    : Used 18 registers, 2064+0 bytes smem, 48 bytes cmem[0], 4 bytes cmem[16]

共有メモリ使用量(サイズ)

$ nvcc ‐arch=sm_20 differentiate_constant.cu ‐Xptxas ‐vptxas info    : Compiling entry function '_Z13differentiatePdS_' for 'sm_20'ptxas info    : Function properties for _Z13differentiatePdS_

0 bytes stack frame, 0 bytes spill stores, 0 bytes spill loadsptxas info    : Used 13 registers, 2064+0 bytes smem, 48 bytes cmem[0], 8 bytes cmem[2]

Page 21: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

CUDA Occupancy Calculator デモ

GPGPU実践プログラミング321 2015/05/20

Page 22: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

レジスタ数の制約*

2015/05/20GPGPU実践プログラミング322

Compute Capalicity2.0世代のGPUのレジスタ利用

1 Warpあたり64本単位でレジスタを確保

レジスタ数が問題となってOccupancy100%の達成が困難

Occupancy 100%を達成するためには

ハードウェア的制約

1SMあたりのレジスタ数 32768本以下

1SMあたりのWarp数 48(=48×32スレッド)以下

1 Warpあたり64本単位でレジスタを確保

*http://www.gdep.jp/column/view/33

Page 23: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

レジスタ数の制約*

2015/05/20GPGPU実践プログラミング323

Occupancy 100%を達成するためには

1スレッドあたりの利用可能レジスタ数

32768本/(48Warp/SM×32thread/Warp)=21.3=21本/thread 1スレッドあたり21本以下

1 Warpが確保するレジスタ数

21本/thread×32thread/Warp=672→704(64の倍数)に切り上げ

1SMあたりの使用レジスタ数

704本/Warp×48Warp/SM=33792本/SM (>32768)

1スレッドあたりの使用レジスタ数が20本以下でないと100%を達成できない

*http://www.gdep.jp/column/view/33

Page 24: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

詳細なプロファイリング

2015/05/20GPGPU実践プログラミング324

gputime, cputime, occupancy以外のプロファイル

設定ファイルに測定する項目を記述

設定ファイルを環境変数CUDA_PROFILE_CONFIGで指定

prof.confがよく使われる

$ export CUDA_PROFILE_CONFIG=prof.conf 設定後,CUDA_PROFILE=1にしてプログラムを実行

$ export CUDA_PROFILE=1

Page 25: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

詳細なプロファイリング

2015/05/20GPGPU実践プログラミング325

prof.confの内容

Profiler User's Guide http://docs.nvidia.com/cuda/profiler‐users‐guide/index.html

4.3. Command Line Profiler Configuration中のTable 2 9. Metrics Reference中のTable 3

nvprofを利用することも可能(CUDA 5以降)

$ nvprof ‐‐query‐eventsの結果を参照

Page 26: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

カーネル起動に関する情報

GPGPU実践プログラミング326 2015/05/20

名称 内容

gpustarttimestamp カーネルもしくはメモリ転送開始時のタイムスタンプ(ns,64bit16進数)

gpuendtimestamp カーネルもしくはメモリ転送完了時のタイムスタンプ(ns,64bit16進数)

timestamp カーネル起動もしくはメモリ転送開始時のタイムスタンプ(s,単精度実数)

gridsize カーネル起動時のブロック数(x,y)

gridsize3d カーネル起動時のブロック数(x,y,z)

threadblocksize カーネル起動時のスレッド数(x,y,z)

dynsmemperblock 動的に割り当てられた共有メモリのサイズ

stasmemperblock 静的に割り当てられた共有メモリのサイズ

regperthread 1スレッドあたりのレジスタ数

memtransferdir メモリ転送の方向(0. host‐>device, 1. device‐>host)

memtransfersze メモリ転送サイズ

memtransferhostmemtype ホストメモリの種類(ページング可能かページロックか)

streamid カーネルを起動したストリームのID

cacheconfigrequested キャッシュ設定の要求 共有メモリ:L1キャッシュ0. 設定無し 1. 48kB:16kB2. 16kB:48kB  3. 32kB:32kBcacheconfigexecuted カーネル起動時のキャッシュ設定

Page 27: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

カーネル実行時のイベント

2015/05/20GPGPU実践プログラミング327

全てのGPUで取得できる情報

名称 内容

local_load ローカルメモリからの読込回数(1SM内のWarpあたり)

local store  ローカルメモリからの書込回数(1SM内のWarpあたり)

gld_request グローバルメモリからの読込回数(1SM内のWarpあたり)

gst_request グローバルメモリへの書込回数(1SM内のWarpあたり)

divergent_branch divergent branchの発生回数

branch  プログラム中の分岐命令の数

sm_cta_launched 1SM内で実行されたブロックの数

Page 28: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

カーネル実行時のイベント

2015/05/20GPGPU実践プログラミング328

Compute Capability 1.xのGPUで取得できる情報名称 内容

gld_incoherent 非コアレスアクセスによるグローバルメモリからの読込回数

gld_coherent コアレスアクセスによるグローバルメモリからの読込回数

gld_32b  32バイト単位で行われたグローバルメモリからの読込回数

gld_64b  64バイト単位で行われたグローバルメモリからの読込回数

gld_128b  128バイト単位で行われたグローバルメモリからの読込回数

gst_incoherent 非コアレスアクセスによるグローバルメモリへの書込回数

gst_coherent コアレスアクセスによるグローバルメモリへの書込回数

gst_32b  32バイト単位で行われたグローバルメモリへの書込回数

gst_64b  64バイト単位で行われたグローバルメモリへの書込回数

gst_128b  128バイト単位で行われたグローバルメモリへの書込回数

instructions  実行された命令数

warp_serialize 共有メモリ,コンスタントメモリでコンフリクトした回数

cta_launched 起動されたブロックの数

Page 29: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

カーネル実行時のイベント

2015/05/20GPGPU実践プログラミング329

Compute Capability 2.xのGPUで取得できる情報名称 内容

instructions_issued(バージョンによってはinst_issued)

命令発行数(命令のreplay*を含む)

instructions_issued1_0 命令群0の1命令発行に要するサイクル数

instructions_issued2_0 命令群0の2命令発行に要するサイクル数

instructions_issued1_1 命令群1の1命令発行に要するサイクル数

instructions_issued2_1 命令群1の2命令発行に要するサイクル数

instructions_executed(バージョンによってはinst_executed)

命令発行数(replayを含まない)

warps_launched 起動されたWarpの数(1SMあたり)

threads_launched 起動されたスレッドの数(1SMあたり)

active_cycles 1SM内で 低でも1 Warpが実行されたサイクル数

active_warps 1SM内でアクティブになったWarpの数の合計サイクルごとにアクティブなWarpの数(0~48の間で)を加算

shared_load 共有メモリからの読込回数(1SM内のWarpあたり)

shared_store 共有メモリへの書込回数(1SM内のWarpあたり)

*同一Warp内のスレッド

が同じ命令を逐次的に実行

バンクコンフリクト等が原因で並列実行できない場合に発生http://on‐demand.gputechconf.com/gtc‐express/2011/presentations/Inst_limited_kernels_Oct2011.pdf

Page 30: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

カーネル実行時のイベント

2015/05/20GPGPU実践プログラミング330

Compute Capability 2.xのGPUで取得できる情報名称 内容

l1_global_load_hit L1キャッシュにヒットしたグローバルメモリからの読込回数

l1_global_load_miss L1キャッシュでキャッシュミスしたグローバルメモリからの読込回数

l1_local_load_hit L1キャッシュにヒットしたローカルメモリからの読込回数

l1_local_load_miss L1キャッシュでキャッシュミスしたローカルメモリからの読込回数

l1_local_store_hit L1キャッシュにヒットしたローカルメモリへの書込回数

l1_local_store_miss L1キャッシュでキャッシュミスしたローカルメモリへの書込回数

l1_shared_bank_conflict 共有メモリ内でバンクコンフリクトした回数

uncached_global_load_transaction

キャッシュされないグローバルメモリからの読込回数32,64,128ビットアクセスに対して1,2,4で加算

global_store_transaction グローバルメモリへの書込回数32,64,128ビットアクセスに対して1,2,4で加算

Page 31: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

カーネル実行時のイベント

2015/05/20GPGPU実践プログラミング331

合計で70個程度(※動作は未確認)

•elapsed_cycles_sm•global_store_transaction•l1_global_load_hit•l1_global_load_miss•l1_local_load_hit•l1_local_load_miss•l1_local_store_hit•l1_local_store_miss•l1_shared_bank_conflict•sm_cta_launched•tex0_cache_sector_misses•tex0_cache_sector_queries•uncached_global_load_transaction•fb_subp0_read_sectors•fb_subp0_write_sectors•fb_subp1_read_sectors•fb_subp1_write_sectors•l2_subp0_read_hit_sectors•l2_subp0_read_sector_misses•l2_subp0_read_sector_queries•l2_subp0_read_sysmem_sector_queries•l2_subp0_read_tex_hit_sectors•l2_subp0_read_tex_sector_queries•l2_subp0_total_read_sector_queries•l2_subp0_total_write_sector_queries

•l2_subp0_write_sector_misses•l2_subp0_write_sector_queries l2•l2_subp0_write_sysmem_sector_queries•l2_subp1_read_hit_sectors•l2_subp1_read_sector_misses•l2_subp1_read_sector_queries•l2_subp1_read_sysmem_sector_queries•l2_subp1_read_tex_hit_sectors•l2_subp1_read_tex_sector_queries•l2_subp1_total_read_sector_queries•l2_subp1_total_write_sector_queries•l2_subp1_write_sector_misses l2 subp1•l2_subp1_write_sector_queries l2 subp1•l2_subp1_write_sysmem_sector_queries•gld_inst_128bit•gld_inst_16bit•gld_inst_32bit•gld_inst_64bit•gld_inst_8bit•gst_inst_128bit•gst_inst_16bit•gst_inst_32bit•gst_inst_64bit•gst_inst_8bit•active_cycles

•active_warps•atom_count•branch•divergent_branch•gld_request•gred_count•gst_request•inst_executed•inst_issued•local_load•local_store•prof_trigger_00•prof_trigger_01•prof_trigger_02•prof_trigger_03•prof_trigger_04•prof_trigger_05•prof_trigger_06•prof_trigger_07•shared_load•shared_store•thread_inst_executed_0•thread_inst_executed_1•threads_launched•warps_launched

http://www.ics.uci.edu/~roblim1/docs/cupticounters.txt

Page 32: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

プログラム挙動の確認

2015/05/20GPGPU実践プログラミング332

スレッド数の変化によるメモリアクセスの変化

グローバルメモリからの読込(prof_gld) gld_request l1_global_load_hit l1_global_load_miss

グローバルメモリへの書込(prof_gst) gst_request global_store_transaction

命令

inst_issued (prof_inst_issued) inst_executed (prof_inst_executed)

Page 33: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

#define N (512000)#define Nbytes (N*sizeof(float))#define NT (256)#define NB (N/NT) //=2000

__global__ void init(float *a,float *b, float *c){

int i = blockIdx.x*blockDim.x+ threadIdx.x;

a[i] = 1.0;b[i] = 2.0;c[i] = 0.0;

}__global__ void add(float *a,

float *b, float *c){int i = blockIdx.x*blockDim.x

+ threadIdx.x;c[i] = a[i] + b[i];

}

int main(void){float *a,*b,*c;

cudaMalloc((void **)&a, Nbytes);cudaMalloc((void **)&b, Nbytes);cudaMalloc((void **)&c, Nbytes);

init<<< NB, NT>>>(a,b,c);add<<< NB, NT>>>(a,b,c);

return 0;}

ベクトル和(コアレスアクセス版)

2015/05/20GPGPU実践プログラミング333

vectoradd_coalesce.cu

Page 34: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

#define N (512000)#define Nbytes (N*sizeof(float))#define NT (250)#define NB (N/NT) //=2048

__global__ void init(float *a,float *b, float *c){

int i = blockIdx.x*blockDim.x+ threadIdx.x;

a[i] = 1.0;b[i] = 2.0;c[i] = 0.0;

}__global__ void add(float *a,

float *b, float *c){int i = blockIdx.x*blockDim.x

+ threadIdx.x;c[i] = a[i] + b[i];

}

int main(void){float *a,*b,*c;

cudaMalloc((void **)&a, Nbytes);cudaMalloc((void **)&b, Nbytes);cudaMalloc((void **)&c, Nbytes);

init<<< NB, NT>>>(a,b,c);add<<< NB, NT>>>(a,b,c);

return 0;}

ベクトル和(非コアレスアクセス版)

2015/05/20GPGPU実践プログラミング334

vectoradd_noncoalesce.cu

Page 35: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

export CUDA_PROFILE=1nvcc ‐arch=sm_20 vectoradd_coalesce.cu#export CUDA_PROFILE_CONFIG=prof_gldexport CUDA_PROFILE_LOG=vectoradd_c_profile_gld.log./a.out#export CUDA_PROFILE_CONFIG=prof_gstexport CUDA_PROFILE_LOG=vectoradd_c_profile_gst.log./a.out#export CUDA_PROFILE_CONFIG=prof_inst_issuedexport CUDA_PROFILE_LOG=vectoradd_c_profile_inst_issued.log./a.out#export CUDA_PROFILE_CONFIG=prof_inst_executedexport CUDA_PROFILE_LOG=vectoradd_c_profile_inst_executed.log./a.out##

#nvcc ‐arch=sm_20 vectoradd_noncoalesce.cu#export CUDA_PROFILE_CONFIG=prof_gldexport CUDA_PROFILE_LOG=vectoradd_n_profile_gld.log./a.out#export CUDA_PROFILE_CONFIG=prof_gstexport CUDA_PROFILE_LOG=vectoradd_n_profile_gst.log./a.out#export CUDA_PROFILE_CONFIG=prof_inst_issuedexport CUDA_PROFILE_LOG=vectoradd_n_profile_inst_issued.log./a.out#export CUDA_PROFILE_CONFIG=prof_inst_executedexport CUDA_PROFILE_LOG=vectoradd_n_profile_inst_executed.log./a.out#export CUDA_PROFILE=0

コンパイルと実行(シェルスクリプト)

2015/05/20GPGPU実践プログラミング335

vectoradd.sh

Page 36: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

実行結果(ベクトル和のみ抜粋, Occupancyはどちらも1)

2015/05/20GPGPU実践プログラミング336

l1_global_load_missの値が増加

globa_store_transactionの値が大幅に増加

inst_issuedの値が大幅に増加

内容 コアレスアクセス 非コアレスアクセス

gputime+cputime(4回の平均)

56.808+103=159.808

76.616+122.5=199.116

gld_request 2336 2368

l1_global_load_hit 0 1941

l1_global_load_miss 2336 2577 

gst_request 1136 1168

global_store_transaction 1136 2252

inst_issued 24113 31399

inst_executed 19720 19992

Page 37: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

メモリアクセスの評価

2015/05/20GPGPU実践プログラミング337

transactions/request 1 Warpがアクセス要求に対してキャッシュラインをいくつ使うか

理想値

32 thread/Warp × variable size[byte/thread]/ 128 byte/line 

4バイト変数では1,8バイト変数では2

読込

(l1_global_load_hit+l1_global_load_miss)/gld_request

書込

global_store_transaction/gst_requet

Page 38: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

transactions/request

2015/05/20GPGPU実践プログラミング338

理想値

float型(4バイト)の読込 1 float型(4バイト)の書込 1

非コアレスアクセスではメモリ転送の効率が50%に低下

読込 書込

コアレスアクセス (2336+0)/2336=1 1136/1136=1

非コアレスアクセス (1941+2577)/2368≈2 2252/1168≈2

Page 39: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

プログラム挙動の確認

2015/05/20GPGPU実践プログラミング339

命令の実行に要したサイクルの評価

実行した命令数

inst_executed (prof_inst_executed)

Warpが起動したサイクル数

active_cycles (prof_cycle)

Page 40: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

#define N (8*1024) //64kBに収める#define Nbytes (N*sizeof(float))#define NT (256)#define NB (N/NT)

__global__ void init(float *a,float *b, float *c){

int i = blockIdx.x*blockDim.x+ threadIdx.x;

a[i] = 1.0;b[i] = 2.0;c[i] = 0.0;

}__global__ void add(float *a,

float *b, float *c){int i = blockIdx.x*blockDim.x

+ threadIdx.x;c[i] = a[i] + b[i];

}

int main(void){float *a,*b,*c;

cudaMalloc((void **)&a, Nbytes);cudaMalloc((void **)&b, Nbytes);cudaMalloc((void **)&c, Nbytes);

init<<< NB, NT>>>(a,b,c);add<<< NB, NT>>>(a,b,c);

return 0;}

GPUプログラム(グローバルメモリ利用)

2015/05/20GPGPU実践プログラミング

vectoradd.cu

340

Page 41: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

#define N (8*1024) #define Nbytes (N*sizeof(float))#define NT (256)#define NB (N/NT)__constant__ float a[N],b[N];

__global__ void init(float *c){int i = blockIdx.x*blockDim.x

+ threadIdx.x;c[i] = 0.0f;

}__global__ void add(float *c){

int i = blockIdx.x*blockDim.x+ threadIdx.x;

c[i] = a[i] + b[i];}int main(void){

float *c;float *host_a,*host_b;

int i;

host_a=(float *)malloc(Nbytes);host_b=(float *)malloc(Nbytes);cudaMalloc((void **)&c,Nbytes);for(i=0;i<N;i++){

host_a[i] = 1.0f;host_b[i] = 2.0f;

}cudaMemcpyToSymbol

(a,host_a,Nbytes);cudaMemcpyToSymbol

(b,host_b,Nbytes);init<<< NB, NT>>>(c);add<<< NB, NT>>>(c);

return 0;}

コンスタントメモリ(単純な置き換え)

2015/05/20GPGPU実践プログラミング

vectoradd_constant.cu

341

Page 42: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

#define N (8*1024) #define Nbytes (N*sizeof(float))#define NT (256)#define NB (N/NT)__constant__ float a, b;

__global__ void init(float *c){int i = blockIdx.x*blockDim.x

+ threadIdx.x;c[i] = 0.0f;

}__global__ void add(float *c){

int i = blockIdx.x*blockDim.x+ threadIdx.x;

c[i] = a + b;}int main(void){

float *c;float host_a,host_b;

host_a=1.0f;host_b=2.0f;cudaMalloc((void **)&c,Nbytes);

//host_a,host_bが配列ではないので//アドレスを取り出すために&を付けるcudaMemcpyToSymbol

(a,&host_a,sizeof(float));cudaMemcpyToSymbol

(b,&host_b,sizeof(float));init<<< NB, NT>>>(c);add<<< NB, NT>>>(c);

return 0;}

コンスタントメモリ(同一アドレス参照)

2015/05/20GPGPU実践プログラミング

vectoradd_broadcast.cu

342

Page 43: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

export CUDA_PROFILE=1#nvcc ‐arch=sm_20 vectoradd.cu#export CUDA_PROFILE_CONFIG=prof_inst_executedexport CUDA_PROFILE_LOG=vectoradd_profile_inst_executed.log./a.out#export CUDA_PROFILE_CONFIG=prof_cycleexport CUDA_PROFILE_LOG=vectoradd_profile_cycle.log./a.out##nvcc ‐arch=sm_20 vectoradd_constant.cu#export CUDA_PROFILE_CONFIG=prof_inst_executedexport CUDA_PROFILE_LOG=vectoradd_constant_profile_inst_executed.log

./a.out#export CUDA_PROFILE_CONFIG=prof_cycleexport CUDA_PROFILE_LOG=vectoradd_constant_profile_cycle.log./a.out

##nvcc ‐arch=sm_20 vectoradd_broadcast.cu#export CUDA_PROFILE_CONFIG=prof_inst_executedexport CUDA_PROFILE_LOG=vectoradd_broadcast_profile_inst_executed.log

./a.out#export CUDA_PROFILE_CONFIG=prof_cycleexport CUDA_PROFILE_LOG=vectoradd_broadcast_profile_cycle.log./a.out#export CUDA_PROFILE=0

コンパイルと実行(シェルスクリプト)

2015/05/20GPGPU実践プログラミング343

vectoradd_cycle.sh

Page 44: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

実行結果(ベクトル和のみ抜粋, Occupancyはどちらも1)

2015/05/20GPGPU実践プログラミング344

inst_issuedの値が減少

active_cyclesの値が大幅に増加

同じ処理の実行に余分なサイクルが必要

1サイクル(クロック)あたりの命令実行数(≠演算回数) グローバルメモリ 408/ 658=0.62 コンスタントメモリ 336/2984=0.11 ブロードキャスト 288/ 599=0.48

内容 グローバルメモリ コンスタントメモリ ブロードキャスト

gputime+cputime(2回の平均)

2.96+49=51.96

7.216+53.5=60.716

2.96+49.5=52.46

inst_executed 408  336 288

active_cycles 658 2984 599

Page 45: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

簡易的なプロファイリング(CUDA 5以降)

2015/05/20GPGPU実践プログラミング345

実行と同時にプロファイル結果を出力

$ nvprof ./a.out

$ nvprof ‐‐query‐events プロファイルできるイベント一覧を表示

$ nvprof ‐events inst_executed ./a.out プロファイルするイベントを指定して実行

Page 46: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Nsight デバッグ・プロファイルツール

https://developer.nvidia.com/nsight‐eclipse‐edition https://developer.nvidia.com/nvidia‐nsight‐visual‐studio‐edition

Visual StudioやEclipseと統合し,開発→デバッグ→プロファイリングが可能

GPGPU実践プログラミング346 2015/05/20

Page 47: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Available Events

2015/05/20GPGPU実践プログラミング347

The profiler supports logging of following counters during kernel execution only on GPUs with Compute Capability 2.0 or higher

Name description

instructions_issued Number of instructions issued including replays

instructions_issued1_0  Number of cycles that issue one instruction for instruction group 0

instructions_issued2_0  Number of cycles that issue two instructions for instruction group 0 

instructions_issued1_1  Number of cycles that issue one instruction for instruction group 1

instructions_issued2_1  Number of cycles that issue two instructions for instruction group 1 

instructions_executed Number of instructions executed, do not include replays

warps_launched Number of warps launched in a SM

threads_launched Number of threads launched in a SM

active_cycles Count of cycles in which at least one warp is active in a multiprocessor

active_warpsAccumulated count of no. of warps which are active per cycle in a multiprocessor. Each cycle increments it by the number of warps active in that cycle (in range 0‐48)

shared_load Number of executed shared load instructions per warp in a SM

shared_store Number of executed shared store instructions per warp in a SM

http://www.cs.cmu.edu/afs/cs/academic/class/15668‐s11/www/cuda‐doc/Compute_Profiler.txt

Page 48: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Available Events

2015/05/20GPGPU実践プログラミング348

The profiler supports logging of following counters during kernel execution only on GPUs with Compute Capability 2.0 or higher

Name description

l1_global_load_hit       Number of global load hits in L1 cache

l1_global_load_miss      Number of global load misses in L1 cache

l1_local_load_hit        Number of local load hits in L1 cache

l1_local_load_miss       Number of local load misses in L1 cache

l1_local_store_hit       Number of local store hits in L1 cache

l1_local_store_miss      Number of local store misses in L1 cache

l1_shared_bank_conflict  Count of no. of bank conflicts in shared memory

uncached_global_load_transaction

Number of uncached global load transactions. This increments by 1, 2 or 4 for 32, 64 and 128 bit accesses respectively

uncached_global_load_transaction

Number of uncached global load transactions. This increments by 1, 2, or 4 for 32, 64 and 128 bit  accesses respectively  

global_store_transaction Number of global store transactions. This increments by 1, 2, or 4 for 32, 64 and 128 bit accesses respectively

Page 49: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Available Events

2015/05/20GPGPU実践プログラミング349

The profiler supports logging of following counters during kernel execution only on GPUs with Compute Capability 2.0 or higher

Name description

l2_subp0_write_sector_misses   Accumulated write sector misses from L2 cache for slice 0 for all the L2 cache units   

l2_subp1_write_sector_misses   Accumulated write sectors misses from L2 cache for slice 1 for all the L2 cache units   

l2_subp0_read_sector_misses  Accumulated read sectors misses from L2 cache for slice 0 for all the L2 cache units   

l2_subp1_read_sector_misses  Accumulated read sectors misses from L2 cache for slice 1 for all the L2 cache units  

l2_subp0_write_sector_queries  Accumulated write sector queries from L1 to L2 cache for slice 0 of all the L2 cache units   

l2_subp1_write_sector_queries  Accumulated write sector queries from L1 to L2 cache for slice 1 of all the L2 cache units  

l2_subp0_read_sector_queries   Accumulated read sector queries from L1 to L2 cache for slice 0 of all the L2 cache units   

l2_subp1_read_sector_queries   Accumulated read sector queries from L1 to L2 cache for slice 1 of all the L2 cache units  

tex0_cache_sector_queries      Number of texture cache sector queries for texture unit 0 

tex0_cache_sector_misses Number of texture cache sector misses for texture unit 0 

tex1_cache_sector_queries Number of texture cache sector queries for texture unit 1 

tex1_cache_sector_misses Number of texture cache sector misses for texture unit 1 

Page 50: パフォーマンス解析ツール カーネルや関数(API )の名称 gputime GPU上で処理に要した時間( s単位) cputime CPUで処理(=カーネル起動)に要した時間

Available Events

2015/05/20GPGPU実践プログラミング350

The profiler supports logging of following counters during kernel execution only on GPUs with Compute Capability 2.0 or higher

Name description

fb_subp0_read_sectors Number of read requests sent to sub‐partition 0 of all the DRAM units 

fb_subp1_read_sectors Number of read requests sent to sub‐partition 1 of all the DRAM units

fb_subp0_write_sectors Number of write requests sent to sub‐partition 0 of all the DRAM units

fb_subp1_write_sectors Number of read requests sent to sub‐partition 1 of all the DRAM units

fb0_subp0_read_sectors Number of read requests sent to sub‐partition 0 of DRAM unit 0 

fb0_subp1_read_sectors Number of read requests sent to sub‐partition 1 of DRAM unit 0

fb0_subp0_write_sectors Number of write requests sent to sub‐partition 0 of DRAM unit 0 

fb0_subp1_write_sectors Number of write requests sent to sub‐partition 1 of DRAM unit 0 

fb1_subp0_read_sectors Number of read requests sent to sub‐partition 0 of DRAM unit 1 

fb1_subp1_read_sectors Number of read requests sent to sub‐partition 1 of DRAM unit 1 

fb1_subp0_write_sectors Number of write requests sent to sub‐partition 0 of DRAM unit 1 

fb1_subp1_write_sectors       Number of write requests sent to sub‐partition 1 of DRAM unit 1