背景
OpenCLとは、GPUという画像処理プロセッサを利用して並列処理を行うプログラムです。IntelのCPUの中にはGPUが内蔵されているものがあり、それを利用することで並列処理プログラムを作れます。
しかし、ハードウェアに依存するためか、インテルが提供するプログラムを設定する必要がありました。
詰まるところがあったので、メモを共有します。
全体像
- 使ったPC
- GPUのランタイムを設定
- OpenCLを設定
- 動作確認
- まとめ
使ったPC
分類 | 名前 |
---|---|
モデル | Lenovo ThinkPad S1 Yoga |
CPU | Intel Core i7-4600U CPU @ 2.10GHz × 4 |
GPU | Intel Haswell Mobile |
OS | Ubuntu17.10 |
GPUのランタイムを設定
Intelのwebページから、OpenCLのRuntimeをダウンロードします。注意: SDKやDriverではなく、Runtimeです。
ページの途中にダウンロードリンクがあるので、「runtime」でページ内検索すると見つけやすいです。
OpenC Drivers and Runtimes for Intel Architecture
Ubuntuを使っているので、「for Red Hat* and Ubuntu* Linux* (64-bit)」をダウンロードしました。
ダウンロードできたら、下記のような流れで解凍、インストールできます。
cd ~/Downloads tar zxvf opencl_runtime_16.1.2_x64_rh_6.4.0.37.tgz cd opencl_runtime_16.1.2_x64_rh_6.4.0.37 sudo ./install.sh
OpenCLを設定
aptコマンドでインストールできます。sudo apt install ocl-icd-opencl-dev
下記のコマンドでバージョンを確認できます。
sudo apt-cache show ocl-icd-dev
2.2.11がインストールされたようです。
... Version: 2.2.11-1ubuntu1 ...
動作確認
OpenCLのプログラムを動かしてみます。ディレクトリを作り、その中に下記のプログラムを配置します。
今回のサンプルに使うのは、こちらのページ(3.3 First OpenCL Program)にあった、OpenCLで「Hello, World!]という文字列を作るプログラムです。
hello.c
#include <stdio.h> #include <stdlib.h> #ifdef __APPLE__ #include <OpenCL/opencl.h> #else #include <CL/cl.h> #endif #define MEM_SIZE (128) #define MAX_SOURCE_SIZE (0x100000) int main() { cl_device_id device_id = NULL; cl_context context = NULL; cl_command_queue command_queue = NULL; cl_mem memobj = NULL; cl_program program = NULL; cl_kernel kernel = NULL; cl_platform_id platform_id = NULL; cl_uint ret_num_devices; cl_uint ret_num_platforms; cl_int ret; char string[MEM_SIZE]; FILE *fp; char fileName[] = "./hello.cl"; char *source_str; size_t source_size; /* Load the source code containing the kernel*/ fp = fopen(fileName, "r"); if (!fp) { fprintf(stderr, "Failed to load kernel.\n"); exit(1); } source_str = (char*)malloc(MAX_SOURCE_SIZE); source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp); fclose(fp); /* Get Platform and Device Info */ ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms); ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices); /* Create OpenCL context */ context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret); /* Create Command Queue */ command_queue = clCreateCommandQueueWithProperties(context, device_id, 0, &ret); /* Create Memory Buffer */ memobj = clCreateBuffer(context, CL_MEM_READ_WRITE,MEM_SIZE * sizeof(char), NULL, &ret); /* Create Kernel Program from the source */ program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret); /* Build Kernel Program */ ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL); /* Create OpenCL Kernel */ kernel = clCreateKernel(program, "hello", &ret); /* Set OpenCL Kernel Parameters */ ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj); /* Execute OpenCL Kernel */ size_t globalWorkSize[] = {1}; size_t localWorkSize[] = {1}; ret = clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, globalWorkSize, localWorkSize, 0, NULL, NULL); /* Copy results from the memory buffer */ ret = clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0, MEM_SIZE * sizeof(char),string, 0, NULL, NULL); /* Display Result */ puts(string); /* Finalization */ ret = clFlush(command_queue); ret = clFinish(command_queue); ret = clReleaseKernel(kernel); ret = clReleaseProgram(program); ret = clReleaseMemObject(memobj); ret = clReleaseCommandQueue(command_queue); ret = clReleaseContext(context); free(source_str); return 0; }
hello.cl
__kernel void hello(__global char* string) { string[0] = 'H'; string[1] = 'e'; string[2] = 'l'; string[3] = 'l'; string[4] = 'o'; string[5] = ','; string[6] = ' '; string[7] = 'W'; string[8] = 'o'; string[9] = 'r'; string[10] = 'l'; string[11] = 'd'; string[12] = '!'; string[13] = '\0'; }
上記のファイルをコンパイルするにあたり、gccをインストールしていない場合は、下記のコマンドでインストールしてください。
sudo apt install build-essential
OpenCLのオプションを付けて、プログラムをコンパイルします。
gcc hello.c -lOpenCL
コンパイルできたら、下記のコマンドでファイルを実行します。
./a.out
「Hello, World!」と表示されたら成功です。
まとめ
IntelのGPUを利用して、OpenCLのプログラムを実行できました。何かの参考になれば嬉しいです。
0 件のコメント :
コメントを投稿