CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター...

42
CUDA基礎2 東京工業大学 学術国際情報センター 黄 遠雄 1 2016/6/27 20GPU コンピューティング 講習会

Transcript of CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター...

Page 1: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

CUDA基礎2

東京工業大学 学術国際情報センター

黄 遠雄

1 2016/6/27 第20回 GPU コンピューティング 講習会

Page 2: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

データ競合

2016/6/27 第20回 GPU コンピューティング 講習会 2

Multi threads

多数のthreadが、あるアドレスの値を読みに行き、その値を変えて書き込みに行く場合、1つのthread が書き込みを終了しないうちに別のthreadが値を読みに行く可能性がある。

Page 3: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

データ競合(例)

• thread2 も 0 の値をロードする

• その結果Mem[x] = 1

2016/6/27 第20回 GPU コンピューティング 講習会 3

thread1: thread2:

Old Mem[x] New Old + 1 Mem[x] New

Old Mem[x] New Old + 1 Mem[x] New

Mem[x] initialized to 0

time

Page 4: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Atomic Operation

• 一つのメモリアドレスに対してただ一つのread-modify-writeの操作を行う

• ハードウェアが、他のthreadのread-modify-writeの操作を排他的にAtomic Operationが終わるまで停止する – 他のthreadのAtomic OperationはQueueに

– 全てのthreadのAtomic Operationは逐次実行される

2016/6/27 第20回 GPU コンピューティング 講習会 4

Page 5: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Atomic Operationによる正しい結果 thread1:

thread2: Old Mem[x] New Old + 1 Mem[x] New

Old Mem[x] New Old + 1 Mem[x] New

thread1:

thread2: Old Mem[x] New Old + 1 Mem[x] New

Old Mem[x] New Old + 1 Mem[x] New

Or

2016/6/27 第20回 GPU コンピューティング 講習会 5

Page 6: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Thrust

Linear Algebra FFT, BLAS,

SPARSE, Matrix

Numerical & Math RAND, Statistics

Data Struct. & AI Sort, Scan, Zero Sum

Visual Processing Image & Video

NVIDIA

cuFFT,

cuBLAS,

cuSPARSE

NVIDIA

Math

Lib

NVIDIA

cuRAND

NVIDIA

NPP

NVIDIA

Video

Encode

GPU AI –

Board

Games

GPU AI –

Path

Finding

2016/6/27 第20回 GPU コンピューティング 講習会 6

Page 7: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Thrust:GPU版のSTL

• Standard Template Library (STL, C++)のCUDA版に相当したライブラリ。

• Header をincludeし、Host 側からAPIをCallする。

• 計算はGPU上で実行されるが、自分でDevice memoryの管理やKernelコード書く必要がない。

• vector, scan, sortなど配列によく使われる関数が提供されている。

2016/6/27 第20回 GPU コンピューティング 講習会 7

Page 8: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Thrustを用いたベクトル加法

// device メモリを確保

thrust::device_vector<float> deviceInput1(inputLength);

thrust::device_vector<float> deviceInput2(inputLength);

thrust::device_vector<float> deviceOutput(inputLength);

// host 上の配列を device メモリへ転送

thrust::copy(hostInput1, hostInput1 + inputLength, deviceInput1.begin());

thrust::copy(hostInput2, hostInput2 + inputLength, deviceInput2.begin());

// device上の配列 deviceInput1 と deviceInput2 に thrust::plus<float>() // の操作を行う、計算結果はdeviceOutputに出力

thrust::transform(deviceInput1.begin(), deviceInput1.end(), deviceInput2.begin(), deviceOutput.begin(),

thrust::plus<float>());

2016/6/27 第20回 GPU コンピューティング 講習会 8

Page 9: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

変数型の Qualifier

__shared__ shared memory 上に確保される。

block単位のthread実行中のみ確保される。

block内のthreadからしかread/write不可

__constant__ constant memory 上に確保される。

プログラムが終了するまで確保される。

全てのthreadからreadでき、CPU側からは APIを通じて write 可。

constant cache が有効、 thread から読み込みが早い。

__device__ global memory の領域に確保される。

プログラムが終了するまで確保される。

全てのthreadからread/writeでき、CPU側からはAPIを通じて read/write 可。

Variable declaration Memory Scope Lifetime

int LocalVar; register thread thread

__device__ __shared__ int SharedVar; shared block block

__device__ int GlobalVar; global grid application

__device__ __constant__ int ConstantVar; constant grid application

2016/6/27 第20回 GPU コンピューティング 講習会 9

Page 10: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Shared メモリの確保

10

KERNEL 関数の中で

静的に確保 __shared__ double fs[1024];

実行時に確保 extern __shared__ double fs[];

<<< Dg, Db, 1024, 0 >>> の第3引数でサイズを指定。

Global Memory

Processing Unit

I/O

ALU

Processor (SM)

Shared Memory

Register File

Control Unit

PC IR

各Streaming Multiprocessor 当たり実際にあるメモリ(ハードウェア、on-chip memory) 非常に高速なアクセスが可能

block 内のthread でデータの交換が可能。

2016/6/27 第20回 GPU コンピューティング 講習会

Page 11: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Reduction

• 配列の中の、最大値、最小値、総和等を求めたり、Sort などを行う操作。

• CPU では容易で、様々なアルゴリズムが開発されている。GPU では data parallel に基づいたthread 並列が必須なため、

Parallel Reduction を行う必要がある。

2016/6/27 第20回 GPU コンピューティング 講習会 11

Page 12: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

配列要素の総和

• Global memory の配列の中の、最大値、最小値、総和等を求める方法は基本的に同じであるため、ここでは総和を求める。

• Reduction は配列要素間の比較を行う必要があるが、thread 間で情報交換を行うには block 内では shared memory を使い、grid 全体では global memory を使う。

• global memory の頻繁なアクセスを行うと、GPU本来の性能が引き出せないので、可能な限り shared memory を利用する。

12 2016/6/27 第20回 GPU コンピューティング 講習会

Page 13: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

総和計算の問題設定

• n (~1024x1024x16(double で約134.2MB))個の要素を持つ配列 A[n] に対して、総和(平均値)を求める。

• 初期に a_h[n] に 0~0.99999999 の疑似乱数を設定し、CPU での総和計算と GPU での総和計算の速度と結果を比較する。

• 初期設定:

srand(12131);

for(i = 0; i < n; i++) a_h[i] = (double) rand()/RAND_MAX;

• GPU の場合は、初期化後に cudaMemcpy で GPU にa_h[n] を転送。

13 2016/6/27 第20回 GPU コンピューティング 講習会

Page 14: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

幾つかの総和計算の例

• CPU での総和計算

double sum = 0.0;

for(i = 0; i < n; i++) sum += a_h[i];

• Atomic operationでの総和計算

• Thrustでの総和計算

2016/6/27 第20回 GPU コンピューティング 講習会 14

Sample Code: AtomicSample/serialSum

Sample Code: thrustReduction

Page 15: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

GPU でのParallel Sum Reduction

2016/6/27 第20回 GPU コンピューティング 講習会 15

Global memory から shared memory へのデータの読み込み

block 分割: n / (BLOCK_SIZE x 2)個のblock 例:BLOCK_SIZE = 256

512要素 512要素 512要素 a_d[i] 256 thread 256 thread 256 thread

kernel 関数の中に、shared memory の確保

__shared__ double fs[BLOCK_SIZE x 2];

各block の総和は global memory に出力

n = n / (BLOCK_SIZE x 2);

(次のイテレーションへ)

b_d[i]

Page 16: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Parallel Sum Reductionの一例

2016/6/27 第20回 GPU コンピューティング 講習会 16

Page 17: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

問題点

• 半分のthreadsしか計算しなく、Warp内にControl Divergence 発生

• 毎ステップ毎にデータアクセスの距離が長くなる

2016/6/27 第20回 GPU コンピューティング 講習会 17

Page 18: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

収集場所の変更

2016/6/27 第20回 GPU コンピューティング 講習会 18

Thread 0

3 1 7 0 6 1 4 3

7 2 13 3

20 5

25

Thread 1 Thread 2 Thread 3

Page 19: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

改善した Kernel

2016/6/27 第20回 GPU コンピューティング 講習会 19

for (unsigned int stride = blockDim.x; stride > 0; stride /= 2)

{

__syncthreads();

if (t < stride)

partialSum[t] += partialSum[t+stride];

}

for (unsigned int stride = 1; stride <= blockDim.x; stride *= 2) { __syncthreads(); if (t % stride == 0) partialSum[2*t]+= partialSum[2*t+stride]; }

Sample Code: Reduction/reduction

各ステップで、そのステップを実行する前に前回のステップでの全てのthreadによる計

算が終わっている事を保証する為 __syncthreads() が必須

Page 20: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

データ転送と計算

• CUDA Kernel は全部のデータがコピーし終わった後に、実行される

2016/6/27 第20回 GPU コンピューティング 講習会 20

Trans. A Trans. B Comp Trans. C

time

Only use one direction, GPU idle

PCIe Idle Only use one direction, GPU idle

Page 21: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

パイプライン化

• データを分割して、データ転送と計算をoverlapする

2016/6/27 第20回 GPU コンピューティング 講習会 21

Trans A.0

Trans B.0

Trans C.0

Trans A.1

Comp C.0 = A.0 + B.0

Trans B.1

Comp C.1 = A.1 + B.1

Trans A.2

Trans B.2

Trans C.1

Comp C.2 = A.2 + B.2

Trans A.3

Trans B.3

Page 22: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

CUDA Stream

2016/6/27 第20回 GPU コンピューティング 講習会 22

Device での thread の実行(タスク)は、ストリーム単位で管理されている。

■ GPU の kernel 関数の実行も 1つの stream ■ cudaMemcpy も1つの stream

Default で全ての stream の番号は 0 に設定されている。

同じ stream 上では、投入順に実行される。

GPU kernel の同時実行が可能になったのは CUDA 3.0 から。

cudaGetDeviceProperties( &prop, Device_No ); prop.deviceOverlap = 1

Utility: deviceQuery

Concurrent kernel execution: Yes

Page 23: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Stream の指定

cudaStream_t stream; cudaStreamCreate( &stream );

cudaStreamDestroy( stream );

cudaMemcpyAsync(void *dst, const void *src, size_t count, enum cudaMemcpyKind kind, cudaStream_t stream); kind: cudaMemcpyHostToDevice cudaMemcpyDeviceToHost

gpu_kernel_fucntion<<< grid, thread, 0, stream>>(a, b, c); grid: block_per_grid, thread: threads_per_block,

2016/6/27 第20回 GPU コンピューティング 講習会 23

Page 24: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Stream スケジューリング(1) ti

me

stream 0

cudaMemcpy 0 {0}

cudaMemcpy 0 {1}

GPU kernel 0 {0}

GPU kernel 0 {1}

GPU kernel 0 {2}

GPU kernel 0 {3}

cudaMemcpy 0 {2}

cudaMemcpy 0 {3}

GPU kernel 0 {1}

nonation

stream number

calling order

2016/6/27 第20回 GPU コンピューティング 講習会 24

Page 25: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Stream スケジューリング(2) ti

me

stream 1

cudaMemcpy 1 {0}

cudaMemcpy 1 {1}

GPU kernel 2 {0}

GPU kernel 2 {1}

GPU kernel 2 {2}

GPU kernel 2 {3}

cudaMemcpy 1 {2}

cudaMemcpy 1 {3}

stream 2

cudaDeviceSynchronize(); {1};

cudaDeviceSynchronize(); {2}

GPU kernel 2 {4}

2016/6/27 第20回 GPU コンピューティング 講習会 25

Page 26: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Stream スケジューリング(3) ti

me

stream 1

cudaMemcpy 1 {0}

cudaMemcpy 1 {1}

GPU kernel 2 {0}

GPU kernel 2 {1}

cudaMemcpy 1 {3}

cudaMemcpy 1 {4}

stream 2

cudaDeviceSynchronize(); {1};

cudaDeviceSynchronize(); {2}

2016/6/27 第20回 GPU コンピューティング 講習会 26

GPU kernel 1 {2}

GPU kernel 2 {2}

Page 27: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Multi-Streamを用いた配列計算

2016/6/27 第20回 GPU コンピューティング 講習会 27

… unsigned int partition_size = n / STREAM_N; for(i = 0; i < STREAM_N; i++) { cudaStreamCreate( &stream[i] ); cudaMalloc( (void**) &a_d[i], partition_size * sizeof(double) ); … } for(i = 0; i < STREAM_N; i++) { cudaMemcpyAsync( a_d[i], a_h + i * partition_size, partition_size * sizeof(double), cudaMemcpyHostToDevice, stream[i] ); … kernel<<< partition_size / BLOCK_SIZE, BLOCK_SIZE, 0, stream[i] >>>( c_d[i], a_d[i] ); … } for(i = 0; i < STREAM_N; i++) { cudaMemcpyAsync( c_h + i * partition_size, c_d[i], partition_size * sizeof(double), cudaMemcpyDeviceToHost, stream[i] ); }

Sample Code: MultiStream/VectorAddMS

Page 28: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

1 Stream の結果

2016/6/27 第20回 GPU コンピューティング 講習会 28

Page 29: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

4 Streams の結果(overlap)

2016/6/27 第20回 GPU コンピューティング 講習会 29

Overlapped with input Overlapped with output

Page 30: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Concurrent Stream 並列

2016/6/27 第20回 GPU コンピューティング 講習会 30

Sample Code: MultiStream/Concurrent

Page 31: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Unified Memory

CPU GPU

Host

Memory

Device

Memory

CPU GPU

Unified

Memory

独立メモリスペース 仮想共有メモリスペース

Page 32: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Unified Memoryの利点

• 手動で H2D, D2H コピーは必要なくなる

• ポインターの数は減る、管理が容易に

• コードの行数も減る

• CPU/GPU両方の関数もアクセス出来るのでデバッグは簡単になる

• 複雑なデータ構造の実装も簡単になる (例:動的多次元配列)

Page 33: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Example Code

Host code with device memory

int main()

{

unsigned int size = n*sizeof(double);

a_h = (double **) malloc(size);

b_h = (double **) malloc(size);

cudaMalloc( (void**) &a_d, size );

cudaMalloc( (void**) &b_d, size);

cudaMemcpy( a_d, a_h, size, cudaMemcpyHostToDevice );

}

Host code with unified memory int main()

{

unsigned int size = n*sizeof(double);

cudaMallocManaged( (void**) &a_h[s], size );

cudaMallocManaged( (void**) &b_h[s], size );

}

2016/6/27 第20回 GPU コンピューティング 講習会 33

Page 34: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

GPUの上に動的二次元配列(1)

CPU a_h = (double **) malloc(sizeof(double *)*ny);

for(j = 0; j < ny; j++)

{

a_h[j] = (double *) malloc(sizeof(double)*nx);

}

GPU cudaMalloc( (void**) &a_d, sizeof(double *)*ny );

for(j = 0; j < ny; j++)

{

cudaMalloc( (void**) &a_d[j], sizeof(double)*nx );

}

OK Segmentation fault

2016/6/27 第20回 GPU コンピューティング 講習会 34

Page 35: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

GPUの上に動的二次元配列(2)

cudaMalloc( (void**) &a_d, sizeof(double *)*ny );

for(j = 0; j < ny; j++)

{

cudaMalloc( (void**) &a_d[j], sizeof(double)*nx );

}

cudaMalloc() は Host memory をアクセスするが a_d[j]は device memory にいる

Sample Code: UnifiedMemory/MatrixAddDynamicError01

2016/6/27 第20回 GPU コンピューティング 講習会 35

a_d

a_d[j]

Host memory

Device memory

Page 36: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

GPUの上に動的二次元配列(3)

a_d = (double **) malloc(sizeof(double *)*ny);

for(j = 0; j < ny; j++)

{

cudaMalloc( (void**) &a_d[j], sizeof(double)*nx );

}

….

Kernel<<<........>>>( a_d ... );

Kernel Error a_d[j]はHost memoryにいる Kernel内ではアクセス出来ない

2016/6/27 第20回 GPU コンピューティング 講習会 36

a_d

a_d[j]

Host memory

Device memory

Sample Code: UnifiedMemory/MatrixAddDynamicError02

Page 37: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

GPUの上に動的二次元配列(4)

a_d = (double **) malloc(sizeof(double *)*ny);

for(j = 0; j < ny; j++)

{

cudaMalloc( (void**) &a_d[j], sizeof(double)*nx );

}

….

cudaMalloc( (void**) &a_dd, sizeof(double *)*ny );

cudaMemcpy( a_dd, a_d, sizeof(double *)*ny, cudaMemcpyHostToDevice );

Kernel<<<........>>>( a_dd ... );

a_d[j] を通してメモリ確保した後 a_d[j] (データ=アドレス)を (device memory上)a_dd[j] にコピーする

2016/6/27 第20回 GPU コンピューティング 講習会 37

a_d

a_d[j]

Host memory

Device memory

a_dd[j]

a_dd

Sample Code: UnifiedMemory/MatrixAddDynamic

Page 38: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

GPUの上に動的二次元配列(5)

Unified Memoryを使えば

cudaMallocManaged( (void**) &a_h, sizeof(double *)*ny ); for(j = 0; j < ny; j++) { cudaMallocManaged( (void**) &a_h[j], sizeof(double)*nx ); } ... Kernel<<<........>>>( a_h ... );

2016/6/27 第20回 GPU コンピューティング 講習会 38

a_h = (double **) malloc(sizeof(double *)*ny); for(j = 0; j < ny; j++) { a_h[j] = (double *) malloc(sizeof(double)*nx); }

Sample Code: UnifiedMemory/MatrixAddDynamicUM

Page 39: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Unified MemoryとStream

• Unified MemoryはバッググラウンドでCPU/GPU間にデータ転送を行う

• Streamは非同期でデータアクセスする

• Crash(Segmentation fault)の可能性がある

–ある時点で、あるポインター(メモリ)をアクセス出来るStreamの指定が必要(Data Visibility)

– cudaDeviceSynchronize()を使う

2016/6/27 第20回 GPU コンピューティング 講習会 39

Page 40: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Data Visibility の指定

cudaStreamAttachMemAsync( cudaStream_t stream, void *ptr, size_t length, unsigned int flags)

stream: CUDA stream

ptr: メモリ・アドレス

length: 領域のサイズ

flags: Data Visibility のタイプを指定する定数

cudaMemAttachGlobal

cudaMemAttachSingle

cudaMemAttachHost

2016/6/27 第20回 GPU コンピューティング 講習会 40

Page 41: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

• cudaMemAttachGlobal(default) – すべてのGPU Stream 、CPUもアクセス可能 – GPU が何かを実行する時、このメモリ(使用中ではなくでも)はアクセス出来なくなり、Concurrent streamでアクセスすると Segmentation fault の可能性がある

• cudaMemAttachSingle(Stream) – 指定したGPU streamだけがアクセス可能 – Concurrent streamはこれを使う

• cudaMemAttachHost – CPUだけがアクセス可能 – GPUの計算が影響しなくなる

Data Visibility のタイプ(flags)

Page 42: CUDA基礎 - sim.gsic.titech.ac.jp · cuda基礎2 東京工業大学 学術国際情報センター 黄 遠雄 2016/6/27 第20回 gpu コンピューティング 講習会 1

Concurrent Stream 並列 (Unified Memory + CPU)

2016/6/27 第20回 GPU コンピューティング 講習会 42

Sample Code: UnifiedMemory/VectorAddUMMS

Overlapped with Data copy Overlapped GPU and CPU calculations