cf4ocl (C Framework for OpenCL)  v2.1.0
Object-oriented framework for developing and benchmarking OpenCL projects in C/C++
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ccl_device_wrapper.c
Go to the documentation of this file.
1 /*
2  * This file is part of cf4ocl (C Framework for OpenCL).
3  *
4  * cf4ocl is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation, either version 3 of the
7  * License, or (at your option) any later version.
8  *
9  * cf4ocl is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with cf4ocl. If not, see
16  * <http://www.gnu.org/licenses/>.
17  * */
18 
31 #include "ccl_device_wrapper.h"
32 #include "ccl_platform_wrapper.h"
33 #include "_ccl_abstract_wrapper.h"
34 #include "_ccl_defs.h"
35 
41 struct ccl_device {
42 
47  CCLWrapper base;
48 
49 #ifdef CL_VERSION_1_2
50 
54  GSList* subdev_arrays;
55 #endif
56 
57 };
58 
59 #ifdef CL_VERSION_1_2
60 
69 static void ccl_device_release_subdev_arrays(gpointer data) {
70 
71  /* Make sure data is not NULL. */
72  g_return_if_fail(data != NULL);
73 
74  /* Convert data to array of sub-devices. */
75  CCLDevice** subdevs = (CCLDevice**) data;
76 
77  /* Destroy sub-devices. */
78  for (cl_uint i = 0; subdevs[i] != NULL; ++i)
79  ccl_device_destroy(subdevs[i]);
80 
81  /* Destroy array holding sub-devices. */
82  g_free(subdevs);
83 }
84 
94 static void ccl_device_release_fields(CCLDevice* dev) {
95 
96  /* Make sure device wrapper object is not NULL. */
97  g_return_if_fail(dev != NULL);
98 
99  /* Release list of arrays of sub-devices. */
100  g_slist_free_full(dev->subdev_arrays,
101  ccl_device_release_subdev_arrays);
102 }
103 
104 #endif
105 
128 CCL_EXPORT
129 CCLDevice* ccl_device_new_wrap(cl_device_id device) {
130 
131  return (CCLDevice*) ccl_wrapper_new(
132  CCL_DEVICE, (void*) device, sizeof(CCLDevice));
133 
134 }
135 
144 CCL_EXPORT
146 
147 #ifdef CL_VERSION_1_2
148 
149  cl_uint ver = ccl_device_get_opencl_version(dev, NULL);
150 
151  /* Device destruction depends on device OpenCL version. */
152  if (ver >= 120) {
153 
154  /* If OpenCL >= 1.2, then pass clReleaseDevice to release
155  * device (will only matter for sub-devices). */
156  ccl_wrapper_unref((CCLWrapper*) dev, sizeof(CCLDevice),
157  (ccl_wrapper_release_fields) ccl_device_release_fields,
158  (ccl_wrapper_release_cl_object) clReleaseDevice, NULL);
159 
160  } else {
161 
162  /* If OpenCL < 1.2, don't pass OpenCL specific destructors. */
163  ccl_wrapper_unref((CCLWrapper*) dev, sizeof(CCLDevice),
164  NULL, NULL, NULL);
165  }
166 
167 #else
168 
169  ccl_wrapper_unref((CCLWrapper*) dev, sizeof(CCLDevice),
170  NULL, NULL, NULL);
171 
172 #endif
173 }
174 
192 CCL_EXPORT
194 
195  /* Make sure dev is not NULL. */
196  g_return_val_if_fail(dev != NULL, 0);
197  /* Make sure err is NULL or it is not set. */
198  g_return_val_if_fail(err == NULL || *err == NULL, 0);
199 
200  char* ver_str;
201  cl_uint ver = 0;
202 
203  /* Get version string which has the format "OpenCL x.x ..." */
204  ver_str = ccl_device_get_info_array(
205  dev, CL_DEVICE_VERSION, char*, err);
206 
207  if (ver_str != NULL) {
208  ver = /* strlen("OpenCL ") == 7 */
209  atoi(ver_str + 7) * 100 + /* Major version. */
210  atoi(ver_str + 9) * 10; /* Minor version. */
211  }
212  return ver;
213 
214 }
215 
233 CCL_EXPORT
235 
236  /* Make sure dev is not NULL. */
237  g_return_val_if_fail(dev != NULL, 0);
238  /* Make sure err is NULL or it is not set. */
239  g_return_val_if_fail(err == NULL || *err == NULL, 0);
240 
241  char* ver_str;
242  cl_uint ver = 0;
243 
244  /* Get version string which has the format "OpenCL C x.x ..." */
245  ver_str = ccl_device_get_info_array(
246  dev, CL_DEVICE_OPENCL_C_VERSION, char*, err);
247 
248  if (ver_str != NULL) {
249  ver = /* strlen("OpenCL C ") == 9 */
250  atoi(ver_str + 9) * 100 + /* Major version. */
251  atoi(ver_str + 11) * 10; /* Minor version. */
252  }
253  return ver;
254 
255 }
256 
277 CCL_EXPORT
279  const cl_device_partition_property *properties,
280  cl_uint *num_devs_ret, CCLErr** err) {
281 
282  /* Make sure device wrapper object is not NULL. */
283  g_return_val_if_fail(dev != NULL, NULL);
284 
285  /* OpenCL function return status. */
286  cl_int ocl_status;
287  /* Number of sub-devices the partition may yield. */
288  cl_uint num_devs;
289  /* Array for holding sub-devices. */
290  void** subdevs = NULL;
291 
292 #ifndef CL_VERSION_1_2
293 
294  CCL_UNUSED(properties);
295  CCL_UNUSED(ocl_status);
296  CCL_UNUSED(num_devs);
297 
298  /* If cf4ocl was not compiled with support for OpenCL >= 1.2, always throw
299  * error. */
300  ccl_if_err_create_goto(*err, CCL_ERROR, TRUE,
301  CCL_ERROR_UNSUPPORTED_OCL, error_handler,
302  "%s: Sub-device creation requires cf4ocl to be deployed with "
303  "support for OpenCL version 1.2 or newer.",
304  CCL_STRD);
305 
306 #else
307 
308  /* How many sub-devices will this partition yield? */
309  ocl_status = clCreateSubDevices(
310  ccl_device_unwrap(dev), properties, 0, NULL, &num_devs);
312  CL_SUCCESS != ocl_status, ocl_status, error_handler,
313  "%s: unable to determine how many sub-devices can be created " \
314  "(OpenCL error %d: %s).",
315  CCL_STRD, ocl_status, ccl_err(ocl_status));
316 
317  /* Create array for holding sub-devices. The last element should
318  * be NULL. */
319  subdevs = g_new0(void*, num_devs + 1);
320 
321  /* Create sub-devices. */
322  ocl_status = clCreateSubDevices(
323  ccl_device_unwrap(dev), properties, num_devs,
324  (cl_device_id*) subdevs, NULL);
326  CL_SUCCESS != ocl_status, ocl_status, error_handler,
327  "%s: unable to create sub-devices (OpenCL error %d: %s).",
328  CCL_STRD, ocl_status, ccl_err(ocl_status));
329 
330  /* Wrap sub-devices. */
331  for (cl_uint i = 0; subdevs[i] != NULL; ++i)
332  subdevs[i] = ccl_device_new_wrap(subdevs[i]);
333 
334  /* Return number of sub-devices? */
335  if (num_devs_ret != NULL) *num_devs_ret = num_devs;
336 
337  /* Add new sub-devices to list of sub-devices. */
338  dev->subdev_arrays = g_slist_prepend(dev->subdev_arrays, subdevs);
339 
340 #endif
341 
342  /* If we got here, everything is OK. */
343  g_assert(err == NULL || *err == NULL);
344  goto finish;
345 
346 error_handler:
347  /* If we got here there was an error, verify that it is so. */
348  g_assert(err == NULL || *err != NULL);
349 
350  /* An error occurred, return NULL to signal it. */
351  if (num_devs_ret != NULL) *num_devs_ret = 0;
352  if (subdevs != NULL) g_free(subdevs);
353  subdevs = NULL;
354 
355 finish:
356 
357  /* Return event. */
358  return (CCLDevice* const*) subdevs;
359 }
360 
Device object.
Definition: ccl_common.h:98
#define CCL_OCL_ERROR
Resolves to error category identifying string, in this case an error in the OpenCL library...
Definition: ccl_common.h:324
Definition of a wrapper class and its methods for OpenCL device objects.
#define ccl_if_err_create_goto(err, quark, error_condition, error_code, label, msg,...)
If error is detected (error_code != no_error_code), create an error object (CCLErr) and go to the spe...
Definition: _ccl_defs.h:91
Definition of a wrapper class and its methods for OpenCL platform objects.
Useful definitions used internally by cf4ocl.
const char * ccl_err(int code)
Convert OpenCL error code to a readable string.
Definition: ccl_errors.c:118
#define CCL_ERROR
Resolves to error category identifying string, in this case an error in cf4ocl.
Definition: ccl_common.h:320
Base class for all OpenCL wrappers.
#define ccl_device_unwrap(dev)
Get the OpenCL device_id object.
void ccl_device_destroy(CCLDevice *dev)
Decrements the reference count of the device wrapper object.
#define CCL_UNUSED(x)
Macro to avoid warning in unused variables.
Definition: ccl_common.h:86
#define ccl_device_get_info_array(dev, param_name, param_type, err)
Macro which returns an array device information value.
CCLDevice *const * ccl_device_create_subdevices(CCLDevice *dev, const cl_device_partition_property *properties, cl_uint *num_devs_ret, CCLErr **err)
Creates a NULL-terminated array of sub-devices that each reference a non-intersecting set of compute ...
cl_uint ccl_device_get_opencl_c_version(CCLDevice *dev, CCLErr **err)
Get the OpenCL C version supported by the device.
GError CCLErr
Error handling class.
Definition: ccl_common.h:291
cl_uint ccl_device_get_opencl_version(CCLDevice *dev, CCLErr **err)
Get the OpenCL version supported by the device.
Device wrapper class.
The operation is not supported by the version of the selected OpenCL platform.
Definition: ccl_common.h:311
CCLDevice * ccl_device_new_wrap(cl_device_id device)
Get the device wrapper for the given OpenCL device.