目指すところ
OpenCLとは何かみたいな話は他のサイトに譲って、使いましょう。楽しいから。
プログラム全文
githubからクローンできます。
環境構築
この記事で作った環境
Visual Studioがちょっと古いですが、ビルド設定はそんなに差はないと思います。
・Windows 10
・Visual Studio 2015
・Intel SDK for OpenCL 7.0.0.2519
OpenCL SDKの入手
OpenCLはKhronos Groupが仕様を策定して、各ベンダーが仕様に基づいた実装を行っています。そのため、所有する機器のベンダーからOpenCLのSDKを入手する必要があります。
インテル製CPU/GPUの場合、Intel® SDK for OpenCL™ ApplicationsからIntel向けOpenCL SDKを入手します。SDKの入手にはメールアドレスを入力してデベロッパーに登録したりする必要があり、ちょっと面倒かも。
インストールはインストーラに言われるがままにやるだけなので割愛です。
ビルド設定(Visual Studio)
インストールが完了したらVisual Studioを起動して、とりあえず新規プロジェクトを作りましょう。困ったときのwin32コンソールアプリケーションを選択、面倒なので空のプロジェクトにして作ります。
プロジェクトを作ったら、ビルド設定を変更してOpenCLを利用できるようにします。
まずは[VC++ ディレクトリ]の中の[インクルード ディレクトリ]にincludeフォルダを指定します。IntelSDKを何も考えずに突っ込んだ場合はC:\Intel\OpenCL\sdk\includeというパスになりました。
このとき、includeの中にあるCLというフォルダにパスを通さないように気を付けます。CLの中に通してしまうと、大事なものがいろいろ見つからなくなります
続いて、[リンカー]→[全般]の中の[追加のライブラリ ディレクトリ]にlibフォルダを指定します。libフォルダの中にはx64向けとx86向けのそれぞれのフォルダがあるので、必要な方にパスを通してください。今回はC:\Intel\OpenCL\sdk\lib\x86にパスを通しました。
最後に、[リンカー]→[入力]の中の[追加の依存ファイル]にOpenCL.libを指定します。
プラットフォームとデバイスを調べる
Congratulations!これで楽しいOpenCLライフが満喫できます!!いいえ、まだです!!
OpenCLを実際に使うときには、OpenCLに対応したデバイスのうちどれを使うのか、インデックスを用いて指定する必要があります。そこで、自分の機器にどんなOpenCLデバイスがあるのか調べてみましょう。ソースファイルにmain.cを追加して、以下のプログラムを書いて実行してみましょう。
#include <stdio.h>
#include <CL/cl.h>
int main(int argc, char **argv)
{
// プラットフォーム取得
cl_uint platformNumber = 0;
cl_platform_id platformIds[8];
clGetPlatformIDs(8, platformIds, &platformNumber);
char string[256];
cl_device_type type;
cl_uint value;
size_t sizes[3];
cl_ulong ulvalue;
for (int i = 0; i < platformNumber; i++)
{
printf("platform idx : %d\n", i);
cl_platform_id platform = platformIds[i];
clGetPlatformInfo(platform, CL_PLATFORM_VENDOR, 256, string, NULL);
printf("platform vendor : %s\n", string);
clGetPlatformInfo(platform, CL_PLATFORM_NAME, 256, string, NULL);
printf("platform name : %s\n", string);
clGetPlatformInfo(platform, CL_PLATFORM_VERSION, 256, string, NULL);
printf("platform version : %s\n", string);
// デバイス取得
cl_uint deviceNumber = 0;
cl_device_id deviceIds[8];
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 8, deviceIds, &deviceNumber);
for (int j = 0; j < deviceNumber; j++)
{
printf(" device idx : %d\n", j);
cl_device_id device = deviceIds[j];
clGetDeviceInfo(device, CL_DEVICE_NAME, 256, string, NULL);
printf(" device name : %s\n", string);
clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &type, NULL);
if (type == CL_DEVICE_TYPE_CPU) printf(" device type : CPU\n");
if (type == CL_DEVICE_TYPE_GPU) printf(" device type : GPU\n");
if (type == CL_DEVICE_TYPE_ACCELERATOR) printf(" device type : ACCELERATOR\n");
clGetDeviceInfo(device, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &value, NULL);
printf(" device max compute units : %d\n", value);
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * 3, sizes, NULL);
printf(" device max work item sizes : [%d][%d][%d]\n", sizes[0], sizes[1], sizes[2]);
clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(cl_uint), &value, NULL);
printf(" device max work group size : %d\n", value);
clGetDeviceInfo(device, CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &ulvalue, NULL);
printf(" device max mem alloc size : %d\n", ulvalue);
clGetDeviceInfo(device, CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(cl_ulong), &ulvalue, NULL);
printf(" device max constant buffer size : %d\n", ulvalue);
}
}
}
実行してみると、私の環境では以下のように表示されました。
この表示を見ながらどの機器を使用するのか検討して、使用する機器のplatform idxとdevice idxを用いてOpenCL環境を初期化します。
続く
次は実際に簡単なカーネルプログラムを作って、OpenCLの基本的な使い方を知るC++でOpenCL(使ってみよう編)をやります。