SCM Repository
View of /branches/vis12/src/lib/cl-target/clinfo.c
Parent Directory
|
Revision Log
Revision 2075 -
(download)
(as text)
(annotate)
Sat Nov 3 13:27:02 2012 UTC (9 years, 6 months ago) by jhr
File size: 12819 byte(s)
Sat Nov 3 13:27:02 2012 UTC (9 years, 6 months ago) by jhr
File size: 12819 byte(s)
Added clinfo command-line tool
/*! \file clinfo.c * * \author John Reppy * * \brief This file contains functions that can be used to determine properties of the * host machine's OpenCL support. */ /* * COPYRIGHT (c) 2011 The Diderot Project (http://diderot-language.cs.uchicago.edu) * All rights reserved. */ #include "Diderot/clinfo.h" #include <stdio.h> #include <string.h> #include <stdlib.h> #define MAX_PLATFORMS 16 static bool GetDevices (unsigned int platIdx, PlatformInfo_t *plat); #define CHECK(call) do { \ cl_int __sts = call; \ if (__sts != CL_SUCCESS) { \ fprintf(stderr, "error %d at %s:%d\n", __sts, __FILE__, __LINE__); \ exit (1); \ } \ } while (0) //! Checked memory allocation STATIC_INLINE void *CheckedAlloc (size_t szb) { void *p = malloc(szb); if (p == 0) { fprintf (stderr, "fatal error: unable to allocate %d bytes of memory\n", (int)szb); exit (1); } return p; } #define NEW(ty) (ty *)CheckedAlloc(sizeof(ty)) #define NEWVEC(ty,n) (ty *)CheckedAlloc(sizeof(ty) * (n)) #define NEWSTR(s) strcpy((char *)CheckedAlloc(strlen(s)+1), s) #define FREE(p) do { if (p != 0) free(p); } while(0) CLInfo_t *Diderot_GetCLInfo () { cl_platform_id platformIDs[MAX_PLATFORMS]; char buf[512]; // get platform info // get number of OpenCL platforms cl_uint numPlatforms; CHECK(clGetPlatformIDs (MAX_PLATFORMS, platformIDs, &numPlatforms)); PlatformInfo_t *plats = NEWVEC(PlatformInfo_t, numPlatforms); for (unsigned int i = 0; i < numPlatforms; i++) { clGetPlatformInfo (platformIDs[i], CL_PLATFORM_NAME, sizeof(buf), buf, 0); plats[i].name = NEWSTR(buf); plats[i].id = platformIDs[i]; // get OpenCL version info clGetPlatformInfo (platformIDs[i], CL_PLATFORM_VERSION, sizeof(buf), buf, 0); // get extension info // FIXME: TODO // get device info if (! GetDevices (i, &(plats[i]))) { // free storage for (unsigned int j = 0; j <= i; j++) { free (plats[i].name); } free (plats); } } CLInfo_t *info = NEW(CLInfo_t); info->numPlatforms = numPlatforms; info->platforms = plats; return info; } static char *GetStringInfo (cl_device_id dev, cl_device_info param) { char buf[1024]; CHECK(clGetDeviceInfo (dev, param, sizeof(buf), buf, 0)); return NEWSTR(buf); } static bool GetDevices (unsigned int platIdx, PlatformInfo_t *plat) { cl_uint numDevs; char buf[512]; // get number of devices for the platform clGetDeviceIDs (plat->id, CL_DEVICE_TYPE_ALL, 0, 0, &numDevs); if (numDevs == 0) { plat->numDevices = 0; plat->devices = 0; return false; } plat->numDevices = numDevs; plat->devices = NEWVEC(DeviceInfo_t, numDevs); cl_device_id *devices = NEWVEC(cl_device_id, numDevs); CHECK(clGetDeviceIDs (plat->id, CL_DEVICE_TYPE_ALL, numDevs, devices, 0)); for (unsigned int i = 0; i < numDevs; i++) { DeviceInfo_t *dev = &(plat->devices[i]); dev->index[0] = platIdx; dev->index[1] = i; dev->name = GetStringInfo(devices[i], CL_DEVICE_NAME); dev->vendor = GetStringInfo(devices[i], CL_DEVICE_VENDOR); dev->id = devices[i]; CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_VERSION, sizeof(buf), buf, 0)); if (sscanf (buf, "OpenCL %d.%d", &(dev->majorVersion), &(dev->minorVersion)) != 2) { fprintf(stderr, "error scanning version string: \"%s\"\n", buf); exit (1); } CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_TYPE, sizeof(cl_device_type), &(dev->ty), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_AVAILABLE, sizeof(cl_bool), &(dev->isAvail), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_ADDRESS_BITS, sizeof(cl_uint), &(dev->addrBits), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_ENDIAN_LITTLE, sizeof(cl_bool), &(dev->littleEndian), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &(dev->numCUs), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_CONSTANT_ARGS, sizeof(cl_uint), &(dev->maxConstArgs), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS, sizeof(cl_uint), &(dev->maxWIDims), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &(dev->maxWGSize), 0)); size_t szb = sizeof(size_t) * dev->maxWIDims; dev->maxWISize = (size_t *) CheckedAlloc (szb); CHECK(clGetDeviceInfo (devices[i], CL_DEVICE_MAX_WORK_ITEM_SIZES, szb, dev->maxWISize, 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &(dev->globalMemSzb), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), &(dev->localMemSzb), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_PARAMETER_SIZE, sizeof(size_t), &(dev->maxParamSzb), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE, sizeof(cl_ulong), &(dev->maxConstBufSzb), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &(dev->maxAllocSzb), 0)); cl_bool imagesSupported; CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_IMAGE_SUPPORT, sizeof(cl_bool), &imagesSupported, 0)); if (imagesSupported) { CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_IMAGE2D_MAX_WIDTH, sizeof(size_t), &(dev->maxImg2D[0]), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &(dev->maxImg2D[1]), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_IMAGE3D_MAX_WIDTH, sizeof(size_t), &(dev->maxImg3D[0]), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_IMAGE3D_MAX_HEIGHT, sizeof(size_t), &(dev->maxImg3D[1]), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_IMAGE3D_MAX_DEPTH, sizeof(size_t), &(dev->maxImg3D[2]), 0)); } else { dev->maxImg2D[0] = dev->maxImg2D[1] = 0; dev->maxImg3D[0] = dev->maxImg3D[1] = dev->maxImg3D[2] = 0; } CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->charWid), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->shortWid), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->intWid), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->longWid), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->floatWid), 0)); CHECK(clGetDeviceInfo ( devices[i], CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR, sizeof(cl_uint), &(dev->doubleWid), 0)); // determine the compute-unit width if (isCPUDevice(dev)) dev->cuWidth = 1; else if (isGPUDevice(dev)) if (strcasecmp("AMD", dev->vendor) == 0) dev->cuWidth = 64; // an AMD wavefront is 64-wide else if (strcasecmp("NVIDIA", dev->vendor) == 0) dev->cuWidth = 32; // an NVIDIA warp is 32-wide else dev->cuWidth = 32; // FIXME: not sure what this should be? else dev->cuWidth = 1; // FIXME: not sure what this should be? } free(devices); return true; } /*! \brief return the device with the given index. */ DeviceInfo_t *Diderot_GetDeviceByIndex (CLInfo_t *clinfo, unsigned int platIdx, unsigned int devIdx) { if ((clinfo == 0) || (clinfo->numPlatforms <= platIdx) || (clinfo->platforms[platIdx].numDevices <= devIdx)) return 0; else return &(clinfo->platforms[platIdx].devices[devIdx]); } void Diderot_PrintCLInfo (FILE *outS, CLInfo_t *clinfo) { if (clinfo->numPlatforms == 0) { fprintf(outS, "No OpenCL platforms\n"); return; } fprintf(outS, "OpenCL profile:\n"); for (unsigned int i = 0; i < clinfo->numPlatforms; i++) { PlatformInfo_t *plat = &(clinfo->platforms[i]); fprintf (outS, " Platform %d (%s)\n", i, plat->name); for (unsigned int j = 0; j < plat->numDevices; j++) { DeviceInfo_t *dev = &(plat->devices[j]); if (dev->isAvail) fprintf (outS, " Device %d.%d (%s):\n", i, j, dev->name); else fprintf (outS, " Device %d.%d (%s): **UNAVAILABLE**\n", i, j, dev->name); fprintf (outS, " Vendor: %s\n", dev->vendor); fprintf (outS, " OpenCL version: %d.%d\n", dev->majorVersion, dev->minorVersion); fprintf (outS, " Type: "); if (isCPUDevice(dev)) fprintf (outS, " CPU"); if (isGPUDevice(dev)) fprintf (outS, " GPU"); if (dev->ty & CL_DEVICE_TYPE_ACCELERATOR) fprintf (outS, " ACCELERATOR"); if (dev->ty & CL_DEVICE_TYPE_DEFAULT) fprintf (outS, " DEFAULT"); fprintf (outS, "\n"); fprintf (outS, " Address size: %d\n", dev->addrBits); fprintf (outS, " Endianess: %s\n", dev->littleEndian ? "LITTLE" : "BIG"); fprintf (outS, " Num. compute units: %d", dev->numCUs); if (dev->cuWidth > 1) fprintf (outS, " * %d\n", dev->cuWidth); else fprintf (outS, "\n"); fprintf (outS, " Max. dimensions: %d\n", dev->maxWIDims); fprintf (outS, " Max. work group size: %ld\n", (long)(dev->maxWGSize)); fprintf (outS, " Max. work items: "); for (int k = 0; k < dev->maxWIDims; k++) fprintf (outS, "%s%ld", (k > 0) ? " x " : "", (long)(dev->maxWISize[k])); fprintf (outS, "\n"); fprintf (outS, " Global memory size: %ld\n", (long)(dev->globalMemSzb)); fprintf (outS, " Local memory size: %ld\n", (long)(dev->localMemSzb)); fprintf (outS, " Max. parameter size: %ld\n", (long)(dev->maxParamSzb)); fprintf (outS, " Max. allocation size: %ld\n", (long)(dev->maxAllocSzb)); fprintf (outS, " Max. const. buffer size: %ld\n", (long)(dev->maxConstBufSzb)); fprintf (outS, " Max. const. arguments: %d\n", dev->maxConstArgs); fprintf (outS, " Max. 2D image size: %ld x %ld\n", (long)(dev->maxImg2D[0]), (long)(dev->maxImg2D[1])); fprintf (outS, " Max. 3D image size: %ld x %ld x %ld\n", (long)(dev->maxImg3D[0]), (long)(dev->maxImg3D[1]), (long)(dev->maxImg3D[2])); fprintf (outS, " Prefered vector width: char%d, short%d, int%d, long%d\n", dev->charWid, dev->shortWid, dev->intWid, dev->longWid); fprintf (outS, " float%d", dev->floatWid); if (dev->doubleWid > 0) fprintf (outS, ", double%d\n", dev->doubleWid); else fprintf (outS, "\n"); } } } DeviceInfo_t *Diderot_DefaultCLDevice (CLInfo_t *clinfo) { if ((clinfo == 0) || (clinfo->numPlatforms == 0)) return 0; // we pick the first GPU device that we find for (unsigned int i = 0; i < clinfo->numPlatforms; i++) { PlatformInfo_t *plat = &(clinfo->platforms[i]); for (unsigned int j = 0; j < plat->numDevices; j++) { if (isGPUDevice(&(plat->devices[j]))) return &(plat->devices[j]); } } // otherwise we pick a CPU device for (unsigned int i = 0; i < clinfo->numPlatforms; i++) { PlatformInfo_t *plat = &(clinfo->platforms[i]); for (unsigned int j = 0; j < plat->numDevices; j++) { if (isCPUDevice(&(plat->devices[j]))) return &(plat->devices[j]); } } // otherwise return 0 return 0; }
root@smlnj-gforge.cs.uchicago.edu | ViewVC Help |
Powered by ViewVC 1.0.0 |