Skip to content

Instantly share code, notes, and snippets.

@ossdev-somewhere
Created January 7, 2018 14:10
Show Gist options
  • Save ossdev-somewhere/8708ea7678a5e176376016bd59a372a2 to your computer and use it in GitHub Desktop.
Save ossdev-somewhere/8708ea7678a5e176376016bd59a372a2 to your computer and use it in GitHub Desktop.
OpenCL single work-item host program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif
#define KERNEL_FILE "hello.cl"
#define KERNEL_NAME "hello"
#define ARRAY_SIZE (128)
#define ALIGN (16)
char *array_a;
char *array_b;
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");
/* 配列を確保する */
if (posix_memalign((void **)&array_a, ALIGN, ARRAY_SIZE) != 0) {
fprintf(stderr, "Could not allocate memory.\n");
exit(1);
}
if (posix_memalign((void **)&array_b, ALIGN, ARRAY_SIZE) != 0) {
fprintf(stderr, "Could not allocate memory.\n");
exit(1);
}
strcpy(array_a, "hello, world!");
/* バッファを作成する */
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_WRITE_ONLY,
ARRAY_SIZE * sizeof(cl_float),
NULL,
&status);
check_status(status, "clCreateBuffer b");
/* カーネルの引数をセットする */
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 = clEnqueueTask(command_queue, kernel, 0, NULL, NULL);
check_status(status, "clEnqueueTask");
status = clFlush(command_queue);
check_status(status, "clFlush");
status = clFinish(command_queue);
check_status(status, "clFinish");
/* バッファから結果を取得する */
status = clEnqueueReadBuffer(command_queue,
mem_b,
CL_TRUE,
0,
ARRAY_SIZE,
array_b,
0,
NULL,
NULL);
check_status(status, "clEnqueueReadBuffer");
/* 結果を表示する */
printf("%s\n", array_b);
/* 終了処理を行う */
free(array_b);
free(array_a);
status = clReleaseKernel(kernel);
check_status(status, "clReleaseKernel");
status = clReleaseProgram(program);
check_status(status, "clReleaseProgram");
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