CUDA 5の新機能(4): nvprofプロファイラ

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

CUDAのドライバにはプロファイル機能が付いていて、CUDA_PROFILEという環境変数に1を設定してCUDAのプログラムを起動すると、カレントディレクトリにcuda_profile_0.log(数字の部分はGPU番号)というファイルに各Kernel実行のプロファイル情報が記録されるようになっている。ただ、Visual Profilerが登場すると、そちらの使用を推奨するようになったのか、昔はツールキットに詳細なマニュアルが付属していて、環境変数のオプションなどが細かく記されていたものが、4.xのころになるとマニュアルが付属しなくなり、半ば隠し機能のような状態になっていた。しかし、ドライバの機能であるため環境を問わずに手軽に使えるというメリットは大きく、実際筆者はこの環境変数によるプロファイル機能を使うことが多く、この微妙な状態の改善を望んでいた。

CUDA 5にはnvprofというコマンドが付属し、このコマンドの引数にプロファイルを採る対象のプログラムと引数を指定すると、プロファイルが採れるようなコマンドである。

$ nvprof /usr/local/cuda/samples/C/bin/linux/release/matrixMul
======== NVPROF is profiling matrixMul...
======== Command: matrixMul
[matrixMul] starting...

[Matrix Multiply Using CUDA] - Starting...
GPU Device 0: "GeForce GTX 580" with compute capability 2.0

MatrixA(320,320), MatrixB(640,320)
Computing result using CUDA Kernel...
done
Performance= 260.19 GFlop/s, Time= 0.504 msec, Size= 131072000 Ops, WorkgroupSize= 1024 threads/block
Checking computed result for correctness: OK

Note: For peak performance, please refer to the matrixMulCUBLAS example.
[matrixMul] test results...
PASSED

> exiting in 3 seconds: 3...2...1...done!

======== Profiling result:
 Time(%)      Time   Calls       Avg       Min       Max  Name
   99.73  151.24ms     301  502.47us  501.58us  503.67us  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
    0.15  232.87us       2  116.44us   88.71us  144.17us  [CUDA memcpy HtoD]
    0.12  177.70us       1  177.70us  177.70us  177.70us  [CUDA memcpy DtoH]

というように、実行の最後にプロファイル結果が表示される。プロファイル結果のみが欲しい場合は、まず-o リザルトファイル名のオプションをつけて、プロファイルをリザルトファイルに記録するようにする。

$ nvprof -o profile.dat /usr/local/cuda/samples/C/bin/linux/release/matrixMul
======== NVPROF is profiling matrixMul...
======== Command: matrixMul
[matrixMul] starting...

[Matrix Multiply Using CUDA] - Starting...
GPU Device 0: "GeForce GTX 580" with compute capability 2.0

MatrixA(320,320), MatrixB(640,320)
Computing result using CUDA Kernel...
done
Performance= 260.17 GFlop/s, Time= 0.504 msec, Size= 131072000 Ops, WorkgroupSize= 1024 threads/block
Checking computed result for correctness: OK

Note: For peak performance, please refer to the matrixMulCUBLAS example.
[matrixMul] test results...
PASSED

> exiting in 3 seconds: 3...2...1...done!

======== Generated result file: profile.dat

その後、-i リザルトファイルのオプションでnvprofコマンドを実行すれば、プロファイルのみが出力される。-iオプションを使う際は、プログラムの実行バイナリを指定する必要は無いので注意する。

$ nvprof -i profile.dat
======== Profiling result:
 Time(%)      Time   Calls       Avg       Min       Max  Name
   99.76  151.24ms     301  502.47us  501.34us  504.04us  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
    0.15  220.81us       2  110.41us   78.05us  142.76us  [CUDA memcpy HtoD]
    0.09  142.34us       1  142.34us  142.34us  142.34us  [CUDA memcpy DtoH]

出力形式は--print-summary-oを付けない場合のデフォルト)、--print-gpu-trace、そして--print-api-traceの3通りである。--print-summaryは上記のような出力であり、他のオプションはそれぞれ

--print-gpu-trace
$ nvprof -i profile.dat --print-gpu-trace
======== Profiling result:
     Start  Duration           Grid Size     Block Size     Regs*    SSMem*    DSMem*      Size  Throughput  Name
       0ns   78.05us                   -              -         -         -         -  409.60KB    5.25GB/s  [CUDA memcpy HtoD]
  403.83us  142.76us                   -              -         -         -         -  819.20KB    5.74GB/s  [CUDA memcpy HtoD]
  575.61us  502.12us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
    6.51ms  502.67us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
    7.01ms  502.34us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
    7.51ms  502.78us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
…長いので省略します…
  156.10ms  502.10us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
  156.60ms  502.53us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
  157.11ms  502.64us           (20 10 1)      (32 32 1)        24    8.19KB        0B         -           -  void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
  162.12ms  142.34us                   -              -         -         -         -  819.20KB    5.76GB/s  [CUDA memcpy DtoH]

Regs: Number of registers used per CUDA thread.
SSMem: Static shared memory allocated per CUDA block.
DSMem: Dynamic shared memory allocated per CUDA block.
--print-api-trace
$ nvprof -i profile.dat --print-api-trace
======== Profiling result:
     Start  Duration  Name
       0ns    1.00us  cuDeviceGetCount
   39.00us    1.00us  cuDeviceGet
   45.00us   47.00us  cuDeviceGetName
…長いので省略します…
  351.00us    1.00us  cuDeviceGetAttribute
  352.00us  105.00us  cuDeviceGetAttribute
  458.00us    1.00us  cuDeviceGetAttribute
    2.06ms   44.69ms  cudaMalloc
   46.75ms  108.00us  cudaMalloc
   46.86ms  106.00us  cudaMalloc
…長いので省略します…
  212.69ms   86.00us  cudaFree
  212.78ms   94.00us  cudaFree
  213.49ms   25.20ms  cudaDeviceReset

のような出力である。また、--csvのオプションを付けると、これらの出力がCSV形式で出力され、Excelなどの表計算ソフトで扱いやすいフォーマットとなる。

$ nvprof -i profile.dat --csv
======== Profiling result:
Time(%),Time,Calls,Avg,Min,Max,Name
,ms,,us,us,us,
99.76,151.2443,301,502.4720,501.3440,504.0370,"void matrixMulCUDA<int=32>(float*, float*, float*, int, int)"
0.15,0.22081,2,110.4070,78.05300,142.7610,"[CUDA memcpy HtoD]"
0.09,0.14234,1,142.3410,142.3410,142.3410,"[CUDA memcpy DtoH]"

また、プロファイルの採れるイベントは、--query-eventsオプションで一覧が表示される。

$ nvprof --query-events
======== Available Events:
                            Name   Description
Device 0:
	Domain domain_a:
                 sm_cta_launched:  Number of thread blocks launched on a multiprocessor.

               l1_local_load_hit:  Number of cache lines that hit in L1 cache for local memory load accesses. In case of perfect coalescing this increments by 1, 2, and 4 for 32, 64 and 128 bit accesses by a warp respectively.

              l1_local_load_miss:   Number of cache lines that miss in L1 cache for local memory load accesses. In case of perfect coalescing this increments by 1, 2, and 4 for 32, 64 and 128 bit accesses by a warp respectively.
…長いので省略します…
         l1_shared_bank_conflict:  Number of shared bank conflicts caused due to addresses for two or more shared memory requests fall in the same memory bank. Increments by N-1 and 2*(N-1) for a N-way conflict for 32 bit and 64bit shared memory accesses respectively.

       tex0_cache_sector_queries:  Number of texture cache requests. This increments by 1 for each 32-byte access.

        tex0_cache_sector_misses:  Number of texture cache misses. This increments by 1 for each 32-byte access.

	Domain domain_b:
           fb_subp0_read_sectors:  Number of DRAM read requests to sub partition 0, increments by 1 for 32 byte access.
…長いので省略します…
l2_subp1_total_write_sector_queries:  Total write requests to slice 1 of L2 cache. This includes requests from  L1, Texture cache, system memory. This increments by 1 for each 32-byte access.

	Domain domain_c:
                   gld_inst_8bit:  Total number of 8-bit global load instructions that are executed by all the threads across all thread blocks.
…長いので省略します…
                 gst_inst_128bit:  Total number of 128-bit global store instructions that are executed by all the threads across all thread blocks.

	Domain domain_d:
                      local_load:  Number of executed load instructions where state space is specified as local, increments per warp on a multiprocessor.
…長いので省略します…
                      gred_count:  Number of warps executing reduction operations on global and shared memory. Increments by one if at least one thread in a warp executes the instruction

プロファイル時にイベントを指定するには、--eventsオプションに続けて、コンマ区切りで上記のようなイベントを列挙すれば良い。

nvprof --events l1_local_load_hit,l1_local_load_miss /usr/local/cuda/samples/C/bin/linux/release/matrixMul
======== NVPROF is profiling matrixMul...
======== Command: matrixMul
[matrixMul] starting...

[Matrix Multiply Using CUDA] - Starting...
GPU Device 0: "GeForce GTX 580" with compute capability 2.0

MatrixA(320,320), MatrixB(640,320)
Computing result using CUDA Kernel...
done
Performance= 53.89 GFlop/s, Time= 2.432 msec, Size= 131072000 Ops, WorkgroupSize= 1024 threads/block
Checking computed result for correctness: OK

Note: For peak performance, please refer to the matrixMulCUBLAS example.
[matrixMul] test results...
PASSED

> exiting in 3 seconds: 3...2...1...done!

======== Profiling result:
		  Invocations       Avg       Min       Max  Event Name
Device 0
	Kernel: void matrixMulCUDA<int=32>(float*, float*, float*, int, int)
		          301         0         0         0  l1_local_load_hit
		          301         0         0         0  l1_local_load_miss

環境によっては

======== Error: unable to locate profiling library libcuinj64.so.5.0.24.

のようなエラーを表示してプログラムの実行に失敗することがあるが、Linuxではこのライブラリファイルは/usr/local/cuda/lib(64)の下に在り、LD_LIBRARY_PATH環境変数で指定すると、正しくプロファイルが採れるようになる。


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

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

<comments hideform="false" />


Comments

ノート:CUDA 5の新機能(4): nvprofプロファイラ

個人用ツール