Skip to content

Instantly share code, notes, and snippets.

@bit-hack
Created May 16, 2018 08:45
Show Gist options
  • Save bit-hack/a3d2c3f55f679194528ef30a7c25f6c0 to your computer and use it in GitHub Desktop.
Save bit-hack/a3d2c3f55f679194528ef30a7c25f6c0 to your computer and use it in GitHub Desktop.
opencl test
#include <CL/cl.h>
#include <array>
const char *source = R"(
kernel void mult(global float *data) {
const int id = get_global_id(0);
data[id] *= 2.f;
}
)";
struct cl_impl_t {
bool init();
auto &get_data() {
return data;
}
bool run() {
if (!write_buffers()) {
return false;
}
if (!run_kernel()) {
return false;
}
if (!read_buffers()) {
return false;
}
if (!sync()) {
return false;
}
return true;
}
protected:
bool create_kernel();
bool create_buffers();
bool write_buffers();
bool read_buffers();
bool run_kernel();
bool sync();
std::array<float, 512> data;
std::array<cl_platform_id, 32> platforms;
cl_context context;
cl_device_id device;
cl_command_queue queue;
cl_program program;
cl_kernel kernel;
cl_mem buffer;
};
bool cl_impl_t::init() {
cl_int ret = CL_SUCCESS;
cl_uint num_platforms = 0;
ret = clGetPlatformIDs(
platforms.size(),
platforms.data(),
&num_platforms);
if (CL_SUCCESS != ret)
return false;
ret = clGetDeviceIDs(
platforms[0], // platform selection
CL_DEVICE_TYPE_CPU,
1, // number of devices
&device, // device pointer
nullptr);
if (CL_SUCCESS != ret)
return false;
context = clCreateContext(
nullptr,
1,
&device,
nullptr,
nullptr,
nullptr);
if (!context)
return false;
queue = clCreateCommandQueue(
context,
device,
cl_command_queue_properties(0),
nullptr);
if (!queue)
return false;
if (!create_kernel()) {
return false;
}
if (!create_buffers()) {
return false;
}
return true;
}
bool cl_impl_t::create_kernel() {
cl_int ret = CL_SUCCESS;
program = clCreateProgramWithSource(
context,
1, // number of source buffers
&source, // source code
nullptr, // source length
nullptr); // error code ret
if (!program)
return false;
ret = clBuildProgram(
program,
0, // num devices
nullptr, // device list
nullptr, // options
nullptr, // notify callback
nullptr); // user data
kernel = clCreateKernel(
program,
"mult", // kernel name
nullptr);
if (!kernel)
return false;
return true;
}
bool cl_impl_t::create_buffers() {
cl_int ret = CL_SUCCESS;
buffer = clCreateBuffer(
context,
CL_MEM_READ_WRITE, // memory usage flags
data.size() * sizeof(float), // buffer size in bytes
nullptr,
nullptr);
if (!buffer)
return false;
return true;
}
bool cl_impl_t::write_buffers() {
cl_int ret = CL_SUCCESS;
ret = clEnqueueWriteBuffer(
queue,
buffer,
CL_FALSE,
0,
data.size() * sizeof(float), // buffer size in bytes
data.data(), // buffer contents
0,
nullptr,
nullptr);
if (CL_SUCCESS != ret)
return false;
return true;
}
bool cl_impl_t::run_kernel() {
cl_int ret = CL_SUCCESS;
const size_t dimensions[] = {data.size(), 0, 0};
ret = clSetKernelArg(
kernel, // kernel
0, // argument index
sizeof(buffer), // size of the memory object
&buffer); // pointer to memory object
if (CL_SUCCESS != ret)
return false;
ret = clEnqueueNDRangeKernel(
queue,
kernel,
1, // work dimensions
nullptr, // global work offset
dimensions, // global work size
nullptr, // local work size
0, // num events
nullptr, // event wait list
nullptr); // event
if (CL_SUCCESS != ret)
return false;
return true;
}
bool cl_impl_t::read_buffers() {
cl_int ret = CL_SUCCESS;
ret = clEnqueueReadBuffer(
queue,
buffer,
CL_FALSE,
0,
sizeof(float) * data.size(), // buffer size in bytes
data.data(), // destination
0,
nullptr,
nullptr);
if (CL_SUCCESS != ret)
return false;
return true;
}
bool cl_impl_t::sync() {
cl_int ret = CL_SUCCESS;
ret = clFinish(queue);
if (CL_SUCCESS != ret)
return false;
return true;
}
int main() {
cl_impl_t cl;
if (!cl.init()) {
return 1;
}
auto &data = cl.get_data();
for (uint32_t i = 0; i < data.size(); ++i)
data[i] = float(i);
if (!cl.run()) {
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment