OpenCLメモ (その5) - 転送(コピー)の排除 (SVM : OpenCL 2.0)

前回は、OpenCL 1.2の範囲でUSE_HOST_PTRやALLOC_HOST_PTRを使ってホスト-デバイス間のコピーをなくす方法を確認した。今回は、OpenCL 2.0のSVM (Shared Virtual Memory)を使った方法を確認する。

参考資料
Intel Developer Zone - OpenCL™ 2.0 Shared Virtual Memory Overview

まず、選択したデバイスがSVM(Shared Virtual Memory)をサポートしているか確認する必要がある。こんな感じで調べられる。

cl_device_svm_capabilities caps;
err = clGetDeviceInfo(ocl->device, CL_DEVICE_SVM_CAPABILITIES,
sizeof(cl_device_svm_capabilities), &caps, NULL);
if (CL_SUCCESS != err) {
return err;
}
ocl->svmCoarse = 0!=(caps & CL_DEVICE_SVM_COARSE_GRAIN_BUFFER);
ocl->svmFineBuffer = 0!=(caps & CL_DEVICE_SVM_FINE_GRAIN_BUFFER);
ocl->svmFineSystem = 0!=(caps & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM);


SVMには3種類あって、順番により強力になる。

・SVM Coarse Grain Buffer
clSVMAllocという専用の関数を使って確保する。ホストから触るときには、USE_HOST_PTRなどの時と同様にMap / Unmapによる同期が必要なSVM。

・SVM Fine Grain Buffer
clSVMAllocという専用の関数を使って確保する。ホストから触るときでも、Map / Unmap不要(常に同期がとられる)。

・SVM Fine Grain System
普通のホスト(CPU)メモリのポインタをデバイス(GPU)と共有できる。

現時点でIntel HD Graphics 530 (i7 6700K)がサポートするのはFine Grain Bufferまでとなっている。



SVM Coarse Grain Buffer



まず、_aligned_mallocの代わりにclSVMAllocでメモリを確保する。

cl_uint nSize = sizeof(cl_int) * arrayWidth * arrayHeight;
cl_int* inputA = (cl_int*)clSVMAlloc(
ocl.context, //関連付けるcontext
CL_MEM_READ_ONLY, //kernelからの使用方法
nSize, //確保するサイズ
0); //アライメント(0 = 自動)

cl_int* inputB = (cl_int*)clSVMAlloc(
ocl.context, CL_MEM_READ_ONLY, nSize, 0);
cl_int* outputC = (cl_int*)clSVMAlloc(
ocl.context, CL_MEM_READ_ONLY, nSize, 0);


これだけで、_aligned_mallocとclCreateBufferが同時にできたような感じ。

clSVMAllocしたメモリはclSVMFreeで解放すればよい。


clSVMFree(ocl.context, inputA);
clSVMFree(ocl.context, inputB);
clSVMFree(ocl.context, outputC);


ホスト(CPU)側からこの領域を操作するには、USE_HOST_PTRの時同様、Map / Unampが必要になる。clEnqueueSVMMap() / clEnqueueSVMUnmap()を使う。


//対応するホスト側のポインタを取得する
err = clEnqueueSVMMap(
ocl.commandQueue, //投入キュー
CL_FALSE, //終了までブロックするか -> しない
CL_MAP_WRITE, //CPUが書き込むためにMapする
//(読み込みならCL_MAP_READ)
//(両方ならCL_MAP_READ | CL_MAP_WRITE)
inputA, //マップするポインタ
sizeof(cl_uint) * arrayWidth * arrayHeight, //マップするサイズ
0, //この関数が待機すべきeventの数
NULL, //この関数が待機すべき関数のリストへのポインタ
NULL); //この関数の返すevent

//終了を待機
err = clFinish(ocl.commandQueue);

//ホスト(CPU)から操作
//(...略...)

err = clEnqueueSVMUnmap(
ocl.commandQueue, //投入キュー
inputA, //対象のポインタ
0, //この関数が待機すべきeventの数
NULL, //この関数が待機すべき関数のリストへのポインタ
NULL); //この関数の返すevent

//終了を待機
err = clFinish(ocl.commandQueue);

//デバイス(GPU) kernelを実行
//(...略...)


このSVMのポインタをkernelに渡す場合、clSetKernelArgSVMPointer()という専用関数を使う必要がある。


err = clSetKernelArgSVMPointer(ocl->kernel, 0, inputA);
err = clSetKernelArgSVMPointer(ocl->kernel, 1, inputB);
err = clSetKernelArgSVMPointer(ocl->kernel, 2, outputC);


この後の流れは同じ。

確認すると、きちんと転送がなくなっていることがわかる。



"Add"kernelの実行時間は1.741ms。



ちゃんと動くコードはこちら



SVM Fine Grain Buffer



clSVMAllocで指定するflagにCL_MEM_SVM_FINE_GRAIN_BUFFERをつけるだけで使用できる。


cl_uint nSize = sizeof(cl_int) * arrayWidth * arrayHeight;
cl_int* inputA = (cl_int*)clSVMAlloc(
ocl.context, //関連付けるcontext
CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER,
nSize, //確保するサイズ
0); //アライメント(0 = 自動)

cl_int* inputB = (cl_int*)clSVMAlloc(
ocl.context, CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, nSize, 0);
cl_int* outputC = (cl_int*)clSVMAlloc(
ocl.context, CL_MEM_READ_ONLY | CL_MEM_SVM_FINE_GRAIN_BUFFER, nSize, 0);


転送は全く発生せず計算できている。



"Add"kernelの実行時間は2.067msとCoarse Grain Bufferの時と比べて増加してしまっている。CPUと常に同期をとる分、ややkernelの実行が遅くなるようだ。

ちゃんと動くコードはこちら



SVM Fine Grain System



clSVMAllocしたポインタだけでなく、どんなCPUのポインタも共有できるという、最強のSVM。

だが、Skylakeではまだ使用できないのだった…。



続き>>



OpenCLメモリスト
OpenCLメモ (その1) - かんたんな計算
OpenCLメモ (その2) - Intel GPUの構造
OpenCLメモ (その3) - work sizeの調整
OpenCLメモ (その4) - 転送(コピー)の排除 (USE_HOST_PTR)
OpenCLメモ (その5) - 転送(コピー)の排除 (SVM : OpenCL 2.0) (いまここ)
OpenCLメモ (その6) - imageの使用
OpenCLメモ (その7) [終] - reductionとshared local memory(SLM)の使用


スポンサーサイト

コメントの投稿

非公開コメント

プロフィール

rigaya

Author:rigaya
アニメとか見たり、エンコードしたり。
連絡先(@を半角にしてください!)
rigaya34589@live.jp
github

最新記事
最新コメント
カテゴリ
月別アーカイブ
カウンター
検索フォーム
いろいろ
公開中のAviutlプラグインとかのダウンロード

○Aviutlプラグイン
x264guiEx 2.xx (ミラー)
- x264を使用したH264出力
- x264guiExの導入>
- x264.exeはこちら>

x265guiEx (ミラー)
- x265を使用したH.265/HEVC出力
- x265.exeはこちら>

QSVEnc + QSVEncC (ミラー)
- QuickSyncVideoによるH264出力
- QSVEncCはコマンドライン版
- QSVEncC 導入/使用方法>
- QSVEncCオプション一覧>

NVEnc + NVEncC (ミラー)
- NVIDIAのNVEncによるH264出力
- NVEncCオプション一覧>

VCEEnc + VCEEncC (ミラー)
- AMDのVCEによるH.264出力

ffmpegOut (ミラー)
- ffmpeg/avconvを使用した出力

自動フィールドシフト (ミラー)
- SSE2~AVX2による高速化版
- オリジナル: aji様

エッジレベル調整MT (ミラー)
- エッジレベル調整の並列化/高速化
- SSE2~AVX対応
- オリジナル: まじぽか太郎様

バンディング低減MT (ミラー)
- SSE2~AVX2による高速化版
- オリジナル: まじぽか太郎様

PMD_MT (ミラー)
- SSE2~FMA3による高速化版
- オリジナル: スレ48≫989氏

透過性ロゴ (ミラー)
- SSE2~FMA3によるSIMD版
- オリジナル: MakKi氏

AviutlColor (ミラー)
- BT.2020nc向け色変換プラグイン
- BT.709/BT.601向けも同梱

○その他
x264afs (ミラー)
- x264のafs対応版

aui_indexer (ミラー使い方>)
- lsmashinput.aui/m2v.auiの
 インデックス事前・一括生成

auc_export (ミラー使い方>)
- Aviutl Controlの
 エクスポートプラグイン版
 エクスポートをコマンドから

aup_reseter (ミラー)
- aupプロジェクトファイルの
 終了フラグを一括リセット

CheckBitrate (ミラー, 使い方, ソース)
- ビットレート分布の分析(HEVC対応)

チャプター変換 (ミラー使い方>)
- nero/appleチャプター形式変換

エッジレベル調整 (avisynth)
- Avisynth用エッジレベル調整

メモリ・キャッシュ速度測定
- スレッド数を変えて測定

○ビルドしたものとか
L-SMASH (ミラー)
x264 (ミラー)
x265 (ミラー)

○その他
サンプル動画
その他

○読みもの (ミラー)
Aviutl/x264guiExの色変換
動画関連ダウンロードリンク集
簡易インストーラの概要

○更新停止・公開終了
改造版x264gui
x264guiEx 0.xx
RSSリンクの表示
リンク
QRコード
QR