Openholo  v4.0
Open Source Digital Holographic Library
OpenCL.cpp
Go to the documentation of this file.
1 #include "OpenCL.h"
2 //#include <istream>
3 //#include <iostream>
4 //#include <string>
5 #include <sstream>
6 #include "ophPCKernel.cl"
7 #include <stdio.h>
8 
9 
10 OpenCL::OpenCL()
11 {
12  nKernel = 0;
13  nPlatforms = 0;
14  device_id = nullptr;
15  platform = nullptr;
16  item = nullptr;
17  kernel_source = nullptr;
18  program = nullptr;
19  kernel = nullptr;
20  init();
21 }
22 
23 
24 OpenCL::~OpenCL()
25 {
26  for (int i = 0; i < nKernel; i++)
27  {
28  clReleaseProgram(program[i]);
29  clReleaseKernel(kernel[i]);
30  }
31  clReleaseCommandQueue(commands);
32  clReleaseContext(context);
33  delete[] item;
34  delete[] kernel;
35  delete[] platform;
36  item = nullptr;
37  kernel = nullptr;
38  platform = nullptr;
39 }
40 
41 const char *err_code(cl_int err_in)
42 {
43  switch (err_in) {
44  case CL_SUCCESS:
45  return (char*)"CL_SUCCESS";
46  case CL_DEVICE_NOT_FOUND:
47  return (char*)"CL_DEVICE_NOT_FOUND";
48  case CL_DEVICE_NOT_AVAILABLE:
49  return (char*)"CL_DEVICE_NOT_AVAILABLE";
50  case CL_COMPILER_NOT_AVAILABLE:
51  return (char*)"CL_COMPILER_NOT_AVAILABLE";
52  case CL_MEM_OBJECT_ALLOCATION_FAILURE:
53  return (char*)"CL_MEM_OBJECT_ALLOCATION_FAILURE";
54  case CL_OUT_OF_RESOURCES:
55  return (char*)"CL_OUT_OF_RESOURCES";
56  case CL_OUT_OF_HOST_MEMORY:
57  return (char*)"CL_OUT_OF_HOST_MEMORY";
58  case CL_PROFILING_INFO_NOT_AVAILABLE:
59  return (char*)"CL_PROFILING_INFO_NOT_AVAILABLE";
60  case CL_MEM_COPY_OVERLAP:
61  return (char*)"CL_MEM_COPY_OVERLAP";
62  case CL_IMAGE_FORMAT_MISMATCH:
63  return (char*)"CL_IMAGE_FORMAT_MISMATCH";
64  case CL_IMAGE_FORMAT_NOT_SUPPORTED:
65  return (char*)"CL_IMAGE_FORMAT_NOT_SUPPORTED";
66  case CL_BUILD_PROGRAM_FAILURE:
67  return (char*)"CL_BUILD_PROGRAM_FAILURE";
68  case CL_MAP_FAILURE:
69  return (char*)"CL_MAP_FAILURE";
70  case CL_MISALIGNED_SUB_BUFFER_OFFSET:
71  return (char*)"CL_MISALIGNED_SUB_BUFFER_OFFSET";
72  case CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST:
73  return (char*)"CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST";
74  case CL_INVALID_VALUE:
75  return (char*)"CL_INVALID_VALUE";
76  case CL_INVALID_DEVICE_TYPE:
77  return (char*)"CL_INVALID_DEVICE_TYPE";
78  case CL_INVALID_PLATFORM:
79  return (char*)"CL_INVALID_PLATFORM";
80  case CL_INVALID_DEVICE:
81  return (char*)"CL_INVALID_DEVICE";
82  case CL_INVALID_CONTEXT:
83  return (char*)"CL_INVALID_CONTEXT";
84  case CL_INVALID_QUEUE_PROPERTIES:
85  return (char*)"CL_INVALID_QUEUE_PROPERTIES";
86  case CL_INVALID_COMMAND_QUEUE:
87  return (char*)"CL_INVALID_COMMAND_QUEUE";
88  case CL_INVALID_HOST_PTR:
89  return (char*)"CL_INVALID_HOST_PTR";
90  case CL_INVALID_MEM_OBJECT:
91  return (char*)"CL_INVALID_MEM_OBJECT";
92  case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
93  return (char*)"CL_INVALID_IMAGE_FORMAT_DESCRIPTOR";
94  case CL_INVALID_IMAGE_SIZE:
95  return (char*)"CL_INVALID_IMAGE_SIZE";
96  case CL_INVALID_SAMPLER:
97  return (char*)"CL_INVALID_SAMPLER";
98  case CL_INVALID_BINARY:
99  return (char*)"CL_INVALID_BINARY";
100  case CL_INVALID_BUILD_OPTIONS:
101  return (char*)"CL_INVALID_BUILD_OPTIONS";
102  case CL_INVALID_PROGRAM:
103  return (char*)"CL_INVALID_PROGRAM";
104  case CL_INVALID_PROGRAM_EXECUTABLE:
105  return (char*)"CL_INVALID_PROGRAM_EXECUTABLE";
106  case CL_INVALID_KERNEL_NAME:
107  return (char*)"CL_INVALID_KERNEL_NAME";
108  case CL_INVALID_KERNEL_DEFINITION:
109  return (char*)"CL_INVALID_KERNEL_DEFINITION";
110  case CL_INVALID_KERNEL:
111  return (char*)"CL_INVALID_KERNEL";
112  case CL_INVALID_ARG_INDEX:
113  return (char*)"CL_INVALID_ARG_INDEX";
114  case CL_INVALID_ARG_VALUE:
115  return (char*)"CL_INVALID_ARG_VALUE";
116  case CL_INVALID_ARG_SIZE:
117  return (char*)"CL_INVALID_ARG_SIZE";
118  case CL_INVALID_KERNEL_ARGS:
119  return (char*)"CL_INVALID_KERNEL_ARGS";
120  case CL_INVALID_WORK_DIMENSION:
121  return (char*)"CL_INVALID_WORK_DIMENSION";
122  case CL_INVALID_WORK_GROUP_SIZE:
123  return (char*)"CL_INVALID_WORK_GROUP_SIZE";
124  case CL_INVALID_WORK_ITEM_SIZE:
125  return (char*)"CL_INVALID_WORK_ITEM_SIZE";
126  case CL_INVALID_GLOBAL_OFFSET:
127  return (char*)"CL_INVALID_GLOBAL_OFFSET";
128  case CL_INVALID_EVENT_WAIT_LIST:
129  return (char*)"CL_INVALID_EVENT_WAIT_LIST";
130  case CL_INVALID_EVENT:
131  return (char*)"CL_INVALID_EVENT";
132  case CL_INVALID_OPERATION:
133  return (char*)"CL_INVALID_OPERATION";
134  case CL_INVALID_GL_OBJECT:
135  return (char*)"CL_INVALID_GL_OBJECT";
136  case CL_INVALID_BUFFER_SIZE:
137  return (char*)"CL_INVALID_BUFFER_SIZE";
138  case CL_INVALID_MIP_LEVEL:
139  return (char*)"CL_INVALID_MIP_LEVEL";
140  case CL_INVALID_GLOBAL_WORK_SIZE:
141  return (char*)"CL_INVALID_GLOBAL_WORK_SIZE";
142  case CL_INVALID_PROPERTY:
143  return (char*)"CL_INVALID_PROPERTY";
144 
145  default:
146  return (char*)"UNKNOWN ERROR";
147  }
148 }
149 
150 void OpenCL::errorCheck(cl_int err, const char *operation, char *filename, int line)
151 {
152  if (err != CL_SUCCESS)
153  {
154  fprintf(stderr, "Error during operation '%s', ", operation);
155  fprintf(stderr, "in '%s' on line %d\n", filename, line);
156  fprintf(stderr, "Error code was \"%s\" (%d)\n", err_code(err), err);
157  exit(EXIT_FAILURE);
158  }
159 }
160 
161 
163 {
164  cl_int nErr;
165  nKernel = sizeof(pKernel) / sizeof(pKernel[0]);
166 
167  // Create the compute kernel from the program
168  kernel = new cl_kernel[nKernel];
169  program = new cl_program[nKernel];
170 
171 
172  char kname[MAX_KERNEL_NAME] = { 0, };
173  size_t workSize;
174 
175  for (cl_uint i = 0; i < nKernel; i++) {
176  kernel_source = const_cast<char*>(pKernel[i]);
177 
178  // Create the compute program from the source buffer
179  program[i] = clCreateProgramWithSource(context, 1, (const char**)&kernel_source, nullptr, &nErr);
180  checkError(nErr, "Creating program");
181 
182  // Build the program
183  nErr = clBuildProgram(program[i], 1, &device_id, nullptr, nullptr, nullptr);
184  if (nErr != CL_SUCCESS) {
185  size_t len;
186  clGetProgramBuildInfo(program[i], device_id, CL_PROGRAM_BUILD_LOG, 0, nullptr, &len);
187  char* buf = (char*)calloc(len + 1, sizeof(char));
188  clGetProgramBuildInfo(program[i], device_id, CL_PROGRAM_BUILD_LOG, len + 1, buf, nullptr);
189  LOG("\n=> %s\n", buf);
190  free(buf);
191  return false;
192  }
193 
194  getKernelName(i, kname);
195  kernel[i] = clCreateKernel(program[i], kname, &nErr);
196 
197  LOG("kernel[%d] : %s\n", i, kname);
198  //nErr = clEnqueueNDRangeKernel(commands, kernel[i], 2, nullptr, global, local, 0, nullptr, nullptr);
199 
200  nErr = clGetKernelWorkGroupInfo(kernel[i], device_id, CL_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE,
201  sizeof(size_t), &workSize, nullptr);
202  LOG("%d] => Work Group Size: %d\n", i, workSize);
203  nErr = clGetKernelWorkGroupInfo(kernel[i], device_id, CL_KERNEL_WORK_GROUP_SIZE,
204  sizeof(size_t), &workSize, nullptr);
205  work_size = workSize;
206 
207  LOG("%d] => Max Work Group Size: %d\n", i, workSize);
208  }
209  checkError(nErr, "Creating kernel");
210  return true;
211 }
212 
213 void OpenCL::getKernelName(cl_int iKernel, char *kernel)
214 {
215  if (pKernel == nullptr) return;
216 
217  using namespace std;
218  stringstream ss(pKernel[iKernel]);
219  string item;
220  size_t found;
221  bool bFound = false;
222  memset(kernel, 0, MAX_KERNEL_NAME);
223 
224  while (getline(ss, item, '\n')) {
225  if (item.find("__kernel") != string::npos) {
226  ss.seekg(-item.length(), ios_base::cur);
227  while (getline(ss, item, ' ')) {
228  if ((found = item.find("(")) != string::npos) {
229  item = item.substr(0, found);
230  bFound = true;
231  break;
232  }
233  }
234  }
235  if (bFound) break;
236  }
237  if (!bFound) item = "Not Found";
238  memcpy(kernel, item.c_str(), item.length());
239 }
240 
241 
242 bool OpenCL::printDevInfo(cl_device_id device_id)
243 {
244  int nErr;
245  cl_device_id id = nullptr;
246  cl_device_type type;
247  cl_char vendorName[1024] = { 0, };
248  cl_char deviceName[1024] = { 0, };
249 
250  nErr = clGetDeviceInfo(device_id, CL_DEVICE_NAME, sizeof(deviceName), &deviceName, nullptr);
251  if (nErr != CL_SUCCESS) {
252  LOG("Error: Failed to access device name!\n");
253  return false;
254  }
255 
256  LOG("Device Name: %s\n", deviceName);
257 
258  nErr = clGetDeviceInfo(device_id, CL_DEVICE_TYPE, sizeof(type), &type, nullptr);
259  if (nErr != CL_SUCCESS) {
260  LOG("Error: Failed to access device type information!\n");
261  return false;
262  }
263  LOG("Device Type: %s\n", type == CL_DEVICE_TYPE_GPU ? "GPU" : "CPU");
264 
265  nErr = clGetDeviceInfo(device_id, CL_DEVICE_VENDOR, sizeof(vendorName), &vendorName, nullptr);
266  if (nErr != CL_SUCCESS) {
267  LOG("Error: Failed to access device vendor name!\n");
268  return false;
269  }
270  LOG("Vendor Name: %s\n", vendorName);
271 
272  nErr = clGetDeviceInfo(device_id, CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &nUnits, nullptr);
273  if (nErr != CL_SUCCESS) {
274  LOG("Error: Failed to access device number of compute units!\n");
275  return false;
276  }
277  LOG("Max Units: %d\n", nUnits);
278 
279  nErr = clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &group, nullptr);
280  if (nErr != CL_SUCCESS) {
281  LOG("Error: Failed to access device work group size!\n");
282  return false;
283  }
284  LOG("Max Work Group Size: %d\n", group);
285 
286 
287  nErr = clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(cl_uint), &nDimensions, nullptr);
288  if (nErr != CL_SUCCESS) {
289  LOG("Error: Failed to access device number of dimensions!\n");
290  return false;
291  }
292  LOG("Max Work Item Deimesions: %d\n", nDimensions);
293 
294  if (item != nullptr) {
295  delete[] item;
296  item = nullptr;
297  }
298  item = new size_t[nDimensions];
299  nErr = clGetDeviceInfo(device_id, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(size_t) * nDimensions, item, nullptr);
300  if (nErr != CL_SUCCESS) {
301  LOG("Error: Failed to access device work item size!\n");
302  return false;
303  }
304  LOG("Max Work Item Size: [ ");
305  for (int i = 0; i < nDimensions; i++) {
306  LOG("%d", item[i]);
307  if (i != nDimensions - 1)
308  LOG(" / ");
309  }
310  LOG(" ]\n");
311  return true;
312 }
313 
314 bool OpenCL::init()
315 {
316  int nErr;
317 
318  nErr = clGetPlatformIDs(0, nullptr, &nPlatforms);
319  checkError(nErr, "Finding platforms");
320 
321  if (nPlatforms == 0) return false;
322 
323  if(platform == nullptr)
324  platform = new cl_platform_id[nPlatforms];
325  ZeroMemory(platform, nPlatforms);
326 
327  nErr = clGetPlatformIDs(nPlatforms, platform, nullptr);
328  checkError(nErr, "Getting platforms");
329 
330  // Secure a GPU
331  for (int i = 0; i < nPlatforms; i++)
332  {
333  nErr = clGetDeviceIDs(platform[i], CL_DEVICE_TYPE_GPU, 1, &device_id, NULL);
334  if (nErr == CL_SUCCESS) break;
335  }
336 
337  if (device_id == nullptr) checkError(nErr, "Finding a device");
338 
339  printDevInfo(device_id);
340 
341  // Create a compute context
342  context = clCreateContext(nullptr, 1, &device_id, nullptr, nullptr, &nErr);
343  checkError(nErr, "Creating context");
344 
345  // Create a command queue
346  commands = clCreateCommandQueue(context, device_id, 0, &nErr);
347  checkError(nErr, "Creating command queue");
348 
349 
350  return true;
351 }
void errorCheck(cl_int err, const char *operation, char *filename, int line)
Definition: OpenCL.cpp:150
bool LoadKernel()
Definition: OpenCL.cpp:162
const char * err_code(cl_int err_in)
Definition: OpenCL.cpp:41
#define MAX_KERNEL_NAME
Definition: OpenCL.h:6
#define checkError(E, S)
Definition: OpenCL.h:7