• 検索結果がありません。

CUDA を用いた画像処理 画像処理を CUDA で並列化 基本的な並列化の考え方 目標 : 妥当な Naïve コードが書ける 最適化の初歩がわかる ブロックサイズ メモリアクセスパターン

N/A
N/A
Protected

Academic year: 2021

シェア "CUDA を用いた画像処理 画像処理を CUDA で並列化 基本的な並列化の考え方 目標 : 妥当な Naïve コードが書ける 最適化の初歩がわかる ブロックサイズ メモリアクセスパターン"

Copied!
23
0
0

読み込み中.... (全文を見る)

全文

(1)

CUDA画像処理入門

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

GTC Japan 2014

(2)

CUDAを用いた画像処理

 画像処理をCUDAで並列化

— 基本的な並列化の考え方 — 目標 : 妥当なNaïveコードが書ける

 最適化の初歩がわかる

— ブロックサイズ — メモリアクセスパターン

(3)

RGB → Y(輝度) 変換

 カラー画像から、グレイスケールへの変換

(4)

CUDAにおける画像処理の基礎

 2次元メモリ確保API

— Pitchを考慮 — cudaMallocPitch()、cudaMemcpy2D()

 並列化

— CUDAの並列度 : 数万以上欲しい…

(5)

PITCHを考慮したメモリレイアウト

 RGBA(8 bit, uchar4)の配列

 index = x + y * pitchInPixel

width

pitchInPixel = pitchInByte / sizeof(uchar4)

(6)

2次元メモリ 確保・転送

 cudaError_t

cudaMallocPitch

( void** devPtr, size_t* pitch,

size_t width, size_t height )

— widthバイトのメモリを、height行分、取得する。 — 行は、pitchバイトで整列する。

 cudaError_t

cudaMemcpy2D

( void* dst, size_t dpitch,

const void* src, size_t spitch, size_t width, size_t height,

cudaMemcpyKind kind )

— dstで示されるメモリ (dpitchバイトで整列)に、srcで示されるメモリ (spitchバイトで整列) を、width (バイト) x height (行)、コピーする。

(7)

サンプルコード

uchar4 *src, *dImage;

size_t spitch, dPitch, dPitchInPixel; // ピッチつきで、メモリをアロケート

cudaMallocPitch(&dImage, *dPitch, width * sizeof(uchar4), height); dPitchInPixel = dPitch / sizeof(uchar4);

// ピッチを変換しつつ、ホスト→デバイスへと、メモリ転送

cudaMemcpy2D(dImage, dPitch, src, sPitch, width * sizeof(uchar4), height, cudaMemcpyHostToDevice);

(8)

画像処理における並列化の基本

 基本 : 1 ピクセルに対して、 1スレッドを対応させる

— ピクセル数分、スレッドが走る。 例 : 262,144 (= 512 x 512) スレッド

 スレッドは、処理対象のピクセルを持つ。

— 自分の位置 (x, y) を知ることが必要

(9)

2DでのBLOCK・THREADの割り当て

 Thread : 「2次元」でピクセルに対応。

 Block

: 「2次元」で定義。一定のサイズのタイル。

 Grid

: 必要数のBlockを「2次元」に敷き詰める。

1 Block

1 Pixel = 1 Thread

(x, y) =

(Global ID X, Global ID Y)

(10)

2DでのBLOCK・THREADの割り当て

 GlobalID は、(x, y

, z

)方向に計算できる

— GlobalID(x) = blockDim.x * blockIdx.x + threadIdx.x — GlobalID(y) = blockDim.y * blockIdx.y + threadIdx.y — GlobalID(z) = blockDim.z * blockIdx.z + threadIdx.z blockDim.x * blockIdx.x

threadIdx.x

blockDim.y * blockIdx.y threadIdx.y

(11)

RGB → Y 変換 カーネル

__global__

void RGBToYKernel(uchar4 *dDst, const uchar4 *dSrc, int width, int height, int pitch){ int gidx = blockDim.x * blockIdx.x + threadIdx.x;

int gidy = blockDim.y * blockIdx.y + threadIdx.y;

if ((gidx < width) && (gidy < height)) { int pos = gidx + gidy * pitch;

// Y = 0.299 R + 0.587 G + 0.114 B uchar4 value = src[pos];

float Y = 0.299f * value.x + 0.587f * value.y + 0.114f * value.z; unsigned char y = (unsigned char)min(255, (int)Y);

dDst[pos ] = pixel; }

(12)

カーネル呼び出し (GRIDサイズ指定)

/* value、radixで割って、切り上げる */ int divRoundUp(int value, int radix) {

return (value + radix – 1) / radix; }

/* gridDim, blockDimを、2次元(x, y方向)に初期化 */ dim3 blockDim(64, 2);

/* divRoundUp()は、切り上げの割り算 */

dim3 gridDim(divRoundUp(width, blockDim.x), divRoundUp(height, blockDim.y)); RGBToYKernel<<<gridDim, blockDim>>>(dDst, dSrc, …);

(13)

悪い並列化の例

 GPUの並列化としては、NG。非常に低速。

— 並列度が低い — メモリアクセスパターンが悪い  ただし… CPU的発想としてはふつう。 Thread 0 Thread 1 Thread 2 Thread 3 …

(14)

ここはポイント!コアレス(COALESCED)アクセス

 連続するスレッドが、連続するメモリにアクセスする。

— threadIdx.xに対して、連続。 Memory : 0 1 2 3 4 5 6 7 8 … threadIdx.x … Thread :

(15)

再掲 : 2DでのBLOCK・THREADの割り当て

 GlobalID は、(x, y

, z

)方向に計算できる

— GlobalID(x) = blockDim.x * blockIdx.x + threadIdx.x — GlobalID(y) = blockDim.y * blockIdx.y + threadIdx.y — GlobalID(z) = blockDim.z * blockIdx.z + threadIdx.z blockDim.x * blockIdx.x

threadIdx.x

blockDim.y * blockIdx.y threadIdx.y

(16)
(17)

FAQ : BLOCKDIMの決め方

1. Occupancy (占有率) を 100 %にする

2. Blockあたりのスレッド数は、なるべく小さく。

(18)

BLOCKDIMの決め方 (OCCUPANCY から)

 SMXあたり、2048 Thread走らせたい。

— Occupancy (占有率) = 100 %

 Occupancy = 100 % を満たす、Blockあたりのスレッド数は、

2048 Thread / 16 Block = 128 Thread / Block 2048 Thread / 8 Block = 256 Thread / Block 2048 Thread / 4 Block = 512 Thread / Block 2048 Thread / 2 Block = 1024 Thread / Block

項目

最大のBlock数 / SMX 16 最大のThread数 / SMX 2048 最大のThread数 / Block 1024

(19)

BLOCKDIMの決め方(BLOCKの粒度から)

 Grid = 4096 Thread の実行例を考えてみる

— Block : 256 Thread、1024 Threadで比較

— 3 SMX / GPU、1 SMXあたり 1 Blockが実行可能とする 1024 Thread / Block Block Block Block Block SMX 0 SMX 1 SMX 2 256 Thread / Block SMX 0 Block Block Block Block Block Block Block Block Block Block Block Block Block Block Block SMX 1 SMX 2 Block t t

(20)

BLOCKDIMの決め方 (SMXの構造から)

 Warp Scheduler x 4 :

— 1 clockあたり、4 Warpに対する命令発行

— Blockのサイズは、 128 Thread の倍数が望ましい。 (128 Thread = 32 Thread/Warp x 4 Warp)

(21)

タイルは横長がよい

 タイルの横幅は、32(Warpの幅)の倍数がよい。

 32より小さい場合、16、もしくは、8 を使う。

Memory : threadIdx.x 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 Thread :

(22)

RGB→Y変換時のバンド幅 : TESLA K20C

blockDim.x 1 2 4 8 16 32 64 128 256 512 1024 blockD im .y 1 1.4 2.8 5.6 11.2 22.1 43.9 78.5 119.8 119.3 115.4 87.7 2 2.6 5.2 10.4 20.6 40.7 77.9 119.8 119.4 115.3 87.4 -4 4.8 9.6 19.2 37.8 74.0 119.4 118.2 114.2 87.3 - -8 8.4 16.7 33.3 69.6 115.0 117.9 111.9 87.1 - - -16 13.4 26.3 60.6 106.7 115.0 114.3 87.2 - - - -32 17.7 40.4 81.1 103.9 110.9 86.9 - - - - -64 20.7 41.7 79.8 99.0 83.5 - - - -128 20.7 41.6 75.6 75.3 - - - -256 20.7 41.0 60.3 - - - -512 20.5 37.6 - - - -1024 19.1 - - - -値: バンド幅 (GB/sec) Tesla K20c (ECC off) Occupancy < 100 %

(23)

まとめ

 画像処理におけるCUDA

— Pitchを考慮したメモリレイアウト — 2次元のGridの呼び出し

 正しいNaïveコード (カーネル) の書き方

— コアレスアクセス — ピクセルごとに、スレッドを割り当てる  並列度は、数万以上。 — Blockサイズは、128が適当 (単純なカーネルの場合)

参照

関連したドキュメント

婚・子育て世代が将来にわたる展望を描ける 環境をつくる」、「多様化する子育て家庭の

The goods and/or their replicas, the technology and/or software found in this catalog are subject to complementary export regulations by Foreign Exchange and Foreign Trade Law

本節では本研究で実際にスレッドのトレースを行うた めに用いた Linux ftrace 及び ftrace を利用する Android Systrace について説明する.. 2.1

Instagram 等 Flickr 以外にも多くの画像共有サイトがあるにも 関わらず, Flickr を利用する研究が多いことには, 大きく分けて 2

Fig.5 The number of pulses of time series for 77 hours in each season in summer, spring and winter finally obtained by using the present image analysis... Fig.6 The number of pulses

備考 1.「処方」欄には、薬名、分量、用法及び用量を記載すること。

あれば、その逸脱に対しては N400 が惹起され、 ELAN や P600 は惹起しないと 考えられる。もし、シカの認可処理に統語的処理と意味的処理の両方が関わっ

・本計画は都市計画に関する基本的な方 針を定めるもので、各事業の具体的な