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_devinfo.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 General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (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 General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with cf4ocl. If not, see <http://www.gnu.org/licenses/>.
16  * */
17 
119 #include "ccl_utils.h"
120 
121 #ifndef CCL_DEVINFO_OUT
122 
123  #define CCL_DEVINFO_OUT stdout
124 #endif
125 
126 #ifndef CCL_DEVINFO_NA
127  #define CCL_DEVINFO_NA "N/A"
128 #endif
129 
131 #define CCL_DEVINFO_DESCRIPTION "Utility for querying OpenCL " \
132  "platforms and devices"
133 
135 #define CCL_DEVINFO_MAXINFOLEN 500
136 
137 /* Command line arguments and respective default values. */
138 static gboolean opt_all = FALSE;
139 static gboolean opt_basic = TRUE; /* Default. */
140 static gboolean no_platf = FALSE;
141 static gchar** opt_custom = NULL;
142 static guint opt_platf = G_MAXUINT;
143 static guint opt_dev = G_MAXUINT;
144 static gboolean opt_nfound = FALSE;
145 static gboolean opt_verb = FALSE;
146 static gboolean opt_list = FALSE;
147 static gboolean version = FALSE;
148 
149 /* Valid command line options. */
150 static GOptionEntry entries[] = {
151  {"all", 'a', 0, G_OPTION_ARG_NONE, &opt_all,
152  "Show all the available device information", NULL},
153  {"basic", 'b', 0, G_OPTION_ARG_NONE, &opt_basic,
154  "Show basic device information (default)", NULL},
155  {"custom", 'c', 0, G_OPTION_ARG_STRING_ARRAY, &opt_custom,
156  "Show specific information, repeat as necessary", "cl_device_info"},
157  {"device", 'd', 0, G_OPTION_ARG_INT, &opt_dev,
158  "Specify the index of a device to query", "dev_idx"},
159  {"no-platf", 'o', 0, G_OPTION_ARG_NONE, &no_platf,
160  "Ignore platforms, device index reports to all "
161  "devices available in the system", NULL},
162  {"list", 'l', 0, G_OPTION_ARG_NONE, &opt_list,
163  "List known information parameters", NULL},
164  {"platform", 'p', 0, G_OPTION_ARG_INT, &opt_platf,
165  "Specify the index of a platform to query", "platf_idx"},
166  {"notfound", 'n', 0, G_OPTION_ARG_NONE, &opt_nfound,
167  "Show known parameters even if not found in device", NULL},
168  {"verbose", 'v', 0, G_OPTION_ARG_NONE, &opt_verb,
169  "Show description of each parameter", NULL},
170  {"version", 0, 0, G_OPTION_ARG_NONE, &version,
171  "Output version information and exit", NULL},
172  { NULL, 0, 0, 0, NULL, NULL, NULL }
173 };
174 
175 /* Information queried for basic CLI option. */
176 static gchar* basic_info[] = {
177  "type",
178  "vendor",
179  "opencl_c_version",
180  "max_compute_units",
181  "global_mem_size",
182  "max_mem_alloc_size",
183  "local_mem_size",
184  "local_mem_type",
185  "max_work_group_size",
186  NULL
187 };
188 
189 /* Macro to invoke correct function for the specified device information. */
190 #define ccl_devinfo_show_device_info(d) \
191  if (opt_all) ccl_devinfo_show_device_info_all(d); \
192  else if (opt_custom) ccl_devinfo_show_device_info_custom(d); \
193  else ccl_devinfo_show_device_info_basic(d);
194 
203 void ccl_devinfo_args_parse(int argc, char* argv[], CCLErr** err) {
204 
205  /* Make sure err is NULL or it is not set. */
206  g_return_if_fail(err == NULL || *err == NULL);
207 
208  /* Command line options context. */
209  GOptionContext* context = NULL;
210 
211  /* Create parsing context. */
212  context = g_option_context_new(" - " CCL_DEVINFO_DESCRIPTION);
213 
214  /* Add acceptable command line options to context. */
215  g_option_context_add_main_entries(context, entries, NULL);
216 
217  /* Use context to parse command line options. */
218  g_option_context_parse(context, &argc, &argv, err);
219  ccl_if_err_goto(*err, error_handler);
220 
221  /* If we get here, no need for error treatment, jump to cleanup. */
222  g_assert(*err == NULL);
223  goto cleanup;
224 
225 error_handler:
226 
227  /* If we got here, everything is OK. */
228  g_assert(*err != NULL);
229 
230 cleanup:
231 
232  /* Free context. */
233  if (context) g_option_context_free(context);
234 
235  /* Return. */
236  return;
237 
238 }
239 
247 
248  /* Platform info variables. */
249  gchar *profile, *version, *name, *vendor;
250 
251  /* Error location. */
252  CCLErr* err = NULL;
253 
254  /* Get platform profile. */
255  profile = ccl_platform_get_info_string(p, CL_PLATFORM_PROFILE, &err);
256  if (err != NULL) {
257  g_clear_error(&err);
258  profile = "Unknown profile";
259  }
260 
261  /* Get platform version. */
262  version = ccl_platform_get_info_string(p, CL_PLATFORM_VERSION, &err);
263  if (err != NULL) {
264  g_clear_error(&err);
265  version = "Unknown version";
266  }
267 
268  /* Get platform name. */
269  name = ccl_platform_get_info_string(p, CL_PLATFORM_NAME, &err);
270  if (err != NULL) {
271  g_clear_error(&err);
272  name = "Unknown name";
273  }
274 
275  /* Get platform vendor. */
276  vendor = ccl_platform_get_info_string(p, CL_PLATFORM_VENDOR, &err);
277  if (err != NULL) {
278  g_clear_error(&err);
279  vendor = "Unknown vendor";
280  }
281 
282  /* Send info to defined stream. */
283  g_fprintf(CCL_DEVINFO_OUT,
284  "\n* Platform #%d: %s (%s)\n %s, %s\n",
285  idx, name, vendor, version, profile);
286 
287  /* Bye. */
288  return;
289 }
290 
291 #define ccl_devinfo_output_device_info(key, value, desc) \
292  if (opt_verb) { \
293  g_fprintf(CCL_DEVINFO_OUT, \
294  "\t\t Parameter : %s\n" \
295  "\t\t Description : %s\n" \
296  "\t\t Value : %s\n\n", \
297  key, desc, value); \
298  } else { \
299  g_fprintf(CCL_DEVINFO_OUT, \
300  " %-36.36s | %s\n", \
301  key, value); \
302  }
303 
310 
311  /* Parameter value and size. */
312  CCLWrapperInfo* param_value;
313 
314  /* Parameter value string. */
315  gchar param_value_str[CCL_DEVINFO_MAXINFOLEN];
316 
317  /* Error reporting object. */
318  CCLErr* err = NULL;
319 
320  /* Cycle through all supported device information names. */
321  for (gint k = 0; k < ccl_devquery_info_map_size; k++) {
322 
323  /* Get the device information value and size. */
324  param_value = ccl_device_get_info(
325  d, ccl_devquery_info_map[k].device_info, &err);
326 
327  /* Check for errors. */
328  if (err == NULL) {
329 
330  /* If no error, show current parameter value... */
331  ccl_devinfo_output_device_info(
332  ccl_devquery_info_map[k].param_name,
333  ccl_devquery_info_map[k].format(
334  param_value, param_value_str,
336  ccl_devquery_info_map[k].units),
337  ccl_devquery_info_map[k].description);
338 
339  } else {
340 
341  /* ...otherwise clear error... */
342  g_clear_error(&err);
343  if (opt_nfound) {
344  /* ...and show that parameter is not available, if user
345  * requested so. */
346  ccl_devinfo_output_device_info(
347  ccl_devquery_info_map[k].param_name,
348  CCL_DEVINFO_NA,
349  ccl_devquery_info_map[k].description);
350  }
351  }
352  }
353 
354 }
355 
362 
363  /* A row of the device info_map. */
364  const CCLDevQueryMap* info_row;
365 
366  /* Parameter value and size. */
367  CCLWrapperInfo* param_value;
368 
369  /* Parameter value string. */
370  gchar param_value_str[CCL_DEVINFO_MAXINFOLEN];
371 
372  /* Error reporting object. */
373  CCLErr* err = NULL;
374 
375  /* Custom parameter name in proper format. */
376  gchar* custom_param_name;
377 
378  /* Index of next row of the device info_map. */
379  gint idx;
380 
381  /* Cycle through all user specified parameter substrings. */
382  for (guint i = 0; opt_custom[i] != NULL; i++) {
383 
384  /* Set index of next row to zero. */
385  idx = 0;
386 
387  /* Put info name in proper format. */
388  custom_param_name = ccl_devquery_get_prefix_final(opt_custom[i]);
389 
390  /* Get next row (the first one). */
391  info_row = ccl_devquery_match(custom_param_name, &idx);
392 
393  /* Keep getting rows until we reach the end of the device
394  * info_map. */
395  while (info_row != NULL) {
396 
397  /* Get parameter value for current info_map row. */
398  param_value = ccl_device_get_info(d, info_row->device_info, &err);
399 
400  /* Check for errors. */
401  if (err == NULL) {
402 
403  /* If no error, show current parameter value... */
404  ccl_devinfo_output_device_info(
405  info_row->param_name,
406  info_row->format(
407  param_value, param_value_str,
409  info_row->units),
410  info_row->description);
411 
412  } else {
413 
414  /* ...otherwise clear error... */
415  g_clear_error(&err);
416  if (opt_nfound) {
417  /* ...and show that parameter is not available, if user
418  * requested so. */
419  ccl_devinfo_output_device_info(
420  info_row->param_name,
421  CCL_DEVINFO_NA,
422  info_row->description);
423  }
424  }
425 
426  /* Get next row. */
427  info_row = ccl_devquery_match(custom_param_name, &idx);
428 
429  }
430 
431  /* Free the proper format custom parameter name. */
432  g_free(custom_param_name);
433 
434  }
435 
436 }
437 
444 
445  /* A row of the device info_map. */
446  const CCLDevQueryMap* info_row;
447 
448  /* Parameter value and size. */
449  CCLWrapperInfo* param_value;
450 
451  /* Parameter value string. */
452  gchar param_value_str[CCL_DEVINFO_MAXINFOLEN];
453 
454  /* Error reporting object. */
455  CCLErr* err = NULL;
456 
457  /* Cycle through the pre-defined basic information array. */
458  for (guint i = 0; basic_info[i] != NULL; i++) {
459 
460  /* Get next row. */
461  info_row = ccl_devquery_prefix(basic_info[i], NULL);
462 
463  /* Check that its a valid parameter, otherwise we have a
464  * programming error, so it is better to abort. */
465  g_assert(info_row != NULL);
466 
467  /* Get parameter value for current info_map row. */
468  param_value = ccl_device_get_info(d, info_row->device_info, &err);
469 
470  /* Check for errors. */
471  if (err == NULL) {
472 
473  /* If no error, show current parameter value... */
474  ccl_devinfo_output_device_info(
475  info_row->param_name,
476  info_row->format(
477  param_value, param_value_str,
479  info_row->units),
480  info_row->description);
481 
482  } else {
483 
484  /* ...otherwise clear error... */
485  g_clear_error(&err);
486  if (opt_nfound) {
487  /* ...and show that parameter is not available, if user
488  * requested so. */
489  ccl_devinfo_output_device_info(
490  info_row->param_name,
491  CCL_DEVINFO_NA,
492  info_row->description);
493  }
494  }
495 
496  }
497 
498 }
499 
508 int main(int argc, char* argv[]) {
509 
510  /* Error object. */
511  CCLErr* err = NULL;
512 
513  /* List of platform wrapper objects. */
514  CCLPlatforms* platforms = NULL;
515 
516  /* List of device wrapper objects. */
517  CCLDevSelDevices devices = NULL;
518 
519  /* Current platform and device. */
520  CCLPlatform* p;
521  CCLDevice* d;
522 
523  /* Number of devices in platform. */
524  guint num_devs;
525 
526  /* Device information value object. */
527  CCLWrapperInfo* info_value = NULL;
528 
529  /* Device name. */
530  gchar* dev_name;
531 
532  /* Program return status. */
533  gint status;
534 
535  /* Parse command line options. */
536  ccl_devinfo_args_parse(argc, argv, &err);
537  ccl_if_err_goto(err, error_handler);
538 
539  /* If version was requested, output version and exit. */
540  if (version) {
541  ccl_common_version_print("ccl_devinfo");
542  exit(0);
543  }
544 
545  /* Check if user requested a list of known information parameters. */
546  if (opt_list) {
547 
548  /*Yes, user requested list, present it. */
549 
550  g_fprintf(CCL_DEVINFO_OUT, "\nKnown information parameters:\n\n");
551  for (gint i = 0; i < ccl_devquery_info_map_size; i++) {
552  if (opt_verb) {
553  g_fprintf(CCL_DEVINFO_OUT,
554  "\t%s\n\t\t%s.\n\n",
555  ccl_devquery_info_map[i].param_name,
556  ccl_devquery_info_map[i].description);
557  } else {
558  g_fprintf(CCL_DEVINFO_OUT,
559  "\t%s\n",
560  ccl_devquery_info_map[i].param_name);
561  }
562  }
563  g_fprintf(CCL_DEVINFO_OUT, "\n");
564 
565  } else {
566 
567  /* User didn't request list, proceed as normal query. */
568 
569  /* Ignore platforms and focus only on number of devices in system? */
570  if (no_platf) {
571 
572  /* Ignore platform, continue device-wise. */
573 
574  /* Get all devices in the system. */
575  devices = ccl_devsel_devices_new(&err);
576  ccl_if_err_goto(err, error_handler);
577 
578  /* Cycle through devices. */
579  for (guint j = 0; j < devices->len; j++) {
580 
581  /* Get out if this device is not to be queried. */
582  if ((opt_dev != G_MAXUINT) && (j != opt_dev))
583  continue;
584 
585  /* Get current device. */
586  d = (CCLDevice*) devices->pdata[j];
587 
588  /* Get device name. */
589  info_value = ccl_device_get_info(d, CL_DEVICE_NAME, &err);
590  ccl_if_err_goto(err, error_handler);
591 
592  dev_name = (gchar*) info_value->value;
593 
594  /* Show device information. */
595  g_fprintf(CCL_DEVINFO_OUT,
596  "\n [ Device #%d: %s ]\n\n",
597  j, dev_name);
598  ccl_devinfo_show_device_info(d);
599 
600  }
601  g_fprintf(CCL_DEVINFO_OUT, "\n");
602 
603  } else {
604 
605  /* Do not ignore platforms, continue platform-wise. */
606 
607  /* Get list of platform wrapper objects. */
608  platforms = ccl_platforms_new(&err);
609  ccl_if_err_goto(err, error_handler);
610 
611  /* Cycle through platforms. */
612  for (guint i = 0; i < ccl_platforms_count(platforms); i++) {
613 
614  /* Get out if this platform is not to be queried. */
615  if ((opt_platf != G_MAXUINT) && (i != opt_platf))
616  continue;
617 
618  /* Get current platform. */
619  p = ccl_platforms_get(platforms, i);
620 
621  /* Show platform information. */
623 
624  /* Get number of devices. */
625  num_devs = ccl_platform_get_num_devices(p, &err);
626 
627  /* Is this a platform without devices? */
628  if ((err) && (err->domain == CCL_OCL_ERROR) &&
629  (err->code == CL_DEVICE_NOT_FOUND)) {
630 
631  /* Clear "device not found" error. */
632  g_clear_error(&err);
633 
634  /* Inform about non-existing devices. */
635  g_fprintf(CCL_DEVINFO_OUT,
636  "\n [ No devices found ]\n\n");
637 
638  /* Skip this platform. */
639  continue;
640  }
641  ccl_if_err_goto(err, error_handler);
642 
643  /* Cycle through devices. */
644  for (guint j = 0; j < num_devs; j++) {
645 
646  /* Get out if this device is not to be queried. */
647  if ((opt_dev != G_MAXUINT) && (j != opt_dev))
648  continue;
649 
650  /* Get current device. */
651  d = ccl_platform_get_device(p, j, &err);
652  ccl_if_err_goto(err, error_handler);
653 
654  /* Get device name. */
655  info_value = ccl_device_get_info(d, CL_DEVICE_NAME, &err);
656  ccl_if_err_goto(err, error_handler);
657 
658  dev_name = (gchar*) info_value->value;
659 
660  /* Show device information. */
661  g_fprintf(CCL_DEVINFO_OUT,
662  "\n [ Device #%d: %s ]\n\n",
663  j, dev_name);
664  ccl_devinfo_show_device_info(d);
665 
666  }
667  g_fprintf(CCL_DEVINFO_OUT, "\n");
668  }
669  }
670  }
671 
672  /* If we got here, everything is OK. */
673  g_assert(err == NULL);
674  status = CCL_SUCCESS;
675  goto cleanup;
676 
677 error_handler:
678 
679  /* If we got here there was an error, verify that it is so. */
680  g_assert(err != NULL);
681  g_fprintf(stderr, "%s\n", err->message);
682  status = (err->domain == CCL_ERROR) ? err->code : CCL_ERROR_OTHER;
683  g_error_free(err);
684 
685 cleanup:
686 
687  /* Free stuff! */
688  if (platforms) ccl_platforms_destroy(platforms);
689  if (devices) ccl_devsel_devices_destroy(devices);
690  g_strfreev(opt_custom);
691 
692  /* Confirm that memory allocated by wrappers has been properly
693  * freed. */
694  g_return_val_if_fail(ccl_wrapper_memcheck(), CCL_ERROR_OTHER);
695 
696  /* Return status. */
697  return status;
698 
699 }
void ccl_devinfo_show_device_info_basic(CCLDevice *d)
Show basic device information.
Definition: ccl_devinfo.c:443
Maps a string to a cl_device_info bitfield.
const ccl_devquery_format format
Output formatting function.
#define CCL_OCL_ERROR
Resolves to error category identifying string, in this case an error in the OpenCL library...
Definition: ccl_common.h:324
#define ccl_platform_get_info_string(platf, param_name, err)
Helper macro which gets a platform information string.
void ccl_devinfo_show_platform_info(CCLPlatform *p, guint idx)
Show platform information.
Definition: ccl_devinfo.c:246
Any other errors.
Definition: ccl_common.h:315
void ccl_devinfo_show_device_info_all(CCLDevice *d)
Show all available device information.
Definition: ccl_devinfo.c:309
void ccl_devsel_devices_destroy(CCLDevSelDevices devices)
Destroy an object containing device wrappers.
#define ccl_if_err_goto(err, label)
If error is detected in err object (err != NULL), go to the specified label.
Definition: _ccl_defs.h:106
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
const CCLDevQueryMap * ccl_devquery_prefix(const char *prefix, int *size)
Get a pointer to the first device information parameter which has the given prefix.
#define ccl_device_get_info(dev, param_name, err)
Get a CCLWrapperInfo device information object.
void ccl_common_version_print(const char *exec_name)
Print executable version.
Definition: ccl_common.c:37
cl_uint ccl_platforms_count(CCLPlatforms *platforms)
Return number of OpenCL platforms found in CCLPlatforms object.
#define CCL_ERROR
Resolves to error category identifying string, in this case an error in cf4ocl.
Definition: ccl_common.h:320
GPtrArray * CCLDevSelDevices
An object containing device wrappers.
Common header file for _cf4ocl utilities.
Class which represents the OpenCL platforms available in the system.
Definition: ccl_platforms.c:37
#define CCL_DEVINFO_DESCRIPTION
Program description.
Definition: ccl_devinfo.c:131
const cl_device_info device_info
CL device information bitfield.
void ccl_devinfo_show_device_info_custom(CCLDevice *d)
Show user specified device information.
Definition: ccl_devinfo.c:361
void ccl_devinfo_args_parse(int argc, char *argv[], CCLErr **err)
Parse and verify command line arguments.
Definition: ccl_devinfo.c:203
#define CCL_DEVINFO_OUT
Default device information output stream.
Definition: ccl_devinfo.c:123
void * value
Object information.
cl_uint ccl_platform_get_num_devices(CCLPlatform *platf, CCLErr **err)
Return number of devices in platform.
int main(int argc, char *argv[])
Device info main program function.
Definition: ccl_devinfo.c:508
const char *const description
Long description of parameter.
Class which represents information about a wrapped OpenCL object.
const int ccl_devquery_info_map_size
Size of parameter information map.
GError CCLErr
Error handling class.
Definition: ccl_common.h:291
Successful operation.
Definition: ccl_common.h:298
cl_bool ccl_wrapper_memcheck()
Debug function which checks if memory allocated by wrappers has been properly freed.
gchar * ccl_devquery_get_prefix_final(const char *prefix)
Get a final device info prefix in the same format as kept in the ccl_devquery_info_map.
CCLDevSelDevices ccl_devsel_devices_new(CCLErr **err)
Create and return an object with device wrappers for all OpenCL devices present in the system...
const char *const param_name
Parameter name string.
CCLPlatform * ccl_platforms_get(CCLPlatforms *platforms, cl_uint index)
Get platform wrapper object at given index.
#define CCL_DEVINFO_MAXINFOLEN
Maximum length of device information output, per parameter.
Definition: ccl_devinfo.c:135
const CCLDevQueryMap ccl_devquery_info_map[]
Map of parameter name strings to respective cl_device_info bitfields, long description string...
Device wrapper class.
The platform wrapper class.
CCLDevice * ccl_platform_get_device(CCLPlatform *platf, cl_uint index, CCLErr **err)
Get CCLDevice wrapper at given index.
const CCLDevQueryMap * ccl_devquery_match(const char *substr, int *idx)
Search for a device information parameter by matching part of its name.
const char *const units
Parameter units suffix.