00001 /*************************************************************************** 00002 *cr 00003 *cr (C) Copyright 1995-2019 The Board of Trustees of the 00004 *cr University of Illinois 00005 *cr All Rights Reserved 00006 *cr 00007 ***************************************************************************/ 00008 00009 /*************************************************************************** 00010 * RCS INFORMATION: 00011 * 00012 * $RCSfile: OpenCLUtils.C,v $ 00013 * $Author: johns $ $Locker: $ $State: Exp $ 00014 * $Revision: 1.14 $ $Date: 2019年01月17日 21:38:55 $ 00015 * 00016 *************************************************************************** 00017 * DESCRIPTION: 00018 * OpenCL utility functions for use in VMD 00019 * 00020 ***************************************************************************/ 00021 00022 #include <stdio.h> 00023 #include <stdlib.h> 00024 #include <string.h> 00025 #include <sys/stat.h> 00026 #include <sys/types.h> 00027 00028 #if defined(__APPLE__) 00029 #include <OpenCL/cl.h> 00030 #else 00031 #include <CL/cl.h> 00032 #endif 00033 00034 #if defined(VMDOPENCL) 00035 #include "Inform.h" 00036 #endif 00037 00038 int vmd_cl_print_platform_info(void) { 00039 cl_int clerr; 00040 cl_uint numplatforms; 00041 cl_platform_id *platformlist; 00042 clerr=clGetPlatformIDs(0, NULL, &numplatforms); 00043 platformlist = (cl_platform_id *) malloc(sizeof(cl_platform_id)*numplatforms); 00044 clerr=clGetPlatformIDs(numplatforms, platformlist, NULL); 00045 00046 cl_uint i; 00047 for (i=0; i<numplatforms; i++) { 00048 char platname[80]; 00049 clerr=clGetPlatformInfo(platformlist[i], CL_PLATFORM_NAME, 00050 sizeof(platname), (void *) platname, NULL); 00051 00052 char platprofile[80]; 00053 clerr=clGetPlatformInfo(platformlist[i], CL_PLATFORM_PROFILE, 00054 sizeof(platprofile), (void *) platprofile, NULL); 00055 00056 #if 0 00057 char platvendor[80]; 00058 clerr=clGetPlatformInfo(platformlist[i], CL_PLATFORM_VENDOR, 00059 sizeof(platvendor), (void *) platvendor, NULL); 00060 #endif 00061 00062 cl_uint numdevs; 00063 clerr=clGetDeviceIDs(platformlist[i], CL_DEVICE_TYPE_ALL, 00064 0, NULL, &numdevs); 00065 00066 char platforminfo[4096]; 00067 #if !defined(VMDOPENCL) 00068 printf("OpenCL Platform[%d]: %s, %s Devices: %u\n", 00069 i, platname, platprofile, numdevs); 00070 #else 00071 sprintf(platforminfo, "OpenCL Platform[%d]: %s, %s Devices: %u\n", 00072 i, platname, platprofile, numdevs); 00073 msgInfo << platforminfo << sendmsg; 00074 #endif 00075 00076 int j; 00077 cl_device_id *devices = new cl_device_id[numdevs]; 00078 clerr = clGetDeviceIDs(platformlist[i], CL_DEVICE_TYPE_ALL, 00079 numdevs, devices, NULL); 00080 for (j=0; j<numdevs; j++) { 00081 char outstr[1024]; 00082 size_t rsz; 00083 cl_uint clockratemhz, computeunits; 00084 cl_ulong globalmemsz; 00085 cl_char long_device_name[1024] = {0}; 00086 cl_char device_name[1024] = {0}; 00087 cl_device_id dev = devices[j]; 00088 00089 clerr |= clGetDeviceInfo(dev, CL_DEVICE_NAME, sizeof(long_device_name), 00090 long_device_name, &rsz); 00091 clerr |= clGetDeviceInfo(dev, CL_DEVICE_MAX_CLOCK_FREQUENCY, 00092 sizeof(clockratemhz), &clockratemhz, &rsz); 00093 clerr |= clGetDeviceInfo(dev, CL_DEVICE_MAX_COMPUTE_UNITS, 00094 sizeof(computeunits), &computeunits, &rsz); 00095 clerr |= clGetDeviceInfo(dev, CL_DEVICE_GLOBAL_MEM_SIZE, 00096 sizeof(globalmemsz), &globalmemsz, &rsz); 00097 00098 if (clerr == CL_SUCCESS) { 00099 // clean up device name string (some contain lots of spaces) 00100 int len = strlen((const char *) long_device_name); 00101 int k,l; 00102 for (k=0,l=0; k<len; k++) { 00103 if (long_device_name[k] != ' ') { 00104 device_name[l] = long_device_name[k]; 00105 l++; 00106 continue; 00107 } 00108 00109 device_name[l] = long_device_name[k]; 00110 l++; 00111 while (k < len) { 00112 if (long_device_name[k+1] == ' ') 00113 k++; 00114 else 00115 break; 00116 } 00117 } 00118 00119 // list primary GPU device attributes 00120 sprintf(outstr, "[%d] %-40s %2d CU @ %.2f GHz", 00121 j, device_name, computeunits, clockratemhz / 1000.0); 00122 msgInfo << outstr; 00123 00124 // list memory capacity 00125 int gpumemmb = globalmemsz / (1024 * 1024); 00126 if (gpumemmb < 1000) 00127 sprintf(outstr, ", %4dMB RAM", gpumemmb); 00128 else if (gpumemmb < 10240) 00129 sprintf(outstr, ", %.1fGB RAM", gpumemmb / 1024.0); 00130 else 00131 sprintf(outstr, ", %dGB RAM", gpumemmb / 1024); 00132 00133 msgInfo << outstr; 00134 00135 // list optional hardware features and configuration attributes here... 00136 // XXX not implemented yet... 00137 00138 msgInfo << sendmsg; 00139 } else { 00140 sprintf(outstr, " [%d] Error during OpenCL device query!", j); 00141 msgInfo << outstr << sendmsg; 00142 00143 clerr = CL_SUCCESS; 00144 } 00145 } 00146 00147 delete [] devices; 00148 } 00149 00150 free(platformlist); 00151 00152 return 0; 00153 } 00154 00155 00156 cl_platform_id vmd_cl_get_platform_index(int i) { 00157 cl_int clerr; 00158 cl_uint numplatforms; 00159 cl_platform_id *platformlist; 00160 cl_platform_id plat; 00161 clerr=clGetPlatformIDs(0, NULL, &numplatforms); 00162 if (i >= (int) numplatforms) 00163 return NULL; 00164 00165 platformlist = (cl_platform_id *) malloc(sizeof(cl_platform_id)*numplatforms); 00166 clerr=clGetPlatformIDs(numplatforms, platformlist, NULL); 00167 if (clerr != CL_SUCCESS) { 00168 free(platformlist); 00169 return NULL; 00170 } 00171 00172 plat=platformlist[i]; 00173 free(platformlist); 00174 00175 return plat; 00176 } 00177 00178 00179 int vmd_cl_context_num_devices(cl_context clctx) { 00180 size_t parmsz; 00181 cl_int clerr = clGetContextInfo(clctx, CL_CONTEXT_DEVICES, 0, NULL, &parmsz); 00182 if (clerr != CL_SUCCESS) 00183 return 0; 00184 00185 return (int) (parmsz / sizeof(size_t)); 00186 } 00187 00188 00189 cl_command_queue vmd_cl_create_command_queue(cl_context clctx, int dev) { 00190 size_t parmsz; 00191 cl_int clerr = clGetContextInfo(clctx, CL_CONTEXT_DEVICES, 0, NULL, &parmsz); 00192 if (clerr != CL_SUCCESS) 00193 return NULL; 00194 00195 cl_device_id* cldevs = (cl_device_id *) malloc(parmsz); 00196 clerr = clGetContextInfo(clctx, CL_CONTEXT_DEVICES, parmsz, cldevs, NULL); 00197 if (clerr != CL_SUCCESS) 00198 return NULL; 00199 00200 cl_command_queue clcmdq = clCreateCommandQueue(clctx, cldevs[dev], 0, &clerr); 00201 free(cldevs); 00202 if (clerr != CL_SUCCESS) 00203 return NULL; 00204 00205 return clcmdq; 00206 } 00207 00208 00209 cl_kernel vmd_cl_compile_kernel(cl_context clctx, const char *kernname, 00210 const char *srctext, const char *flags, 00211 cl_int *clerr, int verbose) { 00212 char buildlog[8192]; 00213 cl_program clpgm = NULL; 00214 cl_kernel clkern = NULL; 00215 00216 clpgm = clCreateProgramWithSource(clctx, 1, &srctext, NULL, clerr); 00217 if (clerr != CL_SUCCESS) { 00218 if (verbose) 00219 printf("Failed to compile OpenCL kernel: '%s'\n", kernname); 00220 return NULL; 00221 } 00222 *clerr = clBuildProgram(clpgm, 0, NULL, flags, NULL, NULL); 00223 00224 #if 1 00225 if (verbose) { 00226 memset(buildlog, 0, sizeof(buildlog)); 00227 00228 size_t parmsz; 00229 *clerr |= clGetContextInfo(clctx, CL_CONTEXT_DEVICES, 0, NULL, &parmsz); 00230 00231 cl_device_id* cldevs = (cl_device_id *) malloc(parmsz); 00232 *clerr |= clGetContextInfo(clctx, CL_CONTEXT_DEVICES, parmsz, cldevs, NULL); 00233 00234 size_t len=0; 00235 *clerr = clGetProgramBuildInfo(clpgm, cldevs[0], CL_PROGRAM_BUILD_LOG, sizeof(buildlog), buildlog, &len); 00236 if (len > 1) { 00237 printf("OpenCL kernel compilation log:\n"); 00238 printf(" '%s'\n", buildlog); 00239 } 00240 } 00241 #endif 00242 00243 clkern = clCreateKernel(clpgm, kernname, clerr); 00244 if (clerr != CL_SUCCESS) { 00245 if (verbose) 00246 printf("Failed to create OpenCL kernel: '%s'\n", kernname); 00247 return NULL; 00248 } 00249 00250 return clkern; 00251 } 00252 00253 00254 cl_kernel vmd_cl_compile_kernel_file(cl_context clctx, const char *kernname, 00255 const char *filename, const char *flags, 00256 cl_int *clerr, int verbose) { 00257 FILE *ifp; 00258 char *src; 00259 struct stat statbuf; 00260 cl_kernel clkern = NULL; 00261 00262 if ((ifp = fopen(filename, "r")) == NULL) 00263 return NULL; 00264 00265 stat(filename, &statbuf); 00266 src = (char *) calloc(1, statbuf.st_size + 1); 00267 fread(src, statbuf.st_size, 1, ifp); 00268 src[statbuf.st_size] = '0円'; 00269 clkern = vmd_cl_compile_kernel(clctx, kernname, src, flags, clerr, verbose); 00270 free(src); 00271 00272 return clkern; 00273 } 00274 00275 00276