SCM Repository
Annotation of /branches/lamont/src/lib/cl-target/clinfo.c
Parent Directory
|
Revision Log
Revision 2081 - (view) (download) (as text)
1 : | jhr | 1671 | /*! \file clinfo.c |
2 : | * | ||
3 : | * \author John Reppy | ||
4 : | * | ||
5 : | * \brief This file contains functions that can be used to determine properties of the | ||
6 : | * host machine's OpenCL support. | ||
7 : | */ | ||
8 : | |||
9 : | /* | ||
10 : | * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu) | ||
11 : | * All rights reserved. | ||
12 : | */ | ||
13 : | |||
14 : | jhr | 2075 | #include "Diderot/clinfo.h" |
15 : | jhr | 1671 | #include <stdio.h> |
16 : | #include <string.h> | ||
17 : | #include <stdlib.h> | ||
18 : | |||
19 : | #define MAX_PLATFORMS 16 | ||
20 : | |||
21 : | jhr | 2075 | static bool GetDevices (unsigned int platIdx, PlatformInfo_t *plat); |
22 : | jhr | 1671 | |
23 : | #define CHECK(call) do { \ | ||
24 : | cl_int __sts = call; \ | ||
25 : | if (__sts != CL_SUCCESS) { \ | ||
26 : | fprintf(stderr, "error %d at %s:%d\n", __sts, __FILE__, __LINE__); \ | ||
27 : | exit (1); \ | ||
28 : | } \ | ||
29 : | } while (0) | ||
30 : | |||
31 : | jhr | 2075 | //! Checked memory allocation |
32 : | STATIC_INLINE void *CheckedAlloc (size_t szb) | ||
33 : | { | ||
34 : | void *p = malloc(szb); | ||
35 : | if (p == 0) { | ||
36 : | fprintf (stderr, "fatal error: unable to allocate %d bytes of memory\n", (int)szb); | ||
37 : | exit (1); | ||
38 : | } | ||
39 : | return p; | ||
40 : | } | ||
41 : | jhr | 1671 | |
42 : | jhr | 2075 | #define NEW(ty) (ty *)CheckedAlloc(sizeof(ty)) |
43 : | #define NEWVEC(ty,n) (ty *)CheckedAlloc(sizeof(ty) * (n)) | ||
44 : | #define NEWSTR(s) strcpy((char *)CheckedAlloc(strlen(s)+1), s) | ||
45 : | #define FREE(p) do { if (p != 0) free(p); } while(0) | ||
46 : | |||
47 : | CLInfo_t *Diderot_GetCLInfo () | ||
48 : | jhr | 1671 | { |
49 : | cl_platform_id platformIDs[MAX_PLATFORMS]; | ||
50 : | char buf[512]; | ||
51 : | |||
52 : | // get platform info | ||
53 : | // get number of OpenCL platforms | ||
54 : | cl_uint numPlatforms; | ||
55 : | CHECK(clGetPlatformIDs (MAX_PLATFORMS, platformIDs, &numPlatforms)); | ||
56 : | |||
57 : | PlatformInfo_t *plats = NEWVEC(PlatformInfo_t, numPlatforms); | ||
58 : | jhr | 2075 | for (unsigned int i = 0; i < numPlatforms; i++) { |
59 : | jhr | 1671 | clGetPlatformInfo (platformIDs[i], CL_PLATFORM_NAME, sizeof(buf), buf, 0); |
60 : | plats[i].name = NEWSTR(buf); | ||
61 : | plats[i].id = platformIDs[i]; | ||
62 : | // get OpenCL version info | ||
63 : | clGetPlatformInfo (platformIDs[i], CL_PLATFORM_VERSION, sizeof(buf), buf, 0); | ||
64 : | // get extension info | ||
65 : | // FIXME: TODO | ||
66 : | // get device info | ||
67 : | jhr | 2075 | if (! GetDevices (i, &(plats[i]))) { |
68 : | jhr | 1671 | // free storage |
69 : | jhr | 2075 | for (unsigned int j = 0; j <= i; j++) { |
70 : | jhr | 1671 | free (plats[i].name); |
71 : | } | ||
72 : | free (plats); | ||
73 : | } | ||
74 : | } | ||
75 : | |||
76 : | CLInfo_t *info = NEW(CLInfo_t); | ||
77 : | info->numPlatforms = numPlatforms; | ||
78 : | info->platforms = plats; | ||
79 : | |||
80 : | return info; | ||
81 : | |||
82 : | } | ||
83 : | |||
84 : | static char *GetStringInfo (cl_device_id dev, cl_device_info param) | ||
85 : | { | ||
86 : | char buf[1024]; | ||
87 : | CHECK(clGetDeviceInfo (dev, param, sizeof(buf), buf, 0)); | ||
88 : | return NEWSTR(buf); | ||
89 : | } | ||
90 : | |||
91 : | jhr | 2075 | static bool GetDevices (unsigned int platIdx, PlatformInfo_t *plat) |
92 : | jhr | 1671 | { |
93 : | cl_uint numDevs; | ||
94 : | char buf[512]; | ||
95 : | |||
96 : | // get number of devices for the platform | ||
97 : | clGetDeviceIDs (plat->id, CL_DEVICE_TYPE_ALL, 0, 0, &numDevs); | ||
98 : | |||
99 : | if (numDevs == 0) { | ||
100 : | plat->numDevices = 0; | ||
101 : | plat->devices = 0; | ||
102 : | return false; | ||
103 : | } | ||
104 : | |||
105 : | plat->numDevices = numDevs; | ||
106 : | plat->devices = NEWVEC(DeviceInfo_t, numDevs); | ||
107 : | |||
108 : | cl_device_id *devices = NEWVEC(cl_device_id, numDevs); | ||
109 : | CHECK(clGetDeviceIDs (plat->id, CL_DEVICE_TYPE_ALL, numDevs, devices, 0)); | ||
110 : | |||
111 : | jhr | 2075 | for (unsigned int i = 0; i < numDevs; i++) { |
112 : | jhr | 1671 | DeviceInfo_t *dev = &(plat->devices[i]); |
113 : | jhr | 2075 | dev->index[0] = platIdx; |
114 : | dev->index[1] = i; | ||
115 : | jhr | 1671 | dev->name = GetStringInfo(devices[i], CL_DEVICE_NAME); |
116 : | dev->vendor = GetStringInfo(devices[i], CL_DEVICE_VENDOR); | ||
117 : | dev->id = devices[i]; | ||
118 : | CHECK(clGetDeviceInfo ( | ||
119 : | devices[i], CL_DEVICE_VERSION, sizeof(buf), buf, 0)); | ||
120 : | if (sscanf (buf, "OpenCL %d.%d", &(dev->majorVersion), &(dev->minorVersion)) != 2) { | ||
121 : | fprintf(stderr, "error scanning version string: \"%s\"\n", buf); | ||
122 : | exit (1); | ||
123 : | } | ||
124 : | CHECK(clGetDeviceInfo ( | ||
125 : | devices[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &(dev->ty), 0)); | ||
126 : | CHECK(clGetDeviceInfo ( | ||
127 : | devices[i], CL_DEVICE_AVAILABLE, sizeof(cl_bool), &(dev->isAvail), 0)); | ||
128 : | CHECK(clGetDeviceInfo ( | ||
129 : | devices[i], CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint), &(dev->addrBits), 0)); | ||
130 : | CHECK(clGetDeviceInfo ( | ||
131 : | devices[i], CL_DEVICE_ENDIAN_LITTLE, sizeof(cl_bool), &(dev->littleEndian), 0)); | ||
132 : | CHECK(clGetDeviceInfo ( | ||
133 : | devices[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &(dev->numCUs), 0)); | ||
134 : | CHECK(clGetDeviceInfo ( | ||
135 : | devices[i], CL_DEVICE_MAX_CONSTANT_ARGS, sizeof(cl_uint), &(dev->maxConstArgs), 0)); | ||
136 : | CHECK(clGetDeviceInfo ( | ||
137 : | devices[i], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(cl_uint), &(dev->maxWIDims), 0)); | ||
138 : | CHECK(clGetDeviceInfo ( | ||
139 : | devices[i], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &(dev->maxWGSize), 0)); | ||
140 : | size_t szb = sizeof(size_t) * dev->maxWIDims; | ||
141 : | dev->maxWISize = (size_t *) CheckedAlloc (szb); | ||
142 : | CHECK(clGetDeviceInfo (devices[i], CL_DEVICE_MAX_WORK_ITEM_SIZES, szb, dev->maxWISize, 0)); | ||
143 : | CHECK(clGetDeviceInfo ( | ||
144 : | devices[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &(dev->globalMemSzb), 0)); | ||
145 : | CHECK(clGetDeviceInfo ( | ||
146 : | devices[i], CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), &(dev->localMemSzb), 0)); | ||
147 : | CHECK(clGetDeviceInfo ( | ||
148 : | devices[i], CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(size_t), &(dev->maxParamSzb), 0)); | ||
149 : | CHECK(clGetDeviceInfo ( | ||
150 : | devices[i], CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(cl_ulong), &(dev->maxConstBufSzb), 0)); | ||
151 : | CHECK(clGetDeviceInfo ( | ||
152 : | devices[i], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &(dev->maxAllocSzb), 0)); | ||
153 : | cl_bool imagesSupported; | ||
154 : | CHECK(clGetDeviceInfo ( | ||
155 : | devices[i], CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &imagesSupported, 0)); | ||
156 : | if (imagesSupported) { | ||
157 : | CHECK(clGetDeviceInfo ( | ||
158 : | devices[i], CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &(dev->maxImg2D[0]), 0)); | ||
159 : | CHECK(clGetDeviceInfo ( | ||
160 : | devices[i], CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &(dev->maxImg2D[1]), 0)); | ||
161 : | CHECK(clGetDeviceInfo ( | ||
162 : | devices[i], CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &(dev->maxImg3D[0]), 0)); | ||
163 : | CHECK(clGetDeviceInfo ( | ||
164 : | devices[i], CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &(dev->maxImg3D[1]), 0)); | ||
165 : | CHECK(clGetDeviceInfo ( | ||
166 : | devices[i], CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &(dev->maxImg3D[2]), 0)); | ||
167 : | } | ||
168 : | else { | ||
169 : | dev->maxImg2D[0] = dev->maxImg2D[1] = 0; | ||
170 : | dev->maxImg3D[0] = dev->maxImg3D[1] = dev->maxImg3D[2] = 0; | ||
171 : | } | ||
172 : | CHECK(clGetDeviceInfo ( | ||
173 : | devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->charWid), 0)); | ||
174 : | CHECK(clGetDeviceInfo ( | ||
175 : | devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->shortWid), 0)); | ||
176 : | CHECK(clGetDeviceInfo ( | ||
177 : | devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->intWid), 0)); | ||
178 : | CHECK(clGetDeviceInfo ( | ||
179 : | devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->longWid), 0)); | ||
180 : | CHECK(clGetDeviceInfo ( | ||
181 : | devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->floatWid), 0)); | ||
182 : | CHECK(clGetDeviceInfo ( | ||
183 : | devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->doubleWid), 0)); | ||
184 : | // determine the compute-unit width | ||
185 : | if (isCPUDevice(dev)) | ||
186 : | dev->cuWidth = 1; | ||
187 : | else if (isGPUDevice(dev)) | ||
188 : | if (strcasecmp("AMD", dev->vendor) == 0) | ||
189 : | dev->cuWidth = 64; // an AMD wavefront is 64-wide | ||
190 : | else if (strcasecmp("NVIDIA", dev->vendor) == 0) | ||
191 : | dev->cuWidth = 32; // an NVIDIA warp is 32-wide | ||
192 : | else | ||
193 : | dev->cuWidth = 32; // FIXME: not sure what this should be? | ||
194 : | else | ||
195 : | dev->cuWidth = 1; // FIXME: not sure what this should be? | ||
196 : | |||
197 : | } | ||
198 : | |||
199 : | free(devices); | ||
200 : | |||
201 : | return true; | ||
202 : | } | ||
203 : | |||
204 : | jhr | 2075 | /*! \brief return the device with the given index. |
205 : | */ | ||
206 : | DeviceInfo_t *Diderot_GetDeviceByIndex (CLInfo_t *clinfo, unsigned int platIdx, unsigned int devIdx) | ||
207 : | jhr | 1671 | { |
208 : | jhr | 2075 | if ((clinfo == 0) |
209 : | || (clinfo->numPlatforms <= platIdx) | ||
210 : | || (clinfo->platforms[platIdx].numDevices <= devIdx)) | ||
211 : | return 0; | ||
212 : | else | ||
213 : | return &(clinfo->platforms[platIdx].devices[devIdx]); | ||
214 : | } | ||
215 : | |||
216 : | void Diderot_PrintCLInfo (FILE *outS, CLInfo_t *clinfo) | ||
217 : | { | ||
218 : | jhr | 1671 | if (clinfo->numPlatforms == 0) { |
219 : | fprintf(outS, "No OpenCL platforms\n"); | ||
220 : | return; | ||
221 : | } | ||
222 : | |||
223 : | fprintf(outS, "OpenCL profile:\n"); | ||
224 : | jhr | 2075 | for (unsigned int i = 0; i < clinfo->numPlatforms; i++) { |
225 : | jhr | 1671 | PlatformInfo_t *plat = &(clinfo->platforms[i]); |
226 : | fprintf (outS, " Platform %d (%s)\n", i, plat->name); | ||
227 : | jhr | 2075 | for (unsigned int j = 0; j < plat->numDevices; j++) { |
228 : | jhr | 1671 | DeviceInfo_t *dev = &(plat->devices[j]); |
229 : | if (dev->isAvail) | ||
230 : | fprintf (outS, " Device %d.%d (%s):\n", i, j, dev->name); | ||
231 : | else | ||
232 : | fprintf (outS, " Device %d.%d (%s): **UNAVAILABLE**\n", i, j, dev->name); | ||
233 : | fprintf (outS, " Vendor: %s\n", dev->vendor); | ||
234 : | fprintf (outS, " OpenCL version: %d.%d\n", | ||
235 : | dev->majorVersion, dev->minorVersion); | ||
236 : | fprintf (outS, " Type: "); | ||
237 : | if (isCPUDevice(dev)) fprintf (outS, " CPU"); | ||
238 : | if (isGPUDevice(dev)) fprintf (outS, " GPU"); | ||
239 : | if (dev->ty & CL_DEVICE_TYPE_ACCELERATOR) fprintf (outS, " ACCELERATOR"); | ||
240 : | if (dev->ty & CL_DEVICE_TYPE_DEFAULT) fprintf (outS, " DEFAULT"); | ||
241 : | fprintf (outS, "\n"); | ||
242 : | fprintf (outS, " Address size: %d\n", dev->addrBits); | ||
243 : | fprintf (outS, " Endianess: %s\n", dev->littleEndian ? "LITTLE" : "BIG"); | ||
244 : | fprintf (outS, " Num. compute units: %d", dev->numCUs); | ||
245 : | if (dev->cuWidth > 1) | ||
246 : | fprintf (outS, " * %d\n", dev->cuWidth); | ||
247 : | else | ||
248 : | fprintf (outS, "\n"); | ||
249 : | fprintf (outS, " Max. dimensions: %d\n", dev->maxWIDims); | ||
250 : | fprintf (outS, " Max. work group size: %ld\n", (long)(dev->maxWGSize)); | ||
251 : | fprintf (outS, " Max. work items: "); | ||
252 : | for (int k = 0; k < dev->maxWIDims; k++) | ||
253 : | fprintf (outS, "%s%ld", (k > 0) ? " x " : "", (long)(dev->maxWISize[k])); | ||
254 : | fprintf (outS, "\n"); | ||
255 : | fprintf (outS, " Global memory size: %ld\n", (long)(dev->globalMemSzb)); | ||
256 : | fprintf (outS, " Local memory size: %ld\n", (long)(dev->localMemSzb)); | ||
257 : | fprintf (outS, " Max. parameter size: %ld\n", (long)(dev->maxParamSzb)); | ||
258 : | fprintf (outS, " Max. allocation size: %ld\n", (long)(dev->maxAllocSzb)); | ||
259 : | fprintf (outS, " Max. const. buffer size: %ld\n", (long)(dev->maxConstBufSzb)); | ||
260 : | fprintf (outS, " Max. const. arguments: %d\n", dev->maxConstArgs); | ||
261 : | fprintf (outS, " Max. 2D image size: %ld x %ld\n", | ||
262 : | (long)(dev->maxImg2D[0]), (long)(dev->maxImg2D[1])); | ||
263 : | fprintf (outS, " Max. 3D image size: %ld x %ld x %ld\n", | ||
264 : | (long)(dev->maxImg3D[0]), (long)(dev->maxImg3D[1]), (long)(dev->maxImg3D[2])); | ||
265 : | fprintf (outS, " Prefered vector width: char%d, short%d, int%d, long%d\n", | ||
266 : | dev->charWid, dev->shortWid, dev->intWid, dev->longWid); | ||
267 : | fprintf (outS, " float%d", dev->floatWid); | ||
268 : | if (dev->doubleWid > 0) | ||
269 : | fprintf (outS, ", double%d\n", dev->doubleWid); | ||
270 : | else | ||
271 : | fprintf (outS, "\n"); | ||
272 : | } | ||
273 : | } | ||
274 : | |||
275 : | } | ||
276 : | jhr | 2075 | |
277 : | DeviceInfo_t *Diderot_DefaultCLDevice (CLInfo_t *clinfo) | ||
278 : | { | ||
279 : | if ((clinfo == 0) || (clinfo->numPlatforms == 0)) | ||
280 : | return 0; | ||
281 : | |||
282 : | // we pick the first GPU device that we find | ||
283 : | for (unsigned int i = 0; i < clinfo->numPlatforms; i++) { | ||
284 : | PlatformInfo_t *plat = &(clinfo->platforms[i]); | ||
285 : | for (unsigned int j = 0; j < plat->numDevices; j++) { | ||
286 : | if (isGPUDevice(&(plat->devices[j]))) | ||
287 : | return &(plat->devices[j]); | ||
288 : | } | ||
289 : | } | ||
290 : | |||
291 : | // otherwise we pick a CPU device | ||
292 : | for (unsigned int i = 0; i < clinfo->numPlatforms; i++) { | ||
293 : | PlatformInfo_t *plat = &(clinfo->platforms[i]); | ||
294 : | for (unsigned int j = 0; j < plat->numDevices; j++) { | ||
295 : | if (isCPUDevice(&(plat->devices[j]))) | ||
296 : | return &(plat->devices[j]); | ||
297 : | } | ||
298 : | } | ||
299 : | |||
300 : | // otherwise return 0 | ||
301 : | return 0; | ||
302 : | |||
303 : | } |
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |