現在地 >> メニュー >> OpenCL >> OpenCL編02
INDEX:OpenCL編01 <<OpenCL編02 >> OpenCL編03?
次:OpenCL編02_2OpenCL編02_3

はじめに

OpenCLでは
  • 「○○.cpp」(CPU側)
  • 「○○.cl」(GPU側)
の2つのソースコードをつくる。

イメージとしては、
CPU側で「.clファイル」を読み込んでコンパイルして実行する
ような感じ。(※GLSLやCgのようなシェーダ的な感じ)

OpenCLのプログラミング手順


OpenCLのプログラミング手順は次の通り
  1. プラットフォームID
  2. デバイスIDの取得
  3. コンテキストの作成
  4. コマンドキューの作成
  5. プログラムのセットアップ(「.clファイル」の読み込み、ビルド)
  6. カーネルの作成
  7. 各種セットアップ(デバイスメモリ確保、カーネルの引数設定など)
  8. カーネル(GPU側の関数)の実行
  9. 生成した各種オブジェクトの破棄


【1】:プラットフォームIDの取得

「clGetPlatformIDs()」を使えばプラットフォームIDを取得できる。
NVIDIA GPUでは「oclGetPlatformID()」が簡単(かも)。

【例】
//--- プラットフォームIDの取得 ---//
cl_platform_id cpPlatform = NULL;//プラットフォームID

ciErrNum = oclGetPlatformID(&cpPlatform);
if (ciErrNum != CL_SUCCESS)
{
	std::cerr << "Can't Get PlatformID\n";
	return -1;
}
▲デフォルトのプラットフォームIDは「0 (=GL_CUCCESS)」。

【2】:デバイスIDの取得

clGetDeviceIDs()関数を使う。
手順的には、デバイス数(GPUの数)を取得し → IDを取得する。
【例】
//--- デバイスの取得 ---//
cl_uint ciDeviceCount = 0; //デバイス数
cl_device_id *cdDevices = NULL;//デバイスID
	
//デバイス数取得 → デバイスID取得
ciErrNum 
	= clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, 0, NULL, &ciDeviceCount);

//データ格納用メモリ確保
cdDevices = new cl_device_id[ciDeviceCount];
ciErrNum 
	= clGetDeviceIDs(cpPlatform, CL_DEVICE_TYPE_GPU, ciDeviceCount, cdDevices, NULL);
if (ciErrNum != CL_SUCCESS)
{
	std::cerr << "Error @ Getting device Infomation\n";
	return -1;
}

… …
//不要になったら破棄
delete [] cdDevices;

【3】:コンテキストの作成


コンテキストの作成には「clCreateContext()関数」を使う
【例】
cl_context cxGPUContext;//OpenCLコンテキスト用

… …
cl_int ciErrNum = CL_SUCCESS; //エラーチェック用
//--- デバイス関係 ---//
cl_uint ciDeviceCount = 0; //デバイス数
cl_device_id *cdDevices = NULL;//デバイスID
… …

//コンテキストの作成
cxGPUContext = clCreateContext(0, ciDeviceCount, cdDevices, NULL, NULL, &ciErrNum);
if (ciErrNum != CL_SUCCESS)
{
	std::cerr << "Can't Create OpenCL Context\n";
	return -1;
}

■clCreateContext関数
cl_context clCreateContext(
			cl_context_properties *properties, //プロパテティ → 「NULL」 でいい
			cl_uint num_devices, //デバイス数
			const cl_device_id *devices, //デバイスID
			void *pfn_notify ( //コールバック関数が必要な時に使用 → とりあえず「NULL」でいい
					const char *errinfo, 
					const void *private_info, 
					size_t cb, 
					void *user_data),
			void *user_data, //pfn_notifyに与えるデータ → 「NULL」でいい
			cl_int *errcode_ret //→エラーコードを拾う時に使う。「NULL」も可能
			)

OpenCLの「コンテキスト」は1つ以上作成する。
作成したコンテキストによって、
OpenCLで使うメモリやコマンドキュー、カーネル(GPUの関数)等を制御する。

【4】:コマンドキューの作成


コマンドキュー」とはカーネル(GPU上の関数)の実行を制御するためのもの。
例えば
  1. カーネルを実行する
  2. メモリデータを転送する(コピーなど)
  3. CPUとGPU上のメモリを対応付ける(アドレスの対応付け)
  4. 同期処理
などがある。

OpenCLではCPU側がこの「コマンドキュー」を作成しておいて、作成したコンテキストで使用する
「各種OpenCLのコマンド」をここに格納しておく仕組みになっている。


「コマンドキュー」は「clCreateCommandQueue()関数」で作成する
【例】
cl_context cxGPUContext;//OpenCLコンテキスト用
cl_command_queue commandQueue;//コマンドキュー
… …

cl_int ciErrNum = CL_SUCCESS; //エラーチェック用

cl_device_id *cdDevices = NULL;//デバイスID

… コンテキストの作成、デバイスIDの取得など …

//コマンドキューの作成
commandQueue = clCreateCommandQueue(cxGPUContext, (*cdDevices), 0, &ciErrNum);
if (ciErrNum != CL_SUCCESS)
{
	std::cerr << " Error in clCreateCommandQueue call !!!\n";
	return -1;
}

■clCreateCommandQueue関数
cl_command_queue clCreateCommandQueue(cl_context context,//コンテキスト
					cl_device_id device,//デバイスID
					cl_command_queue_properties properties, //コマンドキューのプロパティ(今回は0にして無効化)
					cl_int *errcode_ret)//エラーコードを拾う時に使用(NULL可)

※propertiesについて
  • CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
  • CL_QUEUE_PROFILING_ENABLE
が指定できる。



次:OpenCL編02_2

サンプルコード

目次

― その他 ―

Wiki内検索

計測中...(07.10.8〜)

Save The World






▲よろしければ広告のクリックもお願いします


▲ランキングに参加しました

管理人/副管理人のみ編集できます