Skip to content

Commit 3b4a930

Browse files
committed
Opencl refactor
1 parent ad19120 commit 3b4a930

File tree

11 files changed

+167
-154
lines changed

11 files changed

+167
-154
lines changed

opencl/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
1. [Increment vector](inc_vector.c)
77
1. [Pass by value](pass_by_value.c)
88
1. [Work item built-ins](work_item_builtin.c)
9-
1. [Vector built-in](vector_builtin.c)
9+
1. [Vector type](vector_type.c)
1010
1. Tools
1111
1. [clinfo](clinfo.md)
1212
1. [Benchmarks](benchmarks.md)

opencl/common.h

Lines changed: 59 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,75 @@
55
#include <stdio.h>
66
#include <stdlib.h>
77

8+
// http://stackoverflow.com/questions/28500496/opencl-function-found-deprecated-by-visual-studio
9+
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
810
#include <CL/cl.h>
911

10-
void common_check_build(
11-
cl_int ret,
12-
cl_device_id device,
13-
cl_program program
12+
typedef struct {
13+
cl_context context;
14+
cl_device_id device;
15+
cl_kernel kernel;
16+
cl_program program;
17+
} Common;
18+
19+
static void common_init(
20+
Common *common,
21+
const char *source
1422
) {
1523
char *err;
1624
size_t err_len;
25+
cl_int ret;
26+
cl_platform_id platform;
27+
28+
clGetPlatformIDs(1, &platform, NULL);
29+
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &(common->device), NULL);
30+
common->context = clCreateContext(NULL, 1, &(common->device), NULL, NULL, NULL);
31+
common->program = clCreateProgramWithSource(common->context, 1, &source, NULL, NULL);
32+
ret = clBuildProgram(common->program, 1, &(common->device), "", NULL, NULL);
1733
if (CL_SUCCESS != ret) {
18-
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &err_len);
34+
clGetProgramBuildInfo(common->program, common->device, CL_PROGRAM_BUILD_LOG, 0, NULL, &err_len);
1935
err = malloc(err_len);
20-
clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, err_len, err, NULL);
21-
printf("Kernel build error:\n%s\n", err);
36+
clGetProgramBuildInfo(common->program, common->device, CL_PROGRAM_BUILD_LOG, err_len, err, NULL);
37+
fprintf(stderr, "error: kernel build:\n%s\n", err);
2238
free(err);
2339
exit(EXIT_FAILURE);
2440
}
41+
common->kernel = clCreateKernel(common->program, "main", NULL);
42+
}
43+
44+
static char * common_read_file(const char *path) {
45+
char *buffer;
46+
FILE *f;
47+
long length;
48+
49+
f = fopen(path, "r");
50+
fseek (f, 0, SEEK_END);
51+
length = ftell(f);
52+
fseek(f, 0, SEEK_SET);
53+
buffer = calloc(1, length + 1);
54+
fread (buffer, 1, length, f);
55+
fclose (f);
56+
buffer[length] = '\0';
57+
return buffer;
58+
}
59+
60+
static void common_init_file(
61+
Common *common,
62+
const char *source_path
63+
) {
64+
char *source;
65+
source = common_read_file(source_path);
66+
common_init(common, source);
67+
free(source);
68+
}
69+
70+
static void common_deinit(
71+
Common *common
72+
) {
73+
clReleaseProgram(common->program);
74+
clReleaseKernel(common->kernel);
75+
clReleaseContext(common->context);
76+
clReleaseDevice(common->device);
2577
}
2678

2779
#endif

opencl/getting-started.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Getting started
22

3-
Tested in Ubuntu 15.10 NVIDIA 352.
3+
Tested in Ubuntu 15.10 NVIDIA 352, OpenCL 1.2.
4+
5+
The day we do OpenCL 2.0, it will be put inside a subdirectory and clearly labeled.
46

57
## NVIDIA
68

opencl/inc.c

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
11
/*
22
Pass an int by reference and increment it.
33
4-
This is our OpenCL hello world. No error checking for simplicity.
4+
This is our OpenCL hello world, so we are not doing:
5+
6+
- error checking
7+
- factoring out with anything else
58
*/
69

710
#include <assert.h>
811
#include <stdio.h>
912

13+
#define CL_USE_DEPRECATED_OPENCL_1_2_APIS
1014
#include <CL/cl.h>
1115

1216
int main(void) {
1317
const char *source =
1418
/* kernel pointer arguments must be __global, __constant, or __local. */
1519
/* https://www.khronos.org/registry/cl/sdk/2.1/docs/man/xhtml/restrictions.html */
16-
"__kernel void increment(__global int *out) {\n"
20+
"__kernel void main(__global int *out) {\n"
1721
" out[0]++;\n"
1822
"}\n";
1923
cl_command_queue command_queue;
@@ -31,8 +35,7 @@ int main(void) {
3135
context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);
3236
program = clCreateProgramWithSource(context, 1, &source, NULL, NULL);
3337
clBuildProgram(program, 1, &device, "", NULL, NULL);
34-
/* The name of the kernel function we want to call. */
35-
kernel = clCreateKernel(program, "increment", NULL);
38+
kernel = clCreateKernel(program, "main", NULL);
3639
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(cl_int), &input, NULL);
3740
clSetKernelArg(kernel, 0, sizeof(buffer), &buffer);
3841
command_queue = clCreateCommandQueue(context, device, 0, NULL);
@@ -45,10 +48,11 @@ int main(void) {
4548
assert(input == 2);
4649

4750
/* Cleanup. */
48-
clReleaseKernel(kernel);
49-
clReleaseProgram(program);
5051
clReleaseCommandQueue(command_queue);
51-
clReleaseContext(context);
5252
clReleaseMemObject(buffer);
53+
clReleaseProgram(program);
54+
clReleaseKernel(kernel);
55+
clReleaseContext(context);
56+
clReleaseDevice(device);
5357
return EXIT_SUCCESS;
5458
}

opencl/inc_vector.c

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,27 +17,17 @@ int main(void) {
1717
" out[get_global_id(0)]++;\n"
1818
"}\n";
1919
cl_command_queue command_queue;
20-
cl_context context;
21-
cl_device_id device;
22-
cl_int input[] = {1, 2}, ret;
23-
const size_t global_work_size = sizeof(input) / sizeof(cl_int);
24-
cl_kernel kernel;
20+
cl_int input[] = {1, 2};
2521
cl_mem buffer;
26-
cl_platform_id platform;
27-
cl_program program;
22+
const size_t global_work_size = sizeof(input) / sizeof(cl_int);
23+
Common common;
2824

2925
/* Run kernel. */
30-
clGetPlatformIDs(1, &platform, NULL);
31-
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL);
32-
context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);
33-
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(input), &input, NULL);
34-
program = clCreateProgramWithSource(context, 1, &source, NULL, NULL);
35-
ret = clBuildProgram(program, 1, &device, "", NULL, NULL);
36-
common_check_build(ret, device, program);
37-
kernel = clCreateKernel(program, "main", NULL);
38-
clSetKernelArg(kernel, 0, sizeof(cl_mem), &buffer);
39-
command_queue = clCreateCommandQueue(context, device, 0, NULL);
40-
clEnqueueNDRangeKernel(command_queue, kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);
26+
common_init(&common, source);
27+
buffer = clCreateBuffer(common.context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(input), &input, NULL);
28+
clSetKernelArg(common.kernel, 0, sizeof(cl_mem), &buffer);
29+
command_queue = clCreateCommandQueue(common.context, common.device, 0, NULL);
30+
clEnqueueNDRangeKernel(command_queue, common.kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);
4131
clFlush(command_queue);
4232
clFinish(command_queue);
4333
clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, 0, sizeof(input), &input, 0, NULL, NULL);
@@ -47,10 +37,8 @@ int main(void) {
4737
assert(input[1] == 3);
4838

4939
/* Cleanup. */
50-
clReleaseKernel(kernel);
51-
clReleaseProgram(program);
52-
clReleaseCommandQueue(command_queue);
53-
clReleaseContext(context);
5440
clReleaseMemObject(buffer);
41+
clReleaseCommandQueue(command_queue);
42+
common_deinit(&common);
5543
return EXIT_SUCCESS;
5644
}

opencl/pass_by_value.c

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,17 @@ int main(void) {
1515
" out[0] = in + 1;\n"
1616
"}\n";
1717
cl_command_queue command_queue;
18-
cl_context context;
19-
cl_device_id device;
20-
cl_int input = 1, ret;
21-
cl_kernel kernel;
18+
cl_int input = 1;
2219
cl_mem buffer;
23-
cl_platform_id platform;
24-
cl_program program;
20+
Common common;
2521

2622
/* Run kernel. */
27-
clGetPlatformIDs(1, &platform, NULL);
28-
clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 1, &device, NULL);
29-
context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);
30-
buffer = clCreateBuffer(context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, NULL);
31-
program = clCreateProgramWithSource(context, 1, &source, NULL, NULL);
32-
ret = clBuildProgram(program, 1, &device, "", NULL, NULL);
33-
common_check_build(ret, device, program);
34-
kernel = clCreateKernel(program, "main", NULL);
35-
clSetKernelArg(kernel, 0, sizeof(cl_int), &input);
36-
clSetKernelArg(kernel, 1, sizeof(cl_mem), &buffer);
37-
command_queue = clCreateCommandQueue(context, device, 0, NULL);
38-
clEnqueueTask(command_queue, kernel, 0, NULL, NULL);
23+
common_init(&common, source);
24+
buffer = clCreateBuffer(common.context, CL_MEM_READ_WRITE, sizeof(cl_int), NULL, NULL);
25+
clSetKernelArg(common.kernel, 0, sizeof(cl_int), &input);
26+
clSetKernelArg(common.kernel, 1, sizeof(cl_mem), &buffer);
27+
command_queue = clCreateCommandQueue(common.context, common.device, 0, NULL);
28+
clEnqueueTask(command_queue, common.kernel, 0, NULL, NULL);
3929
clFlush(command_queue);
4030
clFinish(command_queue);
4131
clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, 0, sizeof(cl_int), &input, 0, NULL, NULL);
@@ -44,10 +34,8 @@ int main(void) {
4434
assert(input == 2);
4535

4636
/* Cleanup. */
47-
clReleaseKernel(kernel);
48-
clReleaseProgram(program);
49-
clReleaseCommandQueue(command_queue);
50-
clReleaseContext(context);
5137
clReleaseMemObject(buffer);
38+
clReleaseCommandQueue(command_queue);
39+
common_deinit(&common);
5240
return EXIT_SUCCESS;
5341
}

opencl/vector_builtin.c

Lines changed: 0 additions & 55 deletions
This file was deleted.

opencl/vector_type.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
Increment a vector type (int2) using a vector built-in type.
3+
4+
http://stackoverflow.com/questions/13118228/how-to-pass-vector-paramater-to-opencl-kernel-in-c
5+
6+
TODO: is using them faster than scalars?
7+
8+
- http://stackoverflow.com/questions/20200203/using-own-vector-type-in-opencl-seems-to-be-faster
9+
*/
10+
11+
#include "common.h"
12+
13+
int main(void) {
14+
const char *source =
15+
"__kernel void main(__global int2 *out) {\n"
16+
" out[get_global_id(0)]++;\n"
17+
"}\n";
18+
cl_command_queue command_queue;
19+
cl_int input[] = {0, 1, 2, 3};
20+
cl_mem buffer;
21+
Common common;
22+
const size_t global_work_size = sizeof(input) / sizeof(cl_int2);
23+
24+
/* Run kernel. */
25+
common_init(&common, source);
26+
buffer = clCreateBuffer(common.context, CL_MEM_READ_WRITE | CL_MEM_COPY_HOST_PTR, sizeof(input), &input, NULL);
27+
clSetKernelArg(common.kernel, 0, sizeof(cl_mem), &buffer);
28+
command_queue = clCreateCommandQueue(common.context, common.device, 0, NULL);
29+
clEnqueueNDRangeKernel(command_queue, common.kernel, 1, NULL, &global_work_size, NULL, 0, NULL, NULL);
30+
clFlush(command_queue);
31+
clFinish(command_queue);
32+
clEnqueueReadBuffer(command_queue, buffer, CL_TRUE, 0, sizeof(input), &input, 0, NULL, NULL);
33+
34+
/* Assertions. */
35+
assert(input[0] == 1);
36+
assert(input[1] == 2);
37+
assert(input[2] == 3);
38+
assert(input[3] == 4);
39+
40+
/* Cleanup. */
41+
clReleaseMemObject(buffer);
42+
clReleaseCommandQueue(command_queue);
43+
common_deinit(&common);
44+
return EXIT_SUCCESS;
45+
}

0 commit comments

Comments
 (0)