Ticket #43710: clInfo.c

File clInfo.c, 12.4 KB (added by 246tnt@…, 10 years ago)
Line 
1/*
2 * clInfo.c --
3 *
4 *      Program to enumerate and dump all of the OpenCL information for a
5 *      machine (or at least for a specific run-time).
6 *
7 * (Jeremy Sugerman, 13 August 2009)
8 */
9
10#include <stdio.h>
11#include <malloc.h>
12#include <getopt.h>
13#include <stdlib.h>
14
15#include "CL/cl.h"
16
17#define Warning(...)    fprintf(stderr, __VA_ARGS__)
18
19typedef struct Opts {
20   /*
21    * Boolean options below here, all default to false (zero).
22    */
23
24   int verify;
25   int timing;
26} Opts;
27
28
29/*
30 * Usage --
31 *
32 *      Prints the usage message and exits.
33 *
34 * Results:
35 *      void, but calls exit(1)...
36 */
37
38static void
39Usage(const char *progName) {
40   Warning("Usage: %s [options]\n", progName);
41   Warning("Options:\n");
42   Warning("  -h, --help                This message\n");
43
44   exit(1);
45}
46
47
48/*
49 * ParseOpts --
50 *
51 *      Converts the commandline parameters into their internal
52 *      representation.
53 *
54 * Results:
55 *      void, opts is initialized.
56 */
57
58static void
59ParseOpts(Opts *opts, int argc, char *argv[]) {
60   int opt;
61
62   static struct option longOptions[] = {
63      {"help",         0, 0, 'h'},
64   };
65
66
67   while ((opt = getopt_long(argc, argv, "h",
68                             longOptions, NULL)) != EOF) {
69      switch(opt) {
70      case 'h':
71      default:
72         Usage(argv[0]);
73         break;
74      }
75   }
76
77   return;
78}
79
80
81/*
82 * CLErrString --
83 *
84 *      Utility function that converts an OpenCL status into a human
85 *      readable string.
86 *
87 * Results:
88 *      const char * pointer to a static string.
89 */
90
91static const char *
92CLErrString(cl_int status) {
93   static struct { cl_int code; const char *msg; } error_table[] = {
94      { CL_SUCCESS, "success" },
95      { CL_DEVICE_NOT_FOUND, "device not found", },
96      { CL_DEVICE_NOT_AVAILABLE, "device not available", },
97      { CL_COMPILER_NOT_AVAILABLE, "compiler not available", },
98      { CL_MEM_OBJECT_ALLOCATION_FAILURE, "mem object allocation failure", },
99      { CL_OUT_OF_RESOURCES, "out of resources", },
100      { CL_OUT_OF_HOST_MEMORY, "out of host memory", },
101      { CL_PROFILING_INFO_NOT_AVAILABLE, "profiling not available", },
102      { CL_MEM_COPY_OVERLAP, "memcopy overlaps", },
103      { CL_IMAGE_FORMAT_MISMATCH, "image format mismatch", },
104      { CL_IMAGE_FORMAT_NOT_SUPPORTED, "image format not supported", },
105      { CL_BUILD_PROGRAM_FAILURE, "build program failed", },
106      { CL_MAP_FAILURE, "map failed", },
107      { CL_INVALID_VALUE, "invalid value", },
108      { CL_INVALID_DEVICE_TYPE, "invalid device type", },
109      { 0, NULL },
110   };
111   static char unknown[25];
112   int ii;
113
114   for (ii = 0; error_table[ii].msg != NULL; ii++) {
115      if (error_table[ii].code == status) {
116         return error_table[ii].msg;
117      }
118   }
119
120   snprintf(unknown, sizeof unknown, "unknown error %d", status);
121   return unknown;
122}
123
124
125/*
126 * PrintDevice --
127 *
128 *      Dumps everything about the given device ID.
129 *
130 * Results:
131 *      void.
132 */
133
134static void
135PrintDevice(cl_device_id device) {
136#define LONG_PROPS \
137  defn(VENDOR_ID), \
138  defn(MAX_COMPUTE_UNITS), \
139  defn(MAX_WORK_ITEM_DIMENSIONS), \
140  defn(MAX_WORK_GROUP_SIZE), \
141  defn(PREFERRED_VECTOR_WIDTH_CHAR), \
142  defn(PREFERRED_VECTOR_WIDTH_SHORT), \
143  defn(PREFERRED_VECTOR_WIDTH_INT), \
144  defn(PREFERRED_VECTOR_WIDTH_LONG), \
145  defn(PREFERRED_VECTOR_WIDTH_FLOAT), \
146  defn(PREFERRED_VECTOR_WIDTH_DOUBLE), \
147  defn(MAX_CLOCK_FREQUENCY), \
148  defn(ADDRESS_BITS), \
149  defn(MAX_MEM_ALLOC_SIZE), \
150  defn(IMAGE_SUPPORT), \
151  defn(MAX_READ_IMAGE_ARGS), \
152  defn(MAX_WRITE_IMAGE_ARGS), \
153  defn(IMAGE2D_MAX_WIDTH), \
154  defn(IMAGE2D_MAX_HEIGHT), \
155  defn(IMAGE3D_MAX_WIDTH), \
156  defn(IMAGE3D_MAX_HEIGHT), \
157  defn(IMAGE3D_MAX_DEPTH), \
158  defn(MAX_SAMPLERS), \
159  defn(MAX_PARAMETER_SIZE), \
160  defn(MEM_BASE_ADDR_ALIGN), \
161  defn(MIN_DATA_TYPE_ALIGN_SIZE), \
162  defn(GLOBAL_MEM_CACHELINE_SIZE), \
163  defn(GLOBAL_MEM_CACHE_SIZE), \
164  defn(GLOBAL_MEM_SIZE), \
165  defn(MAX_CONSTANT_BUFFER_SIZE), \
166  defn(MAX_CONSTANT_ARGS), \
167  defn(LOCAL_MEM_SIZE), \
168  defn(ERROR_CORRECTION_SUPPORT), \
169  defn(PROFILING_TIMER_RESOLUTION), \
170  defn(ENDIAN_LITTLE), \
171  defn(AVAILABLE), \
172  defn(COMPILER_AVAILABLE),
173
174#define STR_PROPS \
175  defn(NAME), \
176  defn(VENDOR), \
177  defn(PROFILE), \
178  defn(VERSION), \
179  defn(EXTENSIONS),
180
181#define HEX_PROPS \
182   defn(SINGLE_FP_CONFIG), \
183   defn(QUEUE_PROPERTIES),
184
185
186/* XXX For completeness, it'd be nice to dump this one, too. */
187#define WEIRD_PROPS \
188   CL_DEVICE_MAX_WORK_ITEM_SIZES,
189
190   static struct { cl_device_info param; const char *name; } longProps[] = {
191#define defn(X) { CL_DEVICE_##X, #X }
192      LONG_PROPS
193#undef defn
194      { 0, NULL },
195   };
196   static struct { cl_device_info param; const char *name; } hexProps[] = {
197#define defn(X) { CL_DEVICE_##X, #X }
198      HEX_PROPS
199#undef defn
200      { 0, NULL },
201   };
202   static struct { cl_device_info param; const char *name; } strProps[] = {
203#define defn(X) { CL_DEVICE_##X, #X }
204      STR_PROPS
205#undef defn
206      { CL_DRIVER_VERSION, "DRIVER_VERSION" },
207      { 0, NULL },
208   };
209   cl_int status;
210   size_t size;
211   char buf[65536];
212   long long val; /* Avoids unpleasant surprises for some params */
213   int ii;
214
215
216   for (ii = 0; strProps[ii].name != NULL; ii++) {
217      status = clGetDeviceInfo(device, strProps[ii].param, sizeof buf, buf, &size);
218      if (status != CL_SUCCESS) {
219         Warning("\tdevice[%p]: Unable to get %s: %s!\n",
220                 device, strProps[ii].name, CLErrString(status));
221         continue;
222      }
223      if (size > sizeof buf) {
224         Warning("\tdevice[%p]: Large %s (%d bytes)!  Truncating to %d!\n",
225                 device, strProps[ii].name, size, sizeof buf);
226      }
227      printf("\tdevice[%p]: %s: %s\n",
228             device, strProps[ii].name, buf);
229   }
230   printf("\n");
231
232   status = clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof val, &val, NULL);
233   if (status == CL_SUCCESS) {
234      printf("\tdevice[%p]: Type: ", device);
235      if (val & CL_DEVICE_TYPE_DEFAULT) {
236         val &= ~CL_DEVICE_TYPE_DEFAULT;
237         printf("Default ");
238      }
239      if (val & CL_DEVICE_TYPE_CPU) {
240         val &= ~CL_DEVICE_TYPE_CPU;
241         printf("CPU ");
242      }
243      if (val & CL_DEVICE_TYPE_GPU) {
244         val &= ~CL_DEVICE_TYPE_GPU;
245         printf("GPU ");
246      }
247      if (val & CL_DEVICE_TYPE_ACCELERATOR) {
248         val &= ~CL_DEVICE_TYPE_ACCELERATOR;
249         printf("Accelerator ");
250      }
251      if (val != 0) {
252         printf("Unknown (0x%llx) ", val);
253      }
254      printf("\n");
255   } else {
256      Warning("\tdevice[%p]: Unable to get TYPE: %s!\n",
257              device, CLErrString(status));
258   }
259
260   status = clGetDeviceInfo(device, CL_DEVICE_EXECUTION_CAPABILITIES,
261                            sizeof val, &val, NULL);
262   if (status == CL_SUCCESS) {
263      printf("\tdevice[%p]: EXECUTION_CAPABILITIES: ", device);
264      if (val & CL_EXEC_KERNEL) {
265         val &= ~CL_EXEC_KERNEL;
266         printf("Kernel ");
267      }
268      if (val & CL_EXEC_NATIVE_KERNEL) {
269         val &= ~CL_EXEC_NATIVE_KERNEL;
270         printf("Native ");
271      }
272      if (val) {
273         printf("Unknown (0x%llx) ", val);
274      }
275      printf("\n");
276   } else {
277      Warning("\tdevice[%p]: Unable to get EXECUTION_CAPABILITIES: %s!\n",
278              device, CLErrString(status));
279   }
280
281   status = clGetDeviceInfo(device, CL_DEVICE_GLOBAL_MEM_CACHE_TYPE,
282                            sizeof val, &val, NULL);
283   if (status == CL_SUCCESS) {
284      static const char *cacheTypes[] = { "None", "Read-Only", "Read-Write" };
285      static int numTypes = sizeof cacheTypes / sizeof cacheTypes[0];
286
287      printf("\tdevice[%p]: GLOBAL_MEM_CACHE_TYPE: %s (%lld)\n",
288             device, val < numTypes ? cacheTypes[val] : "???", val);
289   } else {
290      Warning("\tdevice[%p]: Unable to get GLOBAL_MEM_CACHE_TYPE: %s!\n",
291              device, CLErrString(status));
292   }
293   status = clGetDeviceInfo(device,
294                            CL_DEVICE_LOCAL_MEM_TYPE, sizeof val, &val, NULL);
295   if (status == CL_SUCCESS) {
296      static const char *lmemTypes[] = { "???", "Local", "Global" };
297      static int numTypes = sizeof lmemTypes / sizeof lmemTypes[0];
298
299      printf("\tdevice[%p]: CL_DEVICE_LOCAL_MEM_TYPE: %s (%lld)\n",
300             device, val < numTypes ? lmemTypes[val] : "???", val);
301   } else {
302      Warning("\tdevice[%p]: Unable to get CL_DEVICE_LOCAL_MEM_TYPE: %s!\n",
303              device, CLErrString(status));
304   }
305
306   for (ii = 0; hexProps[ii].name != NULL; ii++) {
307      status = clGetDeviceInfo(device, hexProps[ii].param, sizeof val, &val, &size);
308      if (status != CL_SUCCESS) {
309         Warning("\tdevice[%p]: Unable to get %s: %s!\n",
310                 device, hexProps[ii].name, CLErrString(status));
311         continue;
312      }
313      if (size > sizeof val) {
314         Warning("\tdevice[%p]: Large %s (%d bytes)!  Truncating to %d!\n",
315                 device, hexProps[ii].name, size, sizeof val);
316      }
317      printf("\tdevice[%p]: %s: 0x%llx\n",
318             device, hexProps[ii].name, val);
319   }
320   printf("\n");
321
322   for (ii = 0; longProps[ii].name != NULL; ii++) {
323      status = clGetDeviceInfo(device, longProps[ii].param, sizeof val, &val, &size);
324      if (status != CL_SUCCESS) {
325         Warning("\tdevice[%p]: Unable to get %s: %s!\n",
326                 device, longProps[ii].name, CLErrString(status));
327         continue;
328      }
329      if (size > sizeof val) {
330         Warning("\tdevice[%p]: Large %s (%d bytes)!  Truncating to %d!\n",
331                 device, longProps[ii].name, size, sizeof val);
332      }
333      printf("\tdevice[%p]: %s: %lld\n",
334             device, longProps[ii].name, val);
335      if (longProps[ii].param == CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS) {
336        long v[16];
337        int i;
338        status = clGetDeviceInfo(device, CL_DEVICE_MAX_WORK_ITEM_SIZES, sizeof(v), v, &size);
339        printf("\tdevice[%p]: %s: ", device, "CL_DEVICE_MAX_WORK_ITEM_SIZES");
340        for (i=0; i<val; i++)
341          printf("%lld%s", v[i], i == val-1 ? "\n" : ", ");
342      }
343   }
344}
345
346
347/*
348 * PrintPlatform --
349 *
350 *      Dumps everything about the given platform ID.
351 *
352 * Results:
353 *      void.
354 */
355
356static void
357PrintPlatform(cl_platform_id platform) {
358   static struct { cl_platform_info param; const char *name; } props[] = {
359      { CL_PLATFORM_PROFILE, "profile" },
360      { CL_PLATFORM_VERSION, "version" },
361      { CL_PLATFORM_NAME, "name" },
362      { CL_PLATFORM_VENDOR, "vendor" },
363      { CL_PLATFORM_EXTENSIONS, "extensions" },
364      { 0, NULL },
365   };
366   cl_device_id *deviceList;
367   cl_uint numDevices;
368   cl_int status;
369   char buf[65536];
370   size_t size;
371   int ii;
372
373   for (ii = 0; props[ii].name != NULL; ii++) {
374      status = clGetPlatformInfo(platform, props[ii].param, sizeof buf, buf, &size);
375      if (status != CL_SUCCESS) {
376         Warning("platform[%p]: Unable to get %s: %s\n",
377                 platform, props[ii].name, CLErrString(status));
378         continue;
379      }
380      if (size > sizeof buf) {
381         Warning("platform[%p]: Huge %s (%d bytes)!  Truncating to %d\n",
382                 platform, props[ii].name, size, sizeof buf);
383      }
384      printf("platform[%p]: %s: %s\n", platform, props[ii].name, buf);
385   }
386
387   if ((status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL,
388                                0, NULL, &numDevices)) != CL_SUCCESS) {
389      Warning("platform[%p]: Unable to query the number of devices: %s\n",
390              platform, CLErrString(status));
391      return;
392   }
393   printf("platform[%p]: Found %d device(s).\n", platform, numDevices);
394
395   deviceList = malloc(numDevices * sizeof(cl_device_id));
396   if ((status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL,
397                                numDevices, deviceList, NULL)) != CL_SUCCESS) {
398      Warning("platform[%p]: Unable to enumerate the devices: %s\n",
399              platform, CLErrString(status));
400      free(deviceList);
401      return;
402   }
403
404   for (ii = 0; ii < numDevices; ii++) {
405      PrintDevice(deviceList[ii]);
406   }
407
408   free(deviceList);
409}
410
411
412int
413main(int argc, char * argv[])
414{
415    Opts opts = { 0 };
416    cl_int status;
417    cl_platform_id *platformList;
418    cl_uint numPlatforms;
419    int ii;
420
421    ParseOpts(&opts, argc, argv);
422
423
424    if ((status = clGetPlatformIDs(0, NULL, &numPlatforms)) != CL_SUCCESS) {
425       Warning("Unable to query the number of platforms: %s\n",
426               CLErrString(status));
427       exit(1);
428    }
429    printf("Found %d platform(s).\n", numPlatforms);
430
431    platformList = malloc(sizeof(cl_platform_id) * numPlatforms);
432    if ((status = clGetPlatformIDs(numPlatforms, platformList, NULL)) != CL_SUCCESS) {
433       Warning("Unable to enumerate the platforms: %s\n",
434               CLErrString(status));
435       exit(1);
436    }
437
438    for (ii = 0; ii < numPlatforms; ii++) {
439       PrintPlatform(platformList[ii]);
440    }
441
442    free(platformList);
443    exit(0);
444}