Skip to content

Instantly share code, notes, and snippets.

@ossdev-somewhere
Created January 7, 2018 12:50
Show Gist options
  • Save ossdev-somewhere/7a0b0e9a302881f499181cf0019cff98 to your computer and use it in GitHub Desktop.
Save ossdev-somewhere/7a0b0e9a302881f499181cf0019cff98 to your computer and use it in GitHub Desktop.
OpenCL NDRange kernel call
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif
#define KERNEL_FILE "add.cl"
#define KERNEL_NAME "add"
#define ARRAY_SIZE (128)
float array_a[ARRAY_SIZE] = {0, 1, 2};
float array_b[ARRAY_SIZE] = {0, 1, 2};
float array_c[ARRAY_SIZE];
static void read_kernel(void);
static void check_status(cl_int err, const char *api);
int main()
{
/* .clファイルを読み込む */
FILE *fp = fopen(KERNEL_FILE, "r");
if (fp == NULL) {
fprintf(stderr, "Could not open file %s.\n", KERNEL_FILE);
exit(1);
}
fseek(fp, 0, SEEK_END);
long file_size = ftell(fp);
char *source = malloc(file_size);
if (source == NULL) {
fprintf(stderr, "Could not allocate memory.\n");
exit(1);
}
fseek(fp, 0, SEEK_SET);
if (fread(source, file_size, 1, fp) != 1) {
fprintf(stderr, "Could not read file %s.\n", KERNEL_FILE);
exit(1);
}
fclose(fp);
/* 1つめのプラットフォームを取得する */
cl_int status;
cl_platform_id platform_id;
cl_uint num_platforms;
status = clGetPlatformIDs(1, &platform_id, &num_platforms);
check_status(status, "clGetPlatformIDs");
/* 1つめのプラットフォームの1つめのデバイスを取得する */
cl_device_id device_id;
cl_uint num_devices;
status = clGetDeviceIDs(platform_id,
CL_DEVICE_TYPE_DEFAULT,
1,
&device_id,
&num_devices);
check_status(status, "clGetDeviceIDs");
/* OpenCLコンテキストを作成する */
cl_context context = clCreateContext(NULL,
1,
&device_id,
NULL,
NULL,
&status);
check_status(status, "clCreateContext");
/* コマンドキューを作成する */
cl_command_queue command_queue = clCreateCommandQueue(context,
device_id,
0,
&status);
check_status(status, "clCreateCommandQueue");
/* プログラムを作成する */
size_t source_size = strlen(source);
cl_program program = clCreateProgramWithSource(context,
1,
(const char **)&source,
(size_t *)&source_size,
&status);
check_status(status, "clCreateProgramWithSource");
/* プログラムをビルドする */
status = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
if (status == CL_BUILD_PROGRAM_FAILURE) {
/* ログのサイズを取得する */
size_t log_size;
clGetProgramBuildInfo(program,
device_id,
CL_PROGRAM_BUILD_LOG,
0,
NULL,
&log_size);
/* ログのメモリを確保する */
char *log = malloc(log_size);
if (log == NULL) {
fprintf(stderr, "Could not allocate memory.\n");
exit(1);
}
/* ログを取得する */
clGetProgramBuildInfo(program,
device_id,
CL_PROGRAM_BUILD_LOG,
log_size,
log,
NULL);
/* ログを表示する */
printf("%s\n", log);
free(log);
exit(1);
}
check_status(status, "clBuildProgram");
/* カーネルを作成する */
cl_kernel kernel = clCreateKernel(program, KERNEL_NAME, &status);
check_status(status, "clCreateKernel");
/* バッファを作成する */
cl_mem mem_a = clCreateBuffer(context,
CL_MEM_COPY_HOST_PTR | CL_MEM_READ_ONLY,
ARRAY_SIZE * sizeof(cl_float),
array_a,
&status);
check_status(status, "clCreateBuffer a");
cl_mem mem_b = clCreateBuffer(context,
CL_MEM_COPY_HOST_PTR | CL_MEM_READ_ONLY,
ARRAY_SIZE * sizeof(cl_float),
array_b,
&status);
check_status(status, "clCreateBuffer b");
cl_mem mem_c = clCreateBuffer(context,
CL_MEM_WRITE_ONLY,
ARRAY_SIZE * sizeof(cl_float),
NULL,
&status);
check_status(status, "clCreateBuffer c");
/* カーネルの引数をセットする */
status = clSetKernelArg(kernel, 0, sizeof(cl_mem), &mem_a);
check_status(status, "clSetKernelArg");
status = clSetKernelArg(kernel, 1, sizeof(cl_mem), &mem_b);
check_status(status, "clSetKernelArg");
status = clSetKernelArg(kernel, 2, sizeof(cl_mem), &mem_c);
check_status(status, "clSetKernelArg");
/* カーネルを実行する */
size_t global_work_size[1] = {ARRAY_SIZE};
size_t local_work_size[1] = {1};
status = clEnqueueNDRangeKernel(command_queue,
kernel,
1,
NULL,
global_work_size,
local_work_size,
0,
NULL,
NULL);
check_status(status, "clEnqueueNDRangeKernel");
status = clFlush(command_queue);
check_status(status, "clFlush");
status = clFinish(command_queue);
check_status(status, "clFinish");
/* バッファから結果を取得する */
status = clEnqueueReadBuffer(command_queue,
mem_c,
CL_TRUE,
0,
ARRAY_SIZE * sizeof(cl_float),
array_c,
0,
NULL,
NULL);
check_status(status, "clEnqueueReadBuffer");
/* 結果を表示する */
printf("%f %f %f\n", array_c[0], array_c[1], array_c[2]);
/* 終了処理を行う */
status = clReleaseKernel(kernel);
check_status(status, "clReleaseKernel");
status = clReleaseProgram(program);
check_status(status, "clReleaseProgram");
status = clReleaseMemObject(mem_c);
check_status(status, "clReleaseMemObject");
status = clReleaseMemObject(mem_b);
check_status(status, "clReleaseMemObject");
status = clReleaseMemObject(mem_a);
check_status(status, "clReleaseMemObject");
status = clReleaseCommandQueue(command_queue);
check_status(status, "clReleaseCommandQueue");
status = clReleaseContext(context);
check_status(status, "clReleaseContext");
free(source);
return 0;
}
/*
* APIエラーを確認する
*/
static void check_status(cl_int err, const char *api)
{
if (err == CL_SUCCESS)
return;
fprintf(stderr, "API %s error: %d\n", api, err);
exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment