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_selector.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 
30 #include "ccl_device_selector.h"
31 #include "_ccl_defs.h"
32 
38 typedef void (*ccl_devsel_fp)(void);
39 
44 typedef struct ccl_devsel_filter {
45 
50  ccl_devsel_fp function;
51 
56  void* data;
57 
63 
65 
78 static void ccl_devsel_add_filter(CCLDevSelFilters* filters,
79  ccl_devsel_fp function, void* data, CCLDevSelFilterType type) {
80 
81  /* Initialize filters if required. */
82  if (*filters == NULL)
83  *filters = g_ptr_array_new();
84 
85  /* Allocate space for new filter. */
86  CCLDevSelFilter* filter = g_slice_new0(CCLDevSelFilter);
87 
88  /* Set filter function, filter data and type. */
89  filter->function = function;
90  filter->data = data;
91  filter->type = type;
92 
93  /* Add filter to filters array. */
94  g_ptr_array_add(*filters, filter);
95 
96 }
97 
111 static gchar** ccl_get_device_strings_from_array(
112  CCLDevSelDevices devices, CCLErr** err) {
113 
114  /* Make sure err is NULL or it is not set. */
115  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
116 
117  /* Make sure devices array is not null. */
118  g_return_val_if_fail(devices != NULL, NULL);
119 
120  /* Internal error handling object. */
121  CCLErr* err_internal = NULL;
122 
123  /* Array of strings. */
124  gchar** dev_strings;
125 
126  /* Initialize array of strings. */
127  dev_strings = g_new0(gchar*, devices->len + 1);
128 
129  /* Create array of strings describing devices. */
130  for (guint i = 0; i < devices->len; i++) {
131 
132  /* Get device name. */
133  gchar* name = ccl_device_get_info_array(
134  devices->pdata[i], CL_DEVICE_NAME, char*, &err_internal);
135  ccl_if_err_propagate_goto(err, err_internal, error_handler);
136 
137  /* Get device platform wrapper. */
139  devices->pdata[i], &err_internal);
140  ccl_if_err_propagate_goto(err, err_internal, error_handler);
141 
142  /* Get platform name. */
143  gchar* platf_name = ccl_platform_get_info_string(
144  platf_wrap, CL_PLATFORM_NAME, &err_internal);
145  ccl_if_err_propagate_goto(err, err_internal, error_handler);
146 
147  /* Put info in string. */
148  dev_strings[i] = g_strdup_printf(
149  "%d. %s [%s]", i, name, platf_name);
150 
151  /* Release platform wrapper. */
152  ccl_platform_destroy(platf_wrap);
153 
154  }
155 
156  /* If we got here, everything is OK. */
157  g_assert(err == NULL || *err == NULL);
158  goto finish;
159 
160 error_handler:
161  /* If we got here there was an error, verify that it is so. */
162  g_assert(err == NULL || *err != NULL);
163 
164  /* Free what was built of the array of strings. */
165  g_strfreev(dev_strings);
166  dev_strings = NULL;
167 
168 finish:
169 
170  /* Return array of strings describing devices. */
171  return dev_strings;
172 }
173 
186 static void ccl_devsel_dep_menu_list(CCLDevSelDevices devices,
187  cl_int selected, CCLErr** err) {
188 
189  /* Make sure err is NULL or it is not set. */
190  g_return_if_fail(err == NULL || *err == NULL);
191 
192  /* Make sure devices array is not null. */
193  g_return_if_fail(devices != NULL);
194 
195  /* Internal error handling object. */
196  CCLErr* err_internal = NULL;
197 
198  /* Array of device description strings. */
199  gchar** dev_strings;
200 
201  /* Get device description strings. */
202  dev_strings = ccl_get_device_strings_from_array(
203  devices, &err_internal);
204  ccl_if_err_propagate_goto(err, err_internal, error_handler);
205 
206  g_printf("\n");
207 
208  /* Print each device description string. */
209  for (cl_int i = 0; i < (cl_int) devices->len; i++) {
210 
211  /* Current device string. */
212  gchar* sel_str;
213 
214  /* If a device is pre-selected, show it. */
215  sel_str = " ";
216  if (i == selected) {
217  sel_str = "(*)";
218  }
219 
220  /* Print string. */
221  g_printf(" %s %s\n", sel_str, dev_strings[i]);
222 
223  }
224 
225  /* If we got here, everything is OK. */
226  g_assert(err == NULL || *err == NULL);
227  goto finish;
228 
229 error_handler:
230  /* If we got here there was an error, verify that it is so. */
231  g_assert(err == NULL || *err != NULL);
232 
233 finish:
234 
235  /* Free what the array of device description strings. */
236  g_strfreev(dev_strings);
237 
238 }
239 
251 static cl_int ccl_devsel_dep_menu_query(CCLDevSelDevices devices,
252  CCLErr** err) {
253 
254  /* Make sure err is NULL or it is not set. */
255  g_return_val_if_fail(err == NULL || *err == NULL, -1);
256  /* Make sure devices array is not null. */
257  g_return_val_if_fail(devices != NULL, -1);
258 
259  /* Index of selected device. */
260  cl_int index = -1;
261  /* Number of results read from user input. */
262  int result;
263  /* Internal error handler. */
264  CCLErr* err_internal = NULL;
265 
266  /* Print available devices */
267  g_printf("\nList of available OpenCL devices:\n");
268  ccl_devsel_dep_menu_list(devices, -1, &err_internal);
269  ccl_if_err_propagate_goto(err, err_internal, error_handler);
270 
271  /* If only one device exists, return that one. */
272  if (devices->len == 1) {
273  index = 0;
274  } else {
275  /* Otherwise, query the user. */
276  do {
277  g_printf("\n (?) Select device (0-%d) > ", devices->len - 1);
278  fflush(stdout);
279  result = scanf("%u", &index);
280  /* Clean keyboard buffer */
281  int c;
282  do { c = getchar(); } while (c != '\n' && c != EOF);
283  /* Check if result is Ok and break the loop if so */
284  if (1 == result) {
285  if ((index >= 0) && (index < (cl_int) devices->len))
286  break;
287  }
288  /* Result not Ok, print error message */
289  g_printf(" (!) Invalid choice, please insert a value " \
290  "between 0 and %u.\n", devices->len - 1);
291  } while (1);
292  }
293 
294  /* If we got here, everything is OK. */
295  g_assert(err == NULL || *err == NULL);
296  goto finish;
297 
298 error_handler:
299  /* If we got here there was an error, verify that it is so. */
300  g_assert(err == NULL || *err != NULL);
301  index = -1;
302 
303 finish:
304 
305  /* Return device index. */
306  return index;
307 
308 }
309 
329 CCL_EXPORT
331 
332  /* Make sure err is NULL or it is not set. */
333  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
334 
335  /* Platforms wrapper object. */
336  CCLPlatforms* platforms = NULL;
337 
338  /* Platform wrapper object. */
339  CCLPlatform* platform = NULL;
340 
341  /* Device wrapper object. */
342  CCLDevice* device = NULL;
343 
344  /* Array of device wrapper objects. Devices will be selected from
345  * this array. */
346  GPtrArray* devices = NULL;
347 
348  /* Number of platforms. */
349  guint num_platfs;
350 
351  /* Internal error handling object. */
352  CCLErr* err_internal = NULL;
353 
354  /* Get all OpenCL platforms in system wrapped in a CCLPlatforms
355  * object. */
356  platforms = ccl_platforms_new(&err_internal);
357  ccl_if_err_propagate_goto(err, err_internal, error_handler);
358 
359  /* Determine number of platforms. */
360  num_platfs = ccl_platforms_count(platforms);
361 
362  /* Create array of device wrapper objects. */
363  devices = g_ptr_array_new_with_free_func(
364  (GDestroyNotify) ccl_device_destroy);
365 
366  /* Cycle through OpenCL platforms. */
367  for (guint i = 0; i < num_platfs; i++) {
368 
369  /* Get next platform wrapper. */
370  platform = ccl_platforms_get(platforms, i);
371 
372  /* Get number of devices in current platform.*/
373  guint num_devices = ccl_platform_get_num_devices(
374  platform, &err_internal);
375 
376  /* Is this a platform without devices? */
377  if ((err_internal) && (err_internal->domain == CCL_OCL_ERROR) &&
378  (err_internal->code == CL_DEVICE_NOT_FOUND)) {
379 
380  /* Clear "device not found" error. */
381  g_clear_error(&err_internal);
382 
383  /* Skip this platform. */
384  continue;
385  }
386  ccl_if_err_propagate_goto(err, err_internal, error_handler);
387 
388  /* Cycle through devices in current platform. */
389  for (guint j = 0; j < num_devices; j++) {
390 
391  /* Get current device wrapper. */
392  device = ccl_platform_get_device(platform, j, &err_internal);
393  ccl_if_err_propagate_goto(err, err_internal, error_handler);
394 
395  /* Add device wrapper to array of device wrapper objects. */
396  g_ptr_array_add(devices, (gpointer) device);
397 
398  /* Update device reference (because it is kept also in
399  * the array of device wrapper objects). */
400  ccl_device_ref(device);
401 
402  }
403 
404  }
405 
406  /* If we got here, everything is OK. */
407  g_assert(err == NULL || *err == NULL);
408  goto finish;
409 
410 error_handler:
411  /* If we got here there was an error, verify that it is so. */
412  g_assert(err == NULL || *err != NULL);
413 
414 finish:
415 
416  /* Free platforms wrapper object. */
417  if (platforms != NULL) ccl_platforms_destroy(platforms);
418 
419  /* Return the selected devices. */
420  return devices;
421 
422 }
423 
433 CCL_EXPORT
435  g_ptr_array_free(devices, TRUE);
436 }
437 
450 CCL_EXPORT
452 
453  /* Make sure err is NULL or it is not set. */
454  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
455 
456  /* Internal error handling object. */
457  CCLErr* err_internal = NULL;
458 
459  /* Array of devices. */
460  CCLDevSelDevices devices = NULL;
461 
462  /* Array of strings. */
463  gchar** dev_strings = NULL;
464 
465  /* Get all devices present in the system. */
466  devices = ccl_devsel_devices_new(&err_internal);
467  ccl_if_err_propagate_goto(err, err_internal, error_handler);
468 
469  /* Get the array of strings describing the devices. */
470  dev_strings = ccl_get_device_strings_from_array(
471  devices, &err_internal);
472  ccl_if_err_propagate_goto(err, err_internal, error_handler);
473 
474  /* If we got here, everything is OK. */
475  g_assert(err == NULL || *err == NULL);
476  goto finish;
477 
478 error_handler:
479  /* If we got here there was an error, verify that it is so. */
480  g_assert(err == NULL || *err != NULL);
481 
482  /* Free what was built of the array of strings. */
483  g_strfreev(dev_strings);
484  dev_strings = NULL;
485 
486 finish:
487 
488  /* Destroy array of devices. */
489  g_ptr_array_free(devices, CL_TRUE);
490 
491  /* Return array of strings describing devices. */
492  return dev_strings;
493 
494 }
495 
503 CCL_EXPORT
505 
506  /* Make sure err is NULL or it is not set. */
507  g_return_if_fail(err == NULL || *err == NULL);
508 
509  /* Internal error handling object. */
510  CCLErr* err_internal = NULL;
511 
512  /* Array of strings. */
513  gchar** dev_strings = NULL;
514 
515  /* Get the array of strings describing the devices. */
516  dev_strings = ccl_devsel_get_device_strings(&err_internal);
517  ccl_if_err_propagate_goto(err, err_internal, error_handler);
518 
519  /* Print device list to stdout. */
520  for (guint i = 0; dev_strings[i] != NULL; ++i) {
521  g_printf("%s\n", dev_strings[i]);
522  }
523 
524  /* If we got here, everything is OK. */
525  g_assert(err == NULL || *err == NULL);
526  goto finish;
527 
528 error_handler:
529 
530  /* If we got here there was an error, verify that it is so. */
531  g_assert(err == NULL || *err != NULL);
532 
533 finish:
534 
535  /* Free array of strings. */
536  g_strfreev(dev_strings);
537 
538 }
539 
547 CCL_EXPORT
549  CCLDevSelFilters* filters, ccl_devsel_indep filter, void* data) {
550 
551  ccl_devsel_add_filter(
552  filters, (ccl_devsel_fp) filter, data, CCL_DEVSEL_INDEP);
553 }
554 
562 CCL_EXPORT
564  CCLDevSelFilters* filters, ccl_devsel_dep filter, void* data) {
565 
566  ccl_devsel_add_filter(
567  filters, (ccl_devsel_fp) filter, data, CCL_DEVSEL_DEP);
568 }
569 
584  CCLDevSelFilters* filters, CCLErr **err) {
585 
586  /* Make sure filters is not NULL. */
587  g_return_val_if_fail(filters != NULL, NULL);
588 
589  /* Make sure err is NULL or it is not set. */
590  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
591 
592  /* Internal error handling object. */
593  CCLErr* err_internal = NULL;
594 
595  /* Array of devices. */
596  CCLDevSelDevices devices;
597 
598  /* Get all devices present in the system. */
599  devices = ccl_devsel_devices_new(&err_internal);
600  ccl_if_err_propagate_goto(err, err_internal, error_handler);
601 
602  /* *** Filter devices. *** */
603 
604  /* Cycle through all filters. */
605  for (guint i = 0; i < (*filters)->len; i++) {
606 
607  /* If there are no more devices left, get out... */
608  if (devices->len == 0) break;
609 
610  /* Get current filter. */
611  CCLDevSelFilter* curr_filter = g_ptr_array_index(*filters, i);
612 
613  /* Check type of filter, proceed accordingly. */
614  if (curr_filter->type == CCL_DEVSEL_DEP) {
615 
616  /* It's a dependent filter.*/
617  devices = ((ccl_devsel_dep) (curr_filter->function))(
618  devices, curr_filter->data, &err_internal);
619  ccl_if_err_propagate_goto(err, err_internal, error_handler);
620 
621  } else {
622  /* It's an independent filter. */
623 
624  /* Cycle through all devices. */
625  for (guint j = 0; j < devices->len; j++) {
626 
627  /* Get current device wrapper. */
628  CCLDevice* curr_device =
629  (CCLDevice*) g_ptr_array_index(devices, j);
630 
631  /* Check if current device is accepted by current
632  * filter. */
633  cl_bool pass =
634  ((ccl_devsel_indep) curr_filter->function)(
635  curr_device, curr_filter->data, &err_internal);
637  err, err_internal, error_handler);
638 
639  /* If current device didn't pass current filter... */
640  if (!pass) {
641 
642  /* Remove device wrapper from device wrapper array. */
643  g_ptr_array_remove_index(devices, j);
644 
645  /* Force device index decrement, because next device to
646  * be checked will be in this index. */
647  j--;
648 
649  }
650  }
651  }
652  }
653 
654  /* If we got here, everything is OK. */
655  g_assert(err == NULL || *err == NULL);
656  goto finish;
657 
658 error_handler:
659  /* If we got here there was an error, verify that it is so. */
660  g_assert(err == NULL || *err != NULL);
661 
662 finish:
663 
664  /* Free individual filters. */
665  for (guint i = 0; i < (*filters)->len; i++)
666  g_slice_free(CCLDevSelFilter, g_ptr_array_index(*filters, i));
667 
668  /* Free filter array. */
669  g_ptr_array_free(*filters, CL_TRUE);
670 
671  /* Set filters to NULL, so variable can be reused by client. */
672  *filters = NULL;
673 
674  /* Return the selected devices. */
675  return devices;
676 
677 }
678 
697 CCL_EXPORT
699  CCLDevice* dev, void* data, CCLErr **err) {
700 
701  /* Make sure dev is not NULL. */
702  g_return_val_if_fail(dev != NULL, CL_FALSE);
703  /* Make sure err is NULL or it is not set. */
704  g_return_val_if_fail(err == NULL || *err == NULL, CL_FALSE);
705 
706  /* Internal error object. */
707  CCLErr* err_internal = NULL;
708 
709  /* Device type. */
710  cl_device_type type = CL_DEVICE_TYPE_DEFAULT;
711  /* Device type to check for. */
712  cl_device_type type_to_check = CL_DEVICE_TYPE_DEFAULT;
713 
714  /* Make sure data is not NULL. */
715  ccl_if_err_create_goto(*err, CCL_ERROR, data == NULL,
716  CCL_ERROR_INVALID_DATA, error_handler,
717  "%s: invalid filter data", CCL_STRD);
718 
719  /* Get type to check for. */
720  type_to_check = *((cl_device_type*) data);
721 
722  /* Get device type. */
724  dev, CL_DEVICE_TYPE, cl_device_type, &err_internal);
725  ccl_if_err_propagate_goto(err, err_internal, error_handler);
726 
727  /* If we got here, everything is OK. */
728  g_assert(err == NULL || *err == NULL);
729  goto finish;
730 
731 error_handler:
732  /* If we got here there was an error, verify that it is so. */
733  g_assert(err == NULL || *err != NULL);
734 
735 finish:
736 
737  /* Return the selected devices. */
738  return (cl_bool) (type & type_to_check);
739 }
740 
750 CCL_EXPORT
752  CCLDevice* dev, void *data, CCLErr **err) {
753 
754  /* Set device type to GPU. */
755  cl_device_type type_to_check = CL_DEVICE_TYPE_GPU;
756 
757  /* Data not used, ignore compiler warnings. */
758  CCL_UNUSED(data);
759 
760  /* Return result. */
761  return ccl_devsel_indep_type(dev, (void*) &type_to_check, err);
762 
763 }
764 
774 CCL_EXPORT
776  CCLDevice* dev, void *data, CCLErr **err) {
777 
778  /* Set device type to CPU. */
779  cl_device_type type_to_check = CL_DEVICE_TYPE_CPU;
780 
781  /* Data not used, ignore compiler warnings. */
782  CCL_UNUSED(data);
783 
784  /* Return result. */
785  return ccl_devsel_indep_type(dev, (void*) &type_to_check, err);
786 
787 }
788 
799 CCL_EXPORT
801  CCLDevice* dev, void *data, CCLErr **err) {
802 
803  /* Set device type to Accelerator. */
804  cl_device_type type_to_check = CL_DEVICE_TYPE_ACCELERATOR;
805 
806  /* Data not used, ignore compiler warnings. */
807  CCL_UNUSED(data);
808 
809  /* Return result. */
810  return ccl_devsel_indep_type(dev, (void*) &type_to_check, err);
811 
812 }
813 
824 CCL_EXPORT
826  CCLDevice* dev, void *data, CCLErr **err) {
827 
828  /* Make sure device is not NULL. */
829  g_return_val_if_fail(dev != NULL, CL_FALSE);
830  /* Make sure err is NULL or it is not set. */
831  g_return_val_if_fail(err == NULL || *err == NULL, CL_FALSE);
832 
833  /* Internal error object. */
834  CCLErr* err_internal = NULL;
835 
836  /* Return value, i.e., flag indicating if device belongs to the
837  * specified platform. */
838  cl_bool pass = CL_FALSE;
839 
840  /* Partial name must be a substring of complete name. */
841  gchar *complt_info, *complt_info_lowr, *part_info;
842 
843  /* Make sure data is not NULL. */
844  ccl_if_err_create_goto(*err, CCL_ERROR, data == NULL,
845  CCL_ERROR_INVALID_DATA, error_handler,
846  "%s: invalid filter data", CCL_STRD);
847 
848  /* Lower-case partial name for comparison. */
849  part_info = g_ascii_strdown((gchar*) data, -1);
850 
851  /* Compare with device name. */
852  complt_info = ccl_device_get_info_array(
853  dev, CL_DEVICE_NAME, char*, &err_internal);
854  ccl_if_err_propagate_goto(err, err_internal, error_handler);
855 
856  complt_info_lowr = g_ascii_strdown(complt_info, -1);
857 
858  if (!g_strrstr(complt_info_lowr, part_info)) {
859  /* Device name does not match, check device vendor. */
860 
861  /* Free string allocated for previous comparison. */
862  g_free(complt_info_lowr);
863 
864  /* Compare with device vendor. */
865  complt_info = ccl_device_get_info_array(
866  dev, CL_DEVICE_VENDOR, char*, &err_internal);
867  ccl_if_err_propagate_goto(err, err_internal, error_handler);
868 
869  complt_info_lowr = g_ascii_strdown(complt_info, -1);
870 
871  if (!g_strrstr(complt_info_lowr, part_info)) {
872  /* Device vendor does not match, check platform name. */
873 
874  /* Free string allocated for previous comparison. */
875  g_free(complt_info_lowr);
876 
877  /* Compare with platform name. */
878  CCLPlatform* platf;
879 
880  /* Get device platform. */
881  platf = ccl_platform_new_from_device(dev, &err_internal);
882  ccl_if_err_propagate_goto(err, err_internal, error_handler);
883 
884  /* Get platform name. */
885  complt_info = ccl_platform_get_info_string(
886  platf, CL_PLATFORM_NAME, &err_internal);
887  ccl_if_err_propagate_goto(err, err_internal, error_handler);
888 
889  complt_info_lowr = g_ascii_strdown(complt_info, -1);
890 
891  /* Compare. */
892  if (g_strrstr(complt_info_lowr, part_info)) {
893  pass = CL_TRUE;
894  }
895 
896  /* Destroy device platform. */
897  ccl_platform_destroy(platf);
898 
899  } else {
900  pass = CL_TRUE;
901  }
902 
903  } else {
904  pass = CL_TRUE;
905  }
906 
907  g_free(complt_info_lowr);
908  g_free(part_info);
909 
910  /* If we got here, everything is OK. */
911  g_assert(err == NULL || *err == NULL);
912  goto finish;
913 
914 error_handler:
915  /* If we got here there was an error, verify that it is so. */
916  g_assert(err == NULL || *err != NULL);
917 
918  /* Filter will not accept device in case an error occurs. */
919  pass = CL_FALSE;
920 
921 finish:
922 
923  /* Return filtering result. */
924  return pass;
925 
926 }
927 
939 CCL_EXPORT
941  CCLDevice* device, void *data, CCLErr **err) {
942 
943  /* Make sure device is not NULL. */
944  g_return_val_if_fail(device != NULL, CL_FALSE);
945  /* Make sure err is NULL or it is not set. */
946  g_return_val_if_fail(err == NULL || *err == NULL, CL_FALSE);
947 
948  /* Device platform. */
949  cl_platform_id platf;
950 
951  /* Internal error object. */
952  CCLErr* err_internal = NULL;
953 
954  /* Return value, i.e., flag indicating if device belongs to the
955  * specified platform. */
956  cl_bool pass;
957 
958  /* Check if data is NULL, throw error if so. */
959  ccl_if_err_create_goto(*err, CCL_ERROR, data == NULL,
960  CCL_ERROR_INVALID_DATA, error_handler,
961  "%s: invalid filter data", CCL_STRD);
962 
963  /* Get device platform. */
964  platf = ccl_device_get_info_scalar(device, CL_DEVICE_PLATFORM,
965  cl_platform_id, &err_internal);
966  ccl_if_err_propagate_goto(err, err_internal, error_handler);
967 
968  /* Determine filtering result, i.e. if device platform is the same
969  * as the specified platform. */
970  pass = (platf == (cl_platform_id) data) ? CL_TRUE : CL_FALSE;
971 
972  /* If we got here, everything is OK. */
973  g_assert(err == NULL || *err == NULL);
974  goto finish;
975 
976 error_handler:
977  /* If we got here there was an error, verify that it is so. */
978  g_assert(err == NULL || *err != NULL);
979 
980  /* Filter will not accept device in case an error occurs. */
981  pass = CL_FALSE;
982 
983 finish:
984 
985  /* Return filtering result. */
986  return pass;
987 }
988 
1006 CCL_EXPORT
1008  CCLDevSelDevices devices, void *data, CCLErr **err) {
1009 
1010  /* Make sure devices is not NULL. */
1011  g_return_val_if_fail(devices != NULL, NULL);
1012  /* Make sure err is NULL or it is not set. */
1013  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1014 
1015  /* Current device. */
1016  CCLDevice* dev;
1017 
1018  /* Reference platform and current device platform.*/
1019  cl_platform_id platf_ref, platf_curr;
1020 
1021  /* Internal error object. */
1022  CCLErr *err_internal = NULL;
1023 
1024  /* Filter data is ignored by this filter. */
1025  CCL_UNUSED(data);
1026 
1027  /* Get first device, which will determine the reference platform. */
1028  dev = (CCLDevice*) g_ptr_array_index(devices, 0);
1029 
1030  /* Determine reference platform (i.e. platform of first device). */
1031  platf_ref = ccl_device_get_info_scalar(dev, CL_DEVICE_PLATFORM,
1032  cl_platform_id, &err_internal);
1033  ccl_if_err_propagate_goto(err, err_internal, error_handler);
1034 
1035  /* Check if devices belong to the reference platform, remove them if
1036  * they don't. */
1037  for (guint i = 1; i < devices->len; i++) {
1038 
1039  /* Get current device. */
1040  dev = (CCLDevice*) g_ptr_array_index(devices, i);
1041 
1042  /* Get current device platform. */
1043  platf_curr = ccl_device_get_info_scalar(
1044  dev, CL_DEVICE_PLATFORM, cl_platform_id, &err_internal);
1045  ccl_if_err_propagate_goto(err, err_internal, error_handler);
1046 
1047  /* If current device doesn't belong to the reference
1048  * platform... */
1049  if (platf_ref != platf_curr) {
1050 
1051  /* Remove device wrapper from device wrapper array. */
1052  g_ptr_array_remove_index(devices, i);
1053 
1054  /* Force device index decrement, because next device to
1055  * be checked will be in this index. */
1056  i--;
1057 
1058  }
1059 
1060  }
1061 
1062  /* If we got here, everything is OK. */
1063  g_assert(err == NULL || *err == NULL);
1064  goto finish;
1065 
1066 error_handler:
1067  /* If we got here there was an error, verify that it is so. */
1068  g_assert(err == NULL || *err != NULL);
1069 
1070  /* Set return value to NULL to conform to specification. */
1071  devices = NULL;
1072 
1073 finish:
1074 
1075  /* Return filtered devices. */
1076  return devices;
1077 }
1078 
1090 CCL_EXPORT
1092  CCLDevSelDevices devices, void *data, CCLErr **err) {
1093 
1094  /* Make sure devices is not NULL. */
1095  g_return_val_if_fail(devices != NULL, NULL);
1096  /* Make sure err is NULL or it is not set. */
1097  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1098 
1099  /* Internal error object. */
1100  CCLErr *err_internal = NULL;
1101 
1102  /* Index of selected device. */
1103  cl_int index = -1;
1104 
1105  /* Device to be selected. */
1106  gpointer sel_dev;
1107 
1108  /* If data argument is given, perform auto-selection. */
1109  if (data != NULL) {
1110  /* Check if data contains a valid device index. */
1111  index = *((cl_uint*) data);
1112  /* Check if index is within bounds. */
1113  if ((index >= 0) && (index < (cl_int) devices->len)) {
1114  /* Device index is within bounds, print list with
1115  * selection. */
1116  ccl_devsel_dep_menu_list(devices, index, &err_internal);
1117  ccl_if_err_propagate_goto(err, err_internal, error_handler);
1118  } else if (index >= 0) {
1119  /* If we get here, an invalid device index was given. */
1120  g_printf("\n (!) No device at index %d!\n", index);
1121  index = -1;
1122  }
1123  /* Don't show warning if a negative index is given, just
1124  * show the menu. */
1125  }
1126 
1127  /* If no proper index was given ask the user for the correct
1128  * index. */
1129  if (index < 0) {
1130  index = ccl_devsel_dep_menu_query(devices, &err_internal);
1131  ccl_if_err_propagate_goto(err, err_internal, error_handler);
1132  }
1133 
1134  /* Remove all devices except the selected device. */
1135  sel_dev = g_ptr_array_index(devices, index);
1136  ccl_device_ref((CCLDevice*) sel_dev);
1137  g_ptr_array_remove_range(devices, 0, devices->len);
1138  g_ptr_array_add(devices, sel_dev);
1139  g_assert_cmpuint(1, ==, devices->len);
1140 
1141  /* If we got here, everything is OK. */
1142  g_assert(err == NULL || *err == NULL);
1143  goto finish;
1144 
1145 error_handler:
1146  /* If we got here there was an error, verify that it is so. */
1147  g_assert(err == NULL || *err != NULL);
1148 
1149  /* Free array object containing device wrappers and set it to NULL. */
1150  if (devices != NULL) {
1151  g_ptr_array_free(devices, TRUE);
1152  devices = NULL;
1153  }
1154 
1155 finish:
1156 
1157  /* Return filtered devices. */
1158  return devices;
1159 }
1160 
1174 CCL_EXPORT
1176  CCLDevSelDevices devices, void *data, CCLErr **err) {
1177 
1178  /* Make sure devices is not NULL. */
1179  g_return_val_if_fail(devices != NULL, NULL);
1180  /* Make sure err is NULL or it is not set. */
1181  g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1182 
1183  /* Index of selected device. */
1184  cl_uint index;
1185 
1186  /* Device to be selected. */
1187  gpointer sel_dev;
1188 
1189  /* If data is NULL, throw error, because we expect a valid device
1190  * index. */
1191  ccl_if_err_create_goto(*err, CCL_ERROR, data == NULL,
1192  CCL_ERROR_INVALID_DATA, error_handler,
1193  "%s: The 'data' parameter must not be NULL.", CCL_STRD);
1194 
1195  /* Check if data contains a valid device index. */
1196  index = *((cl_uint*) data);
1197 
1198  /* Check if index is within bounds. */
1199  ccl_if_err_create_goto(*err, CCL_ERROR, index >= devices->len,
1200  CCL_ERROR_DEVICE_NOT_FOUND, error_handler,
1201  "%s: No device found at index %d.", CCL_STRD, index);
1202 
1203  /* Select device: remove all devices from list except the selected
1204  * device. */
1205  sel_dev = g_ptr_array_index(devices, index);
1206  ccl_device_ref((CCLDevice*) sel_dev);
1207  g_ptr_array_remove_range(devices, 0, devices->len);
1208  g_ptr_array_add(devices, sel_dev);
1209  g_assert_cmpuint(1, ==, devices->len);
1210 
1211  /* If we got here, everything is OK. */
1212  g_assert(err == NULL || *err == NULL);
1213  goto finish;
1214 
1215 error_handler:
1216  /* If we got here there was an error, verify that it is so. */
1217  g_assert(err == NULL || *err != NULL);
1218 
1219  /* Free array object containing device wrappers and set it to NULL. */
1220  if (devices != NULL) {
1221  g_ptr_array_free(devices, TRUE);
1222  devices = NULL;
1223  }
1224 
1225 finish:
1226 
1227  /* Return filtered devices. */
1228  return devices;
1229 }
1230 
Invalid data passed to a function or returned from function.
Definition: ccl_common.h:304
Classes and functions for filtering and selecting OpenCL contexts and associated devices.
#define CCL_OCL_ERROR
Resolves to error category identifying string, in this case an error in the OpenCL library...
Definition: ccl_common.h:324
CCLDevSelDevices ccl_devsel_dep_platform(CCLDevSelDevices devices, void *data, CCLErr **err)
Dependent filter function which only accepts devices of the same platform (the platform to which the ...
#define ccl_platform_get_info_string(platf, param_name, err)
Helper macro which gets a platform information string.
#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
Device filter class, includes a filter function (independent or dependent) and the respective filter ...
CCLDevSelDevices ccl_devsel_dep_menu(CCLDevSelDevices devices, void *data, CCLErr **err)
Dependent filter function which presents a menu to the user allowing him to select the desired device...
Useful definitions used internally by cf4ocl.
void ccl_devsel_devices_destroy(CCLDevSelDevices devices)
Destroy an object containing device wrappers.
cl_bool ccl_devsel_indep_type_cpu(CCLDevice *dev, void *data, CCLErr **err)
Independent filter function which only accepts CPU devices.
#define ccl_if_err_propagate_goto(err_dest, err_src, label)
Same as ccl_if_err_goto(), but rethrows error in a source CCLErr object to a new destination CCLErr o...
Definition: _ccl_defs.h:120
void ccl_platforms_destroy(CCLPlatforms *platforms)
Destroy a CCLPlatforms* object, including all underlying platforms, devices and data.
CCLPlatforms * ccl_platforms_new(CCLErr **err)
Creates a new CCLPlatforms* object, which contains the list of OpenCL platforms available in the syst...
Definition: ccl_platforms.c:68
cl_uint ccl_platforms_count(CCLPlatforms *platforms)
Return number of OpenCL platforms found in CCLPlatforms object.
cl_bool(* ccl_devsel_indep)(CCLDevice *device, void *data, CCLErr **err)
Independent filter function: Abstract function for filtering one OpenCL device at a time...
#define CCL_ERROR
Resolves to error category identifying string, in this case an error in cf4ocl.
Definition: ccl_common.h:320
cl_bool ccl_devsel_indep_type_accel(CCLDevice *dev, void *data, CCLErr **err)
Independent filter function which only accepts accelerator devices.
The requested OpenCL device was not found.
Definition: ccl_common.h:308
GPtrArray * CCLDevSelDevices
An object containing device wrappers.
#define ccl_device_ref(dev)
Increase the reference count of the device wrapper object.
Independent filter, filters one device at a time.
CCLDevSelDevices ccl_devsel_select(CCLDevSelFilters *filters, CCLErr **err)
Select one or more OpenCL devices based on the provided filters.
Class which represents the OpenCL platforms available in the system.
Definition: ccl_platforms.c:37
void ccl_devsel_add_dep_filter(CCLDevSelFilters *filters, ccl_devsel_dep filter, void *data)
Add a dependent filter to the filter set.
CCLPlatform * ccl_platform_new_from_device(CCLDevice *dev, CCLErr **err)
Get the platform wrapper for the given device wrapper.
void ccl_device_destroy(CCLDevice *dev)
Decrements the reference count of the device wrapper object.
gchar ** ccl_devsel_get_device_strings(CCLErr **err)
Returns a NULL-terminated array of strings, each one containing the name and vendor of each device in...
#define CCL_UNUSED(x)
Macro to avoid warning in unused variables.
Definition: ccl_common.h:86
void ccl_devsel_add_indep_filter(CCLDevSelFilters *filters, ccl_devsel_indep filter, void *data)
Add an independent filter to the filter set.
#define ccl_device_get_info_array(dev, param_name, param_type, err)
Macro which returns an array device information value.
CCLDevSelDevices ccl_devsel_dep_index(CCLDevSelDevices devices, void *data, CCLErr **err)
Dependent filter function which selects the device at the specified index, failing if no device is fo...
CCLDevSelDevices(* ccl_devsel_dep)(CCLDevSelDevices devices, void *data, CCLErr **err)
Dependent filter function: Abstract function for filtering several OpenCL devices depending on the av...
cl_bool ccl_devsel_indep_string(CCLDevice *dev, void *data, CCLErr **err)
Independent filter which selects devices based on device name, device vendor and/or platform name...
GPtrArray * CCLDevSelFilters
A set of independent and dependent device filters.
cl_bool ccl_devsel_indep_type_gpu(CCLDevice *dev, void *data, CCLErr **err)
Independent filter function which only accepts GPU devices.
Dependent filter, filters devices depending on the currently available device choices.
#define ccl_device_get_info_scalar(dev, param_name, param_type, err)
Macro which returns a scalar device information value.
cl_uint ccl_platform_get_num_devices(CCLPlatform *platf, CCLErr **err)
Return number of devices in platform.
enum ccl_devsel_filter_type CCLDevSelFilterType
Filter type.
void ccl_platform_destroy(CCLPlatform *platf)
Decrements the reference count of the platform wrapper object.
cl_bool ccl_devsel_indep_type(CCLDevice *dev, void *data, CCLErr **err)
Independent filter function which accepts devices of the type given in the data parameter.
void(* ccl_devsel_fp)(void)
Generic filter function pointer.
GError CCLErr
Error handling class.
Definition: ccl_common.h:291
void ccl_devsel_print_device_strings(CCLErr **err)
Print to stdout a device description string for each device in the system.
CCLDevSelDevices ccl_devsel_devices_new(CCLErr **err)
Create and return an object with device wrappers for all OpenCL devices present in the system...
struct ccl_devsel_filter CCLDevSelFilter
Device filter class, includes a filter function (independent or dependent) and the respective filter ...
CCLPlatform * ccl_platforms_get(CCLPlatforms *platforms, cl_uint index)
Get platform wrapper object at given index.
Device wrapper class.
cl_bool ccl_devsel_indep_platform(CCLDevice *device, void *data, CCLErr **err)
Independent filter function which only accepts devices of a specified platform.
The platform wrapper class.
CCLDevice * ccl_platform_get_device(CCLPlatform *platf, cl_uint index, CCLErr **err)
Get CCLDevice wrapper at given index.