Intel OpenCLをUbuntu 11.10 64bitで使う | たけおか ぼちぼち日記

たけおか ぼちぼち日記

思いついたらメモ


Ubuntu 11.10 64bit でIntel OpenCL SDKを動かした。
しかし、アホなことにGPUは動かしていない。
私が愛用している Thinkpad X220 (iCore-5 2520M, Intel HD Graphics 3000)でヘラヘラ試していたが、
よく調べると、HD Graphics 3000にはOpenCLサポートは無かった。(へらへら~)

Ubuntuで Intel OpenCLを動かすための日本語の情報は少ないので一応、ここに記す。



Ubuntu で、Intel OpenCLを動かすには、下のページに書いてあるとおり。
http://mhr3.blogspot.com/2011/05/opencl-on-ubuntu.html

それをなぞってやったこと。


1. Intel OpenCLサイトから、SDKをダウンロード(rpmパッケージ)

下記がメインの入り口であろうか?

http://software.intel.com/en-us/articles/vcsource-tools-opencl-sdk/


具体的なダウンロードは下記。

http://software.intel.com/en-us/articles/download-intel-opencl-sdk/


今回は、"Intel® OpenCL SDK Downloads (updated September 26th)" と書いてあった。

"intel_ocl_sdk_1.5_x64.tgz" - package for 64-bit operating systems.
をダウンロード。
(なぜか、私の場合、ファイルが途中で切れていて、何週間もえらく悩んだ。ファイルを再度ゲットしたら嘘のようにうまく行った)

このファイルを、適当なディレクトリで、
% tar xvzf intel_ocl_sdk_1.5_x64.tgz
として、展開する。
すると、rpmとライセンス書きが出てくる。(苦笑)

28469424 2011-09-14 23:28 intel_ocl_sdk_1.5_x64.rpm
23751 2011-09-14 23:28 license.txt

以降、面倒なので、わたしは、次のようにして、rootになって作業する。
% sudo tcsh
自分のパスワードを入力して、あとはroot権限で作業。プロンプトは'#'


2. Ubuntuは、rpmではダメなので、debに変換する。

rpmからdebに変換するには、 rpmとalien のパッケージが必要。入っていなければ、下記のようにインストール。
# apt-get install rpm alien


3. rpm -> deb 変換

# alien --to-deb intel_ocl_sdk_1.5_x64.rpm
変換が終わると、
28472592 2012-01-06 19:45 intel-ocl-sdk_1.5-15294_amd64.deb
というファイルができた。(Intelなのに、amd64とか付いてて可愛い)

alienの実行には、root権限が無ければならない(fakerootコマンドと併用する方法もあり)。



4. OpenCL SDKのインストール

# dpkg -i intel-ocl-sdk_1.5-15294_amd64.deb


5. そして、libnumaを入れていなければ、次のようにしてインストール。
# apt-get install libnuma1

ここで、
/usr/lib64/ に、
drwxr-xr-x 3 root root 4096 2012-01-06 19:48 OpenCL/
-rwxr-xr-x 1 root root 33683 2011-09-14 23:27 libOpenCL.so*
とかできている。


6. /etc/OpenCL/vendors/intelocl64.icdを確認。
当該ファイルが無ければ、
# echo "libintelocl.so" > /etc/OpenCL/vendors/intelocl64.icd
とする。


7.OpenCL ヘッダーファイル

OpenCL ヘッダーファイルは、 /usr/include/CLにある。
メインのライブラリは、/usr/lib64/libOpenCL.so 。
好みによって、
# ldconfig /usr/lib64
# ldconfig /usr/lib64/OpenCL/vendors/intel
とかやるといいかも。(自分はやってしまった)


ldconfig をやらなくとも、
各ユーザの ~/.profile や、 ~/.cshrc で、
環境変数 LD_LIBRARY_PATHに/usr/lib64/OpenCL/vendors/intelを加えておけばよい。

bsh系
export LD_LIBRARY_PATH=/usr/lib64/OpenCL/vendors/intel:$LD_LIBRARY_PATH

csh系
setenv LD_LIBRARY_PATH /usr/lib64/OpenCL/vendors/intel:$LD_LIBRARY_PATH

ちなみに、/usr/lib64/OpenCL/vendors/intel/ にllcとか入っている。


以上で、Intel OpenCL SDKは、インストールできた。




OpenCLを試す その1


ここで述べた簡単なプログラムの俺バージョンの tgz ファイルをダウンロードできます。(platとvadd)




「Intel® OpenCL SDK User's Guide」 (http://software.intel.com/file/38642)

の 4.4 Working with the OpenCL Installable Client Driver (ICD) に
書いてある例題で、OpenCL SDKが入っているかを確認。



#include <opencl.h>
#include <cl_platform.h>


cl_platform_id * platforms = NULL;
char vendor_name[128] = {0};
cl_uint num_platforms = 0;

cl_uint num_devices=0;


int aaa()
{
// get number of available platforms
cl_int err = clGetPlatformIDs(0, NULL, & num_platforms);
printf("err=%d,num_platforms=%d\n", err, num_platforms );
if(CL_SUCCESS != err) {
printf("err!\n");
}
platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id)* num_platforms);
if(NULL == platforms){
printf("malloc err!\n");
}
err = clGetPlatformIDs(num_platforms, platforms, NULL);
printf("clGetPlatformIDs err=%d platforms[0]=%x\n", err, platforms[0] );
if(CL_SUCCESS != err){
printf("clGetPlatformIDs err!\n");
}
for (cl_uint ui=0; ui< num_platforms; ++ui){
printf("platforms[ui]=%x\n", platforms[ui] );
err = clGetPlatformInfo(platforms[ui], CL_PLATFORM_VENDOR,
128*sizeof(char), vendor_name, NULL);
printf("err=%d,vendor_name=%s\n", err, vendor_name );
if(CL_SUCCESS != err){ printf("error !\n"); }
err = clGetPlatformInfo(platforms[ui], CL_PLATFORM_NAME,
128*sizeof(char), vendor_name, NULL);
printf("err=%d,NAME=%s\n",err, vendor_name );
if(CL_SUCCESS != err){ printf("error !\n"); }
err = clGetPlatformInfo(platforms[ui], CL_PLATFORM_VERSION,
128*sizeof(char), vendor_name, NULL);
printf("err=%d,VERSION=%s\n",err, vendor_name );
if(CL_SUCCESS != err){ printf("error !\n"); }
err = clGetPlatformInfo(platforms[ui], CL_PLATFORM_PROFILE,
128*sizeof(char), vendor_name, NULL);
printf("err=%d,profile=%s\n",err, vendor_name );
if(CL_SUCCESS != err){ printf("error !\n"); }
err = clGetPlatformInfo(platforms[ui], CL_PLATFORM_EXTENSIONS,
128*sizeof(char), vendor_name, NULL);
printf("err=%d,extensions=%s\n",err, vendor_name );
if(CL_SUCCESS != err){ printf("error !\n"); }
if(vendor_name != NULL){
if(!strcmp(vendor_name, "Intel Corporation")){
return platforms[ui];
}
}
}
// handle error
}


#define XXX CL_DEVICE_TYPE_ALL
//#define XXX CL_DEVICE_TYPE_DEFAULT
//#define XXX CL_DEVICE_TYPE_ACCELERATOR
//#define XXX CL_DEVICE_TYPE_GPU
//#define XXX CL_DEVICE_TYPE_CPU

cl_device_id device_id = NULL;

dev()
{
int ret;
ret = clGetDeviceIDs( platforms[0], XXX,0,NULL, &num_devices);
printf("clGetDeviceIDs err=%d,num_devices=%d\n", ret, num_devices );
ret = clGetDeviceIDs( platforms[0], XXX,1,&device_id, &num_devices);
printf("clGetDeviceIDs err=%d,num_devices=%d, device_id=%x\n", ret, num_devices, device_id );

}

int main(int argc, char *argv[])
{
aaa();
dev();
}




上記で、Intelの例は、
#define XXX CL_DEVICE_TYPE_ALL
としている。

私のThinkpad X220は、GPUでのOpenCLがサポートされていないので、
#define XXX CL_DEVICE_TYPE_ALL
または、
#define XXX CL_DEVICE_TYPE_CPU
でしか動作しない。

ret = clGetDeviceIDs( platforms[0], CL_DEVICE_TYPE_GPU, 1,&device_id, &num_devices);
で、エラーが返る。そりゃそうだ、GPUを使えないのだもの。


また、他社のOpenGLでは、
CL_DEVICE_TYPE_DEFAULT
が許されているようだが、今回のIntel OpenCL SDKで、私の環境では、エラーが返る。(コンパイルは正常に通る)
ひょっとして、DefaultがGPUになっていて、今回は、それが使用できないから、エラーなのか???


platの実行結果

% ./plat
err=0,num_platforms=1
clGetPlatformIDs err=0 platforms[0]=9b4080
platforms[ui]=9b4080
err=0,vendor_name=Intel(R) Corporation
err=0,NAME=Intel(R) OpenCL
err=0,VERSION=OpenCL 1.1 LINUX
err=0,profile=FULL_PROFILE
err=-30,extensions=FULL_PROFILE
error !
clGetDeviceIDs err=0,num_devices=1
clGetDeviceIDs err=0,num_devices=1, device_id=9c18e0







OpenCLを試す その2

やっぱ、OpenCL kernelを動かさないといけないよね。
ということで、Webをふらふらと彷徨ったら、ばっちり初心者向けを書いてくれている人が! (優しい)


Getting started with OpenCL and GPU Computing
http://www.thebigblob.com/getting-started-with-opencl-and-gpu-computing/


ここに、単なるベクトル(一次元行列)の足し算の例題がある。
ソースもダウンロードできる。
俺バージョンの tgz ファイルをダウンロードできます。(platとvadd)


ここのmain (俺バージョンでは vadd.c)の 43行あたりの

ret = clGetDeviceIDs( platform_id, CL_DEVICE_TYPE_DEFAULT, 1,
&device_id, &ret_num_devices);

の CL_DEVICE_TYPE_DEFAULT は、私のGPU無し環境では、当然 CL_DEVICE_TYPE_CPU にしなければならない(とほほ)

俺バージョンの場合は、
% make とやれば、
vaddという実行形式ファイルができる。
openCLカーネル・プログラムは、
vector_add_kernel.cl
という名称で、同じディレクトリ(カレント・ディレクトリ)に置く。
この名称は、vadd.c の中にハード・コードされている。


% ./vadd
clGetPlatformIDs err=0,num_platforms=1, platform_id=b1fba0
clGetDeviceIDs err=0,num_platforms=1, device_id=b2b930
0 + 1024 = 1024
1 + 1023 = 1024
2 + 1022 = 1024
:
:
1022 + 2 = 1024
1023 + 1 = 1024

という結果が出て、めでたしめでたし。


Intel OpenCLとしては、正常動作しているようだ。


Intel HD Graphics 2500だと、OpenCLが動くようだ。上位っぽい名称の3000でOpenCLが動かないとは…今回は、とてもトホホ感のあるチャレンジだった。

次は、NotePCで挑戦するのはやめて、素直に据え置き機で試そう…