CUDAで行列演算:加減算
をテンプレートにして作成
[
トップ
|
新規
|
一覧
|
検索
|
最終更新
|
ヘルプ
]
開始行:
*CUDAで行列演算 その1 加減算 [#z5d8526e]
CUDAでのプログラミングの基礎を学ぶために,数値解析などで...
+ホスト側メモリ確保,入力データ準備
+デバイス側メモリ確保
+ホストからデバイスへデータ転送
+CUDAカーネル呼び出し
+結果をデバイスからホストへ転送
+メモリ解放
**ホスト側メモリ確保 [#o1d84552]
行列を1次元配列上に格納する.演算対象の行列をAとB,結果を...
| A0 A1 A2 A3 |
| A4 A5 A6 A7 |
| A8 A9 A10 A11 |
の順に格納される.ここで,Nrow = 3, Ncol = 4とした.
このとき,i行j列の要素はA[i*Ncol+j]で取得できる.
ホストメモリを格納する変数名はhA,hBのようにhを接頭子とす...
ホストメモリは次のようにして確保できる.
#code(C){{
unsigned int size_byte = sizeof(float)*nrow*ncol;
float *hA = (float*)malloc(size_byte);
float *hB = (float*)malloc(size_byte);
float *hC = (float*)malloc(size_byte);
}}
メモリの確保はCPU上で行われるので,C/C++言語の他の手法で...
また,CPU側で処理される関数上でSTLのvector等を使って確保...
#code(C,nooutline,nomenu){{
vector<float> A;
A.resize(size);
CuTest(&A[0]);
}}
CuTestはCudaのホスト側関数である.
デバイスメモリに転送する前に,
上記の行列の要素アクセスを使って配列に行列の入力値を代入...
ここでは実験的にチェックしたいので,乱数を用いて
#code(C){{
void RandomInit(float* data, int size, float max)
{
for(int i = 0; i < size; ++i){
data[i] = max*(rand()/(float)RAND_MAX);
}
}
}}
のような関数で初期化を行う.
**デバイス側メモリ確保 [#m776bcca]
CUDAのプログラミングモデルでは,ホストとデバイスがそれぞ...
(ホストメモリとデバイスメモリ)を持つことを仮定しています.
CUDAカーネルはデバイスメモリの中だけ操作することが可能で...
カーネルに渡すデータはデバイスメモリに確保されている必要...
デバイスメモリは,linear memory か CUDA arrays のどちらか...
よく使われるのはlinear memoryだと思われる.
CUDA arraysは内部のデータレイアウトが不透明であり,テクス...
ここでは,linear memoryを使用する.
メモリ確保命令は cudaMalloc である.
#code(C){{
// デバイスメモリの確保
float *dA, *dB, *dC;
cutilSafeCall(cudaMalloc((void**)&dA, size));
cutilSafeCall(cudaMalloc((void**)&dB, size));
cutilSafeCall(cudaMalloc((void**)&dC, size));
}}
cutilSafeCallはSDKが提供するデバッグ用の関数ラッパである.
**ホストからデバイスへデータ転送 [#m7009637]
デバイスメモリを確保したら,ホストメモリからデバイスメモ...
#code(C){{
// ホストからデバイスへの転送
cutilSafeCall(cudaMemcpy(dA, hA, size, cudaMemcpyHostToD...
cutilSafeCall(cudaMemcpy(dB, hB, size, cudaMemcpyHostToD...
}}
cudaMemcpyは第一引数に転送先,第二引数に転送元,第三引数...
cudaMemcpyDeviceToHostでデバイスからホストへのコピーであ...
**CUDAカーネル呼び出し [#l7a8f65a]
CUDAカーネルの呼び出しには,<<< ... >>> を用いる.
カーネル関数名をmatrixAddとすると,
#code(C){{
dim3 block(BLOCK_SIZE, BLOCK_SIZE);
dim3 grid((nrow+block.x-1)/block.x, (ncol+block.y-1)/blo...
matrixAdd<<< grid, block >>>(dC, dA, dB, nrow, ncol);
}}
のようにして呼び出す.
ここで,BLOCK_SIZE=16とした.
"<<< >>>" の中にはグリッド内のブロック数(grid,2Dまで),ブ...
ブロック内のスレッド数を固定としているので,ブロック数をn...
dim3はCUDAのベクトル型変数でグリッドやブロックのサイズを...
[[CUDAのベクトル型]]にまとめる.
呼び出される側のカーネル関数は,
#code(C){{
__global__
void matrixAdd(float* C, float* A, float* B, int nrow, in...
{
int row = blockIdx.y*blockDim.y+threadIdx.y;
int col = blockIdx.x*blockDim.x+threadIdx.x;
int idx = row*ncol+col;
if(row < nrow && col < ncol){
C[idx] = A[idx]+B[idx];
}
}
}}
のように定義する.
__global__修飾子については[[CUDA関数修飾子]]を参照.
また,blockIdxやblockDim,threadIdxは[[CUDAビルトイン変数...
SDKでカーネル実行エラーをチェックするには,カーネル呼び出...
cutilCheckMsg("Kernel execution failed");
を呼び出す.
**結果をデバイスからホストへ転送 [#ga6e2975]
演算結果をデバイスからホストへ転送する.
#code(C){{
// デバイスからホストへ結果を転送
cutilSafeCall(cudaMemcpy(hC, dC, size, cudaMemcpyDeviceT...
}}
**メモリ解放 [#bf7a7561]
すべて終了したらホストメモリ,デバイスメモリを解放する.
#code(C){{
// ホストメモリ解放
free(hA);
free(hB);
free(hC);
// デバイスメモリ解放
cutilSafeCall(cudaFree(dA));
cutilSafeCall(cudaFree(dB));
cutilSafeCall(cudaFree(dC));
}}
デバイスメモリの解放にはcudaFreeを用いる.
終了行:
*CUDAで行列演算 その1 加減算 [#z5d8526e]
CUDAでのプログラミングの基礎を学ぶために,数値解析などで...
+ホスト側メモリ確保,入力データ準備
+デバイス側メモリ確保
+ホストからデバイスへデータ転送
+CUDAカーネル呼び出し
+結果をデバイスからホストへ転送
+メモリ解放
**ホスト側メモリ確保 [#o1d84552]
行列を1次元配列上に格納する.演算対象の行列をAとB,結果を...
| A0 A1 A2 A3 |
| A4 A5 A6 A7 |
| A8 A9 A10 A11 |
の順に格納される.ここで,Nrow = 3, Ncol = 4とした.
このとき,i行j列の要素はA[i*Ncol+j]で取得できる.
ホストメモリを格納する変数名はhA,hBのようにhを接頭子とす...
ホストメモリは次のようにして確保できる.
#code(C){{
unsigned int size_byte = sizeof(float)*nrow*ncol;
float *hA = (float*)malloc(size_byte);
float *hB = (float*)malloc(size_byte);
float *hC = (float*)malloc(size_byte);
}}
メモリの確保はCPU上で行われるので,C/C++言語の他の手法で...
また,CPU側で処理される関数上でSTLのvector等を使って確保...
#code(C,nooutline,nomenu){{
vector<float> A;
A.resize(size);
CuTest(&A[0]);
}}
CuTestはCudaのホスト側関数である.
デバイスメモリに転送する前に,
上記の行列の要素アクセスを使って配列に行列の入力値を代入...
ここでは実験的にチェックしたいので,乱数を用いて
#code(C){{
void RandomInit(float* data, int size, float max)
{
for(int i = 0; i < size; ++i){
data[i] = max*(rand()/(float)RAND_MAX);
}
}
}}
のような関数で初期化を行う.
**デバイス側メモリ確保 [#m776bcca]
CUDAのプログラミングモデルでは,ホストとデバイスがそれぞ...
(ホストメモリとデバイスメモリ)を持つことを仮定しています.
CUDAカーネルはデバイスメモリの中だけ操作することが可能で...
カーネルに渡すデータはデバイスメモリに確保されている必要...
デバイスメモリは,linear memory か CUDA arrays のどちらか...
よく使われるのはlinear memoryだと思われる.
CUDA arraysは内部のデータレイアウトが不透明であり,テクス...
ここでは,linear memoryを使用する.
メモリ確保命令は cudaMalloc である.
#code(C){{
// デバイスメモリの確保
float *dA, *dB, *dC;
cutilSafeCall(cudaMalloc((void**)&dA, size));
cutilSafeCall(cudaMalloc((void**)&dB, size));
cutilSafeCall(cudaMalloc((void**)&dC, size));
}}
cutilSafeCallはSDKが提供するデバッグ用の関数ラッパである.
**ホストからデバイスへデータ転送 [#m7009637]
デバイスメモリを確保したら,ホストメモリからデバイスメモ...
#code(C){{
// ホストからデバイスへの転送
cutilSafeCall(cudaMemcpy(dA, hA, size, cudaMemcpyHostToD...
cutilSafeCall(cudaMemcpy(dB, hB, size, cudaMemcpyHostToD...
}}
cudaMemcpyは第一引数に転送先,第二引数に転送元,第三引数...
cudaMemcpyDeviceToHostでデバイスからホストへのコピーであ...
**CUDAカーネル呼び出し [#l7a8f65a]
CUDAカーネルの呼び出しには,<<< ... >>> を用いる.
カーネル関数名をmatrixAddとすると,
#code(C){{
dim3 block(BLOCK_SIZE, BLOCK_SIZE);
dim3 grid((nrow+block.x-1)/block.x, (ncol+block.y-1)/blo...
matrixAdd<<< grid, block >>>(dC, dA, dB, nrow, ncol);
}}
のようにして呼び出す.
ここで,BLOCK_SIZE=16とした.
"<<< >>>" の中にはグリッド内のブロック数(grid,2Dまで),ブ...
ブロック内のスレッド数を固定としているので,ブロック数をn...
dim3はCUDAのベクトル型変数でグリッドやブロックのサイズを...
[[CUDAのベクトル型]]にまとめる.
呼び出される側のカーネル関数は,
#code(C){{
__global__
void matrixAdd(float* C, float* A, float* B, int nrow, in...
{
int row = blockIdx.y*blockDim.y+threadIdx.y;
int col = blockIdx.x*blockDim.x+threadIdx.x;
int idx = row*ncol+col;
if(row < nrow && col < ncol){
C[idx] = A[idx]+B[idx];
}
}
}}
のように定義する.
__global__修飾子については[[CUDA関数修飾子]]を参照.
また,blockIdxやblockDim,threadIdxは[[CUDAビルトイン変数...
SDKでカーネル実行エラーをチェックするには,カーネル呼び出...
cutilCheckMsg("Kernel execution failed");
を呼び出す.
**結果をデバイスからホストへ転送 [#ga6e2975]
演算結果をデバイスからホストへ転送する.
#code(C){{
// デバイスからホストへ結果を転送
cutilSafeCall(cudaMemcpy(hC, dC, size, cudaMemcpyDeviceT...
}}
**メモリ解放 [#bf7a7561]
すべて終了したらホストメモリ,デバイスメモリを解放する.
#code(C){{
// ホストメモリ解放
free(hA);
free(hB);
free(hC);
// デバイスメモリ解放
cutilSafeCall(cudaFree(dA));
cutilSafeCall(cudaFree(dB));
cutilSafeCall(cudaFree(dC));
}}
デバイスメモリの解放にはcudaFreeを用いる.
ページ名: