Created
May 16, 2018 08:45
-
-
Save bit-hack/a3d2c3f55f679194528ef30a7c25f6c0 to your computer and use it in GitHub Desktop.
opencl test
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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