51
森野慎也, シニアCUDAエンジニア, エヌビディアジャパン CUDAデバッグ・プロファイリング入門

1076: CUDAデバッグ・プロファイリング入門

Embed Size (px)

Citation preview

Page 1: 1076: CUDAデバッグ・プロファイリング入門

森野慎也, シニアCUDAエンジニア, エヌビディアジャパン

CUDAデバッグ・プロファイリング入門

Page 2: 1076: CUDAデバッグ・プロファイリング入門

アジェンダCUDAのデバッグツールの紹介

CUDAデバッガ・メモリチェッカNsight Visual Studio Edition, Nsight Eclipse Edition

cuda-memcheck範囲外アクセス・未初期化値へのアクセス・同期チェックコマンドラインツール。 Windows、Linux、MacOS X上で同じ使い方ができる。

CUDA プロファイラの紹介

Nsight Visual Studio Edition

Nsight Eclipse Edition / Visual Profiler

Page 3: 1076: CUDAデバッグ・プロファイリング入門

CUDA デバッガNsight Visual Studio Edition (NVSE)

Windows 向け。Visual Studioと統合

Nsight Eclipse Edition

Linux・MacOS 向け。EclipseベースのIDE

cuda-gdb

LInux・MacOS向け。コマンドラインデバッガ。

Nsight Eclipse Editionのバックエンド

Page 4: 1076: CUDAデバッグ・プロファイリング入門

NSIGHT VISUAL STUDIO EDITIONVisual Studioに統合されている

VS2013を使用します。

コミュニティエディションが使える!

Professional相当

無償利用も可能。詳細は、以下をご確認んください。

http://www.microsoft.com/ja-jp/dev/products/community.aspx

Ver 対応状況

VS2010 deprecated

VS2012 〇

VS2013 〇

VS2015 未対応

Page 5: 1076: CUDAデバッグ・プロファイリング入門

サンプル : PREFIX SUMWarp Shuffle + シェアードメモリ

Warp (shuffle) Warp (shuffle) Warp (shuffle) Warp (shuffle)

32 32 32 32

Warp (shuffle)

32 64 92 128

Add Add Add

1 … 32 33 … 64 65 … 92 93 … 128

1 … 32 1 … 32 1 … 32 1 … 32

1, 1, 1, 1, … 1, 1, 1, 1, … 1, 1, 1, 1, … 1, 1, 1, 1, …入力

シェアードメモリ(SM内部にある)

シェアードメモリ

結果

Page 6: 1076: CUDAデバッグ・プロファイリング入門

ビルド設定

プロジェクトメニュー

→ ビルドのカスタマイズ

CUDA 7.5を選択。

Nsight Visual Studio Edition

Page 7: 1076: CUDAデバッグ・プロファイリング入門

デバッグ設定

- 「Code Generation」

使用するGPUのCCが設定されていること。(複数指定可)

- 「Generate GPU Debug Info」

「はい(-G)」に設定

Nsight Visual Studio Editionによるデバッグ

Page 8: 1076: CUDAデバッグ・プロファイリング入門

デバッグ

- Nsightメニュー

“CUDA Debugging…”を選択

- 実演

Nsight Visual Studio Edition

Break Point

ステップ実行

スレッド内の変数表示

Warp内のスレッド変数をウォッチ

SM上のWarpの一覧ダブルクリックで選択可能

Page 9: 1076: CUDAデバッグ・プロファイリング入門

NSIGHTでのメモリチェック

- 範囲チェックのみサポート

Nsight Visual Studio Edition

Page 10: 1076: CUDAデバッグ・プロファイリング入門

メモリチェックテストプログラム

__global__ void writeToMem(int *dMem) {

dMem[threadIdx.x] = 0;

}

int main() {

int *dMem;

cudaMalloc(&dMem, sizeof(int) * 255));

writeToMem<<<1, 256>>>(dMem);

(略)

Overrun

…Thread

Memory×

Page 11: 1076: CUDAデバッグ・プロファイリング入門

メモリチェック

- プログラムをデバッグ実行する。

エラー発生行で停止。

- Debugビルド・Releaseビルドの両方で使える。

Nsight Visual Studio Edition

エラー発生行で停止

エラー発生状況の説明表示

Page 12: 1076: CUDAデバッグ・プロファイリング入門

カーネル中のASSERT

- C言語のassertと同じ

- #define NDEBUGで、無効化

Nsight Visual Studio Edition

__global__

void kernelAssert() {

assert(0);

}

int main() {

kernelAssert<<<1, 1>>>();

cudaError_t cuerr = cudaDeviceSynchronize();

printf("%s¥n", cudaGetErrorName(cuerr));

}

実演する

Page 13: 1076: CUDAデバッグ・プロファイリング入門

カーネル中のASSERT

- デバッグ実行時

device_runtime.h中で停止出力に、詳細情報が現れる呼び出し履歴から発生行を表示

- 通常実行時

cudaErrorAssertが返される。

Nsight Visual Studio Edition

Page 14: 1076: CUDAデバッグ・プロファイリング入門

カーネル中のPRINTFNsight Visual Studio Edition

__global__ void printfKernel() {printf("blockIdx(%d, %d, %d) threadIdx(%d, %d, %d)¥n",

blockIdx.x, blockIdx.y, blockIdx.z,threadIdx.x, threadIdx.y, threadIdx.z);

}

int main() {dim3 gridDim(2), blockDim(8);

size_t size;cudaDeviceGetLimit(&size, cudaLimitPrintfFifoSize);printf("Printf FIFO size : %d¥n", (int)size);// cudaDeviceSetLimit(cudaLimitPrintfFifoSize, size);

printfKernel<<<gridDim, blockDim>>>();(略)

Page 15: 1076: CUDAデバッグ・プロファイリング入門

NSIGHT ECLIPSE EDITIONEclipse IDEに統合されたCUDA開発環境

Linux・MacOS向け

cuda-gdbをバックエンドとして利用する。

Jetsonのリモートデバッグもサポート

今日は、MakefileでのビルドとNsightでのデバッグを行います。

Page 16: 1076: CUDAデバッグ・プロファイリング入門

CUDAソースコードのコンパイル

- nvcc : CUDA用のコンパイラ

- 内部でホスト側コンパイラを使用

- デフォルトは、cl.exe(Windows)、g++(Linux)

- --ccbin で(icc, clang)など指定可能

- ホストコンパイラのオプションも受け付ける。

-Xcompiler <ホストコンパイラオプション>

NVCCの構成

18

ソース(*.cu)

ホスト/GPU ソース分割

ホストコンパイラ

デバイスコードコンパイラ

マージ

オブジェクト (*.o)

Page 17: 1076: CUDAデバッグ・プロファイリング入門

MAKEFILEの書き方デバッグ時のオプション

-G : 最適化無効。デバッグ情報の生成

実行速度は、一桁落ちると思ってよい。

-g or –Xcompiler –g

ホストコンパイラに、デバッグ情報の生成を行わせる。

Makefileのレビュー

Page 18: 1076: CUDAデバッグ・プロファイリング入門

起動・プロジェクトのインポート

起動 : $ nsight

メニューから

File -> New

-> Makefile Project withExisting Code

Nsight Eclipse Edition プロジェクト設定

Page 19: 1076: CUDAデバッグ・プロファイリング入門

プロジェクトの作成

- Project Name

- プロジェクト名

- Existing Code Location

- 既存のソースコードの場所

- Toochain for indexer Settings

- ソースのインデキサ設定

Nsight Eclipse Edition プロジェクト設定

Page 20: 1076: CUDAデバッグ・プロファイリング入門

デバッグ設定

- 「Debug Configurations…」を開く

- 「C/C++ Application」をダブルクリック

- 以下の項目を設定

Nameプロファイル名

C/C++ Application : バイナリ

Project : ソースがあるプロジェクト

Nsight Eclipse Edition

Page 21: 1076: CUDAデバッグ・プロファイリング入門

使用するGPUの設定

- Single GPUでのデバッグ (Beta)Kepler(CC3.5以降)、Maxwellが必要

- GPUのBreak pointでの停止

- ソフトウエアで状態を保存。

- システムがGPUを利用できるようにする。

- ブレーク中に終了するとフリーズする場合がある。

Nsight Eclipse Edition

Page 22: 1076: CUDAデバッグ・プロファイリング入門

デバッグ

- Blockスコープで、ステップ実行

Nsight Eclipse Edition

Break Point

ステップ実行

スレッド内の変数表示

GPU上のThread一覧ダブルクリックで選択可能

Page 23: 1076: CUDAデバッグ・プロファイリング入門

メモリチェッカの有効化

- デバッグ設定 / Debugger ペイン

- “Enable CUDA memcheck”をチェック

- Software Preemptionは使えない。(画面を書いていないGPUを使う)

Nsight Eclipse Edition

Page 24: 1076: CUDAデバッグ・プロファイリング入門

メモリチェッカ動作例Nsight Eclipse Edition

Page 25: 1076: CUDAデバッグ・プロファイリング入門

CUDA-MEMCHECK

- 機能

memcheck : 範囲チェック、デバイスメモリのリークをチェック

initcheck : 未初期化値へのアクセスをチェック

synccheck : 同期(__syncthreads())の、すべてのスレッド上の発行をチェック

racecheck : シェアードメモリ上でのハザードを検出

- ビルド時に “-lineinfo”を指定しておくこと。

エラーログ中に、エラー発生行が出力されます。

- Windows / Linux / MacOS X上で、使用法は同じ。

- 今日は、Windowsで動作させてみます。 (配布ファイル中に、ログを入れておきます。)

メモリチェックのためのコマンドラインツール

Page 26: 1076: CUDAデバッグ・プロファイリング入門

プロファイラ (WINDOWS)

Page 27: 1076: CUDAデバッグ・プロファイリング入門

タイムライン計測

タイムラインの計測

GPUの使用率

データ転送・カーネル実行時の時系列を可視化

GPUの稼働時間は、長いほうがよい

並列に、データ転送・CPU処理も行われているとよい。

プロファイラ

Page 28: 1076: CUDAデバッグ・プロファイリング入門

タイムライン取得設定

- 「Nsight」メニューから

「Start Performance Analysis… 」を選択

- Trace Applicationを選択

- Trace Seettingsから “CUDA”をチェック

Nsight Visual Studio Edition

Page 29: 1076: CUDAデバッグ・プロファイリング入門

DEFAULT STREAMでの処理実行Stream : GPU上の処理を管理するキュー

無指定の場合、Default (NULL) Streamが使用される。

t

Memcpy

Host → DeviceKernel

Memcpy

Device → Host

Default (NULL) Stream

Page 30: 1076: CUDAデバッグ・プロファイリング入門

タイムライン取得例Nsight Visual Studio Edition

H->D

memcpy

D->H

memcpy

カーネル

Page 31: 1076: CUDAデバッグ・プロファイリング入門

同期によるレイテンシの発生CPU→GPU : 処理開始までのレイテンシ発生

GPU→CPU : 同期によるレイテンシ

t

Memcpy

Host → DeviceKernel

Memcpy

Device → Host

GPU上での実行

t

MemcpyMemcpy

Device → Host

CPUからのタスク発行

同期待ち 同期待ち

Page 32: 1076: CUDAデバッグ・プロファイリング入門

MemcpyAsync

Host → DeviceKernel

MemcpyAsync

Device → Host

Device

Synchronize()CPU上で別の処理を行う

レイテンシの削減 ・ CPU/GPU上の並列処理非同期コピー(cudaMemcpyAsync()) を使用。

tGPU上での実行

t

CPUからのタスク発行

Page 33: 1076: CUDAデバッグ・プロファイリング入門

非同期MEMCPYを用いたタイムラインNsight Visual Studio Edition

memcpy、カーネル起動処理

Page 34: 1076: CUDAデバッグ・プロファイリング入門

パイプライン化メモリ転送・カーネル実行を、オーバーラップ

複数ストリームの使用

Stream 1

Stream 2

Stream 3

Memcpy

(H->D)Kernel

Memcpy

(D->H)

Memcpy

(H->D)Kernel

Memcpy

(D->H)

Memcpy

(H->D)Kernel

Memcpy

(D->H)

Page 35: 1076: CUDAデバッグ・プロファイリング入門

パイプライン化

実行時間

34.5 ms→ 19.0 ms

Nsight Visual Studio Edition

Page 36: 1076: CUDAデバッグ・プロファイリング入門

メモリアクセス解析・ビルド設定

- ビルド時に、行番号情報を生成

- ソースレベルプロファイリングで必須

Nsight Visual Studio Edition

Page 37: 1076: CUDAデバッグ・プロファイリング入門

プロファイラ設定

- Profile CUDA Applicationを選択

- Experiment Configuration

実施する計測を指定する。

今回は”All”を指定。

Nsignt Visual Studio Edition

Page 38: 1076: CUDAデバッグ・プロファイリング入門

メモリアクセス解析GPU(Maxwell)のデータパス

SM

Regis

ter

File

(変数

)

L2 C

ache

演算

Share

d

Mem

ory

CU

DA C

ore

s

Glo

bal M

em

ory

(GPU

DRAM

)

Host

(PC)

DRAM

PCIe

高速 (数TB / sec) 低速 (~ 10 GB/sec)L1/Te

x

Cache*

*CC 5.2で、R/W可能なL1キャッシュを有効可能

Global

Tex

Local

Page 39: 1076: CUDAデバッグ・プロファイリング入門

GPU内のデータトラフィック表示

- 以下を表示できる

Bandwidth

Size (Load/Store)

Size (Load)

Size (Store)

- 遅いデータパス上でのデータアクセスを減らせないか…

Nsight Eclipse Edition

Global Memory B/W

まず確認する値

Page 40: 1076: CUDAデバッグ・プロファイリング入門

アクセスパターン分析

- AoS : Array of Structures

CPU上でのスタイル

構造化・Object志向

サンプル : memoryAccess

- SoA : Structure of Arrays

GPU上でアクセス効率がよい

struct XY {

float x;

float y;

};

XY xyArray[1024];

struct XYArray {

float x[1024];

float y[1024];

};

Page 41: 1076: CUDAデバッグ・プロファイリング入門

コアレスアクセス

コアレス(Coalesced) アクセス と呼びます

理想的なアクセス

v0 v1 v2 v3 v4 v5 v6 v7 v8

Thread

Memory

Page 42: 1076: CUDAデバッグ・プロファイリング入門

アクセスパターンの違いAoS vs SoA

x y x y

x y x y

1) xをアクセス

2) yをアクセス

x xx x

y y y y

x xx x

y y y y

AoS:

アクセスに抜けがある。効率悪い。

SoA:

アクセスが連続。効率よい。

Page 43: 1076: CUDAデバッグ・プロファイリング入門

AOSのアクセス例

- L2 Transfer Overhead

L2 → L1転送バイト数

使用されるバイト数

- 期待値は 2

- より詳細にみる

アクセスパターン分析

Page 44: 1076: CUDAデバッグ・プロファイリング入門

ソースレベルの表示アクセスパターン分析

Page 45: 1076: CUDAデバッグ・プロファイリング入門

分岐の解析Warp Divergence

Thread- 両方のパスを実行する必要がある。

- 性能が落ちる原因。if (cond) {

}else {

}

Page 46: 1076: CUDAデバッグ・プロファイリング入門

ソースコード

- Global IDが、偶数・奇数で分岐

- 最適化されないよう、メモリフェンス(__threadfence_block())を、入れてあります

分岐の解析

__global__

void divergentExecutionKernel(float *dMem) {

int gid =

blockDim.x * blockIdx.x + threadIdx.x;

float angle =

float(gid % 360) * float(M_PI / 180.f);

if (gid % 2 == 0) {

dMem[gid] = __sinf(angle);

__threadfence_block();

}

else {

dMem[gid] = __cosf(angle);

}

}

Page 47: 1076: CUDAデバッグ・プロファイリング入門

BRANCH STATISTICS

- 50 %の分岐にDivergenceがある。

- ソースコードレベルで確認する。

分岐の解析

Page 48: 1076: CUDAデバッグ・プロファイリング入門

DIVERGENT BRANCH

- 17行目の分岐が、Divergeしている。

分岐の解析

Page 49: 1076: CUDAデバッグ・プロファイリング入門

ソースコードの表示

- if分の中の__cos()での分岐を表示していた。

分岐の解析

Page 50: 1076: CUDAデバッグ・プロファイリング入門

プロファイラ (LINUX)Windows上と同等の内容を、時間の許す限り、デモンストレーションします。

Page 51: 1076: CUDAデバッグ・プロファイリング入門

THANK YOU