tesseract  3.03
/usr/local/google/home/jbreiden/tesseract-ocr-read-only/opencl/opencl_device_selection.h
Go to the documentation of this file.
00001 #ifdef USE_OPENCL
00002 #ifndef DEVICE_SELECTION_H
00003 #define DEVICE_SELECTION_H
00004 
00005 
00006 #ifdef _MSC_VER
00007 #define _CRT_SECURE_NO_WARNINGS
00008 #endif
00009 
00010 #include <stdlib.h>
00011 #include <stdio.h>
00012 #include <string.h>
00013 
00014 #ifdef __APPLE__
00015 #include <OpenCL/cl.h>
00016 #else
00017 #include <CL/cl.h>
00018 #endif
00019 
00020 #define DS_DEVICE_NAME_LENGTH 256
00021 
00022 typedef enum {
00023   DS_SUCCESS = 0,
00024   DS_INVALID_PROFILE = 1000,
00025   DS_MEMORY_ERROR,
00026   DS_INVALID_PERF_EVALUATOR_TYPE,
00027   DS_INVALID_PERF_EVALUATOR,
00028   DS_PERF_EVALUATOR_ERROR,
00029   DS_FILE_ERROR,
00030   DS_UNKNOWN_DEVICE_TYPE,
00031   DS_PROFILE_FILE_ERROR,
00032   DS_SCORE_SERIALIZER_ERROR,
00033   DS_SCORE_DESERIALIZER_ERROR
00034 } ds_status;
00035 
00036 // device type
00037 typedef enum {
00038   DS_DEVICE_NATIVE_CPU = 0,
00039   DS_DEVICE_OPENCL_DEVICE 
00040 } ds_device_type;
00041 
00042 
00043 typedef struct {
00044   ds_device_type  type;
00045   cl_device_id    oclDeviceID;
00046   char*           oclDeviceName;
00047   char*           oclDriverVersion;
00048   // a pointer to the score data, the content/format is application defined.
00049   void*           score;
00050 } ds_device;
00051 
00052 typedef struct {
00053   unsigned int  numDevices;
00054   ds_device*    devices;
00055   const char*   version;
00056 } ds_profile;
00057 
00058 // deallocate memory used by score
00059 typedef ds_status (*ds_score_release)(void* score);
00060 static ds_status releaseDSProfile(ds_profile* profile, ds_score_release sr) {
00061   ds_status status = DS_SUCCESS;
00062   if (profile!=NULL) {
00063     if (profile->devices!=NULL && sr!=NULL) {
00064       unsigned int i;
00065       for (i = 0; i < profile->numDevices; i++) {
00066         status = sr(profile->devices[i].score);
00067         if (status != DS_SUCCESS)
00068           break;
00069       }
00070       free(profile->devices);
00071     }
00072     free(profile);
00073   }
00074   return status;
00075 }
00076 
00077 
00078 static ds_status initDSProfile(ds_profile** p, const char* version) {
00079   int numDevices;
00080   cl_uint numPlatforms;
00081   cl_platform_id* platforms = NULL;
00082   cl_device_id*   devices = NULL;
00083   ds_status status = DS_SUCCESS;
00084   ds_profile* profile = NULL;
00085   unsigned int next;
00086   unsigned int i;
00087 
00088   if (p == NULL)
00089     return DS_INVALID_PROFILE;
00090 
00091   profile = (ds_profile*)malloc(sizeof(ds_profile));
00092   if (profile == NULL)
00093     return DS_MEMORY_ERROR;
00094   
00095   memset(profile, 0, sizeof(ds_profile));
00096 
00097   clGetPlatformIDs(0, NULL, &numPlatforms);
00098   if (numPlatforms == 0)
00099     goto cleanup;
00100 
00101   platforms = (cl_platform_id*)malloc(numPlatforms*sizeof(cl_platform_id));
00102   if (platforms == NULL) {
00103     status = DS_MEMORY_ERROR;
00104     goto cleanup;
00105   }
00106   clGetPlatformIDs(numPlatforms, platforms, NULL);
00107 
00108   numDevices = 0;
00109   for (i = 0; i < (unsigned int)numPlatforms; i++) {
00110     cl_uint num;
00111     clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &num);
00112     numDevices+=num;
00113   }
00114   if (numDevices == 0)
00115     goto cleanup;
00116   
00117   devices = (cl_device_id*)malloc(numDevices*sizeof(cl_device_id));
00118   if (devices == NULL) {
00119     status = DS_MEMORY_ERROR;
00120     goto cleanup;
00121   }
00122 
00123   profile->numDevices = numDevices+1;     // +1 to numDevices to include the native CPU
00124   profile->devices = (ds_device*)malloc(profile->numDevices*sizeof(ds_device));    
00125   if (profile->devices == NULL) {
00126     profile->numDevices = 0;
00127     status = DS_MEMORY_ERROR;
00128     goto cleanup;    
00129   }
00130   memset(profile->devices, 0, profile->numDevices*sizeof(ds_device));
00131 
00132   next = 0;
00133   for (i = 0; i < (unsigned int)numPlatforms; i++) {
00134     cl_uint num;
00135     unsigned j;
00136     clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, numDevices, devices, &num);
00137     for (j = 0; j < num; j++, next++) {
00138       char buffer[DS_DEVICE_NAME_LENGTH];
00139       size_t length;
00140 
00141       profile->devices[next].type = DS_DEVICE_OPENCL_DEVICE;
00142       profile->devices[next].oclDeviceID = devices[j];
00143 
00144       clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DEVICE_NAME
00145         , DS_DEVICE_NAME_LENGTH, &buffer, NULL);
00146       length = strlen(buffer);
00147       profile->devices[next].oclDeviceName = (char*)malloc(length+1);
00148       memcpy(profile->devices[next].oclDeviceName, buffer, length+1);
00149 
00150       clGetDeviceInfo(profile->devices[next].oclDeviceID, CL_DRIVER_VERSION
00151         , DS_DEVICE_NAME_LENGTH, &buffer, NULL);
00152       length = strlen(buffer);
00153       profile->devices[next].oclDriverVersion = (char*)malloc(length+1);
00154       memcpy(profile->devices[next].oclDriverVersion, buffer, length+1);
00155     }
00156   }
00157   profile->devices[next].type = DS_DEVICE_NATIVE_CPU;
00158   profile->version = version;
00159 
00160 cleanup:
00161   if (platforms)  free(platforms);
00162   if (devices)    free(devices);
00163   if (status == DS_SUCCESS) {
00164     *p = profile;
00165   }
00166   else {
00167     if (profile) {
00168       if (profile->devices)
00169         free(profile->devices);
00170       free(profile);
00171     }
00172   }
00173   return status;
00174 }
00175 
00176 // Pointer to a function that calculates the score of a device (ex:
00177 // device->score) update the data size of score. The encoding and the format
00178 // of the score data is implementation defined. The function should return
00179 // DS_SUCCESS if there's no error to be reported.
00180 typedef ds_status (*ds_perf_evaluator)(ds_device* device, void* data);
00181 
00182 typedef enum {
00183   DS_EVALUATE_ALL
00184   ,DS_EVALUATE_NEW_ONLY
00185 } ds_evaluation_type;
00186 
00187 static ds_status profileDevices(ds_profile* profile,
00188                                 const ds_evaluation_type type,
00189                                 ds_perf_evaluator evaluator,
00190                                 void* evaluatorData, unsigned int* numUpdates) {
00191   ds_status status = DS_SUCCESS;
00192   unsigned int i;
00193   unsigned int updates = 0;
00194 
00195   if (profile == NULL) {
00196     return DS_INVALID_PROFILE;
00197   }
00198   if (evaluator == NULL) {
00199     return DS_INVALID_PERF_EVALUATOR;
00200   }
00201 
00202   for (i = 0; i < profile->numDevices; i++) {
00203     ds_status evaluatorStatus;
00204     
00205     switch (type) {
00206     case DS_EVALUATE_NEW_ONLY:
00207       if (profile->devices[i].score != NULL)
00208         break;
00209       //  else fall through
00210     case DS_EVALUATE_ALL:
00211       evaluatorStatus = evaluator(profile->devices+i, evaluatorData);
00212       if (evaluatorStatus != DS_SUCCESS) {
00213         status = evaluatorStatus;
00214         return status;
00215       }
00216       updates++;
00217       break;
00218     default:
00219       return DS_INVALID_PERF_EVALUATOR_TYPE;
00220       break;
00221     };
00222   }
00223   if (numUpdates)
00224     *numUpdates = updates;
00225   return status;
00226 }
00227 
00228 
00229 #define DS_TAG_VERSION                      "<version>"
00230 #define DS_TAG_VERSION_END                  "</version>"
00231 #define DS_TAG_DEVICE                       "<device>"
00232 #define DS_TAG_DEVICE_END                   "</device>"
00233 #define DS_TAG_SCORE                        "<score>"
00234 #define DS_TAG_SCORE_END                    "</score>"
00235 #define DS_TAG_DEVICE_TYPE                  "<type>"
00236 #define DS_TAG_DEVICE_TYPE_END              "</type>"
00237 #define DS_TAG_DEVICE_NAME                  "<name>"
00238 #define DS_TAG_DEVICE_NAME_END              "</name>"
00239 #define DS_TAG_DEVICE_DRIVER_VERSION        "<driver>"
00240 #define DS_TAG_DEVICE_DRIVER_VERSION_END    "</driver>"
00241 
00242 #define DS_DEVICE_NATIVE_CPU_STRING  "native_cpu"
00243 
00244 
00245 
00246 typedef ds_status (*ds_score_serializer)(ds_device* device,
00247                                          void** serializedScore,
00248                                          unsigned int* serializedScoreSize);
00249 static ds_status writeProfileToFile(ds_profile* profile,
00250                                     ds_score_serializer serializer,
00251                                     const char* file) {
00252   ds_status status = DS_SUCCESS;
00253   FILE* profileFile = NULL;
00254 
00255 
00256   if (profile == NULL)
00257     return DS_INVALID_PROFILE;
00258 
00259   profileFile = fopen(file, "wb");
00260   if (profileFile==NULL) {
00261     status = DS_FILE_ERROR;
00262   }
00263   else {
00264     unsigned int i;
00265 
00266     // write version string
00267     fwrite(DS_TAG_VERSION, sizeof(char), strlen(DS_TAG_VERSION), profileFile);
00268     fwrite(profile->version, sizeof(char), strlen(profile->version), profileFile);
00269     fwrite(DS_TAG_VERSION_END, sizeof(char), strlen(DS_TAG_VERSION_END), profileFile);
00270     fwrite("\n", sizeof(char), 1, profileFile);
00271 
00272     for (i = 0; i < profile->numDevices && status == DS_SUCCESS; i++) {
00273       void* serializedScore;
00274       unsigned int serializedScoreSize;
00275 
00276       fwrite(DS_TAG_DEVICE, sizeof(char), strlen(DS_TAG_DEVICE), profileFile);
00277 
00278       fwrite(DS_TAG_DEVICE_TYPE, sizeof(char), strlen(DS_TAG_DEVICE_TYPE),
00279              profileFile);
00280       fwrite(&profile->devices[i].type,sizeof(ds_device_type),1, profileFile);
00281       fwrite(DS_TAG_DEVICE_TYPE_END, sizeof(char),
00282              strlen(DS_TAG_DEVICE_TYPE_END), profileFile);
00283 
00284       switch(profile->devices[i].type) {
00285       case DS_DEVICE_NATIVE_CPU:
00286         { 
00287           // There's no need to emit a device name for the native CPU device.
00288           /*
00289           fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME),
00290                  profileFile);
00291           fwrite(DS_DEVICE_NATIVE_CPU_STRING,sizeof(char),
00292                  strlen(DS_DEVICE_NATIVE_CPU_STRING), profileFile);
00293           fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char),
00294                  strlen(DS_TAG_DEVICE_NAME_END), profileFile);
00295           */
00296         }
00297         break;
00298       case DS_DEVICE_OPENCL_DEVICE: 
00299         {
00300           fwrite(DS_TAG_DEVICE_NAME, sizeof(char), strlen(DS_TAG_DEVICE_NAME),
00301                  profileFile);
00302           fwrite(profile->devices[i].oclDeviceName,
00303                  sizeof(char),strlen(profile->devices[i].oclDeviceName), profileFile);
00304           fwrite(DS_TAG_DEVICE_NAME_END, sizeof(char),
00305                  strlen(DS_TAG_DEVICE_NAME_END), profileFile);
00306 
00307           fwrite(DS_TAG_DEVICE_DRIVER_VERSION, sizeof(char),
00308                  strlen(DS_TAG_DEVICE_DRIVER_VERSION), profileFile);
00309           fwrite(profile->devices[i].oclDriverVersion, sizeof(char),
00310                  strlen(profile->devices[i].oclDriverVersion), profileFile);
00311           fwrite(DS_TAG_DEVICE_DRIVER_VERSION_END, sizeof(char),
00312                  strlen(DS_TAG_DEVICE_DRIVER_VERSION_END), profileFile);
00313         }
00314         break;
00315       default:
00316         status = DS_UNKNOWN_DEVICE_TYPE;
00317         break;
00318       };
00319 
00320       fwrite(DS_TAG_SCORE, sizeof(char), strlen(DS_TAG_SCORE), profileFile);
00321       status = serializer(profile->devices+i, &serializedScore,
00322                           &serializedScoreSize);
00323       if (status == DS_SUCCESS && serializedScore!=NULL && serializedScoreSize > 0) {
00324         fwrite(serializedScore, sizeof(char), serializedScoreSize, profileFile);
00325         free(serializedScore);
00326       }
00327       fwrite(DS_TAG_SCORE_END, sizeof(char), strlen(DS_TAG_SCORE_END), profileFile);
00328       fwrite(DS_TAG_DEVICE_END, sizeof(char), strlen(DS_TAG_DEVICE_END), profileFile);
00329       fwrite("\n",sizeof(char),1,profileFile);
00330     }
00331     fclose(profileFile);
00332   }
00333   return status;
00334 }
00335 
00336 
00337 static ds_status readProFile(const char* fileName, char** content,
00338                              size_t* contentSize) {
00339   FILE * input = NULL;
00340   size_t size = 0;
00341   char* binary = NULL;
00342 
00343   *contentSize = 0;
00344   *content = NULL;
00345 
00346   input = fopen(fileName, "rb");
00347   if(input == NULL) {
00348     return DS_FILE_ERROR;
00349   }
00350 
00351   fseek(input, 0L, SEEK_END); 
00352   size = ftell(input);
00353   rewind(input);
00354   binary = (char*)malloc(size);
00355   if(binary == NULL) {
00356     fclose(input);
00357     return DS_FILE_ERROR;
00358   }
00359   fread(binary, sizeof(char), size, input);
00360   fclose(input);
00361 
00362   *contentSize = size;
00363   *content = binary;
00364   return DS_SUCCESS;
00365 }
00366 
00367 
00368 static const char* findString(const char* contentStart, const char* contentEnd,
00369                               const char* string) {
00370   size_t stringLength;
00371   const char* currentPosition;
00372   const char* found;
00373   found = NULL;
00374   stringLength = strlen(string);
00375   currentPosition = contentStart;
00376   for(currentPosition = contentStart; currentPosition < contentEnd; currentPosition++) {
00377     if (*currentPosition == string[0]) {
00378       if (currentPosition+stringLength < contentEnd) {
00379         if (strncmp(currentPosition, string, stringLength) == 0) {
00380           found = currentPosition;
00381           break;
00382         }
00383       }
00384     }
00385   }
00386   return found;
00387 }
00388 
00389 
00390 typedef ds_status (*ds_score_deserializer)(ds_device* device,
00391                                            const unsigned char* serializedScore,
00392                                            unsigned int serializedScoreSize); 
00393 static ds_status readProfileFromFile(ds_profile* profile,
00394                                      ds_score_deserializer deserializer,
00395                                      const char* file) {
00396 
00397   ds_status status = DS_SUCCESS;
00398   char* contentStart = NULL;
00399   const char* contentEnd = NULL;
00400   size_t contentSize;
00401 
00402   if (profile==NULL)
00403     return DS_INVALID_PROFILE;
00404 
00405   status = readProFile(file, &contentStart, &contentSize);
00406   if (status == DS_SUCCESS) {
00407     const char* currentPosition;
00408     const char* dataStart;
00409     const char* dataEnd;
00410     size_t versionStringLength;
00411 
00412     contentEnd = contentStart + contentSize;
00413     currentPosition = contentStart;
00414 
00415 
00416     // parse the version string
00417     dataStart = findString(currentPosition, contentEnd, DS_TAG_VERSION);
00418     if (dataStart == NULL) {
00419       status = DS_PROFILE_FILE_ERROR;
00420       goto cleanup;
00421     }
00422     dataStart += strlen(DS_TAG_VERSION);
00423 
00424     dataEnd = findString(dataStart, contentEnd, DS_TAG_VERSION_END);
00425     if (dataEnd==NULL) {
00426       status = DS_PROFILE_FILE_ERROR;
00427       goto cleanup;
00428     }
00429 
00430     versionStringLength = strlen(profile->version);
00431     if (versionStringLength!=(dataEnd-dataStart)   
00432         || strncmp(profile->version, dataStart, versionStringLength)!=0) {
00433       // version mismatch
00434       status = DS_PROFILE_FILE_ERROR;
00435       goto cleanup;
00436     }
00437     currentPosition = dataEnd+strlen(DS_TAG_VERSION_END);
00438 
00439     // parse the device information
00440     while (1) {
00441       unsigned int i;
00442 
00443       const char* deviceTypeStart;
00444       const char* deviceTypeEnd;
00445       ds_device_type deviceType;
00446 
00447       const char* deviceNameStart;
00448       const char* deviceNameEnd;
00449 
00450       const char* deviceScoreStart;
00451       const char* deviceScoreEnd;
00452 
00453       const char* deviceDriverStart;
00454       const char* deviceDriverEnd;
00455 
00456       dataStart = findString(currentPosition, contentEnd, DS_TAG_DEVICE);
00457       if (dataStart==NULL) {
00458         // nothing useful remain, quit...
00459         break;
00460       }
00461       dataStart+=strlen(DS_TAG_DEVICE);
00462       dataEnd = findString(dataStart, contentEnd, DS_TAG_DEVICE_END);
00463       if (dataEnd==NULL) {
00464         status = DS_PROFILE_FILE_ERROR;
00465         goto cleanup;
00466       }
00467 
00468       // parse the device type
00469       deviceTypeStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_TYPE);
00470       if (deviceTypeStart==NULL) {
00471         status = DS_PROFILE_FILE_ERROR;
00472         goto cleanup;       
00473       }
00474       deviceTypeStart+=strlen(DS_TAG_DEVICE_TYPE);
00475       deviceTypeEnd = findString(deviceTypeStart, contentEnd,
00476                                  DS_TAG_DEVICE_TYPE_END);
00477       if (deviceTypeEnd==NULL) {
00478         status = DS_PROFILE_FILE_ERROR;
00479         goto cleanup;
00480       }
00481       memcpy(&deviceType, deviceTypeStart, sizeof(ds_device_type));
00482 
00483 
00484       // parse the device name
00485       if (deviceType == DS_DEVICE_OPENCL_DEVICE) {
00486 
00487         deviceNameStart = findString(dataStart, contentEnd, DS_TAG_DEVICE_NAME);
00488         if (deviceNameStart==NULL) {
00489           status = DS_PROFILE_FILE_ERROR;
00490           goto cleanup;       
00491         }
00492         deviceNameStart+=strlen(DS_TAG_DEVICE_NAME);
00493         deviceNameEnd = findString(deviceNameStart, contentEnd,
00494                                    DS_TAG_DEVICE_NAME_END);
00495         if (deviceNameEnd==NULL) {
00496           status = DS_PROFILE_FILE_ERROR;
00497           goto cleanup;       
00498         }
00499 
00500 
00501         deviceDriverStart = findString(dataStart, contentEnd,
00502                                        DS_TAG_DEVICE_DRIVER_VERSION);
00503         if (deviceDriverStart==NULL) {
00504           status = DS_PROFILE_FILE_ERROR;
00505           goto cleanup;       
00506         }
00507         deviceDriverStart+=strlen(DS_TAG_DEVICE_DRIVER_VERSION);
00508         deviceDriverEnd = findString(deviceDriverStart, contentEnd,
00509                                      DS_TAG_DEVICE_DRIVER_VERSION_END);
00510         if (deviceDriverEnd ==NULL) {
00511           status = DS_PROFILE_FILE_ERROR;
00512           goto cleanup;       
00513         }
00514 
00515 
00516         // check if this device is on the system
00517         for (i = 0; i < profile->numDevices; i++) {
00518           if (profile->devices[i].type == DS_DEVICE_OPENCL_DEVICE) {
00519             size_t actualDeviceNameLength;
00520             size_t driverVersionLength;
00521             
00522             actualDeviceNameLength = strlen(profile->devices[i].oclDeviceName);
00523             driverVersionLength = strlen(profile->devices[i].oclDriverVersion);
00524             if (actualDeviceNameLength == (deviceNameEnd - deviceNameStart)
00525                && driverVersionLength == (deviceDriverEnd - deviceDriverStart)
00526                && strncmp(profile->devices[i].oclDeviceName, deviceNameStart,
00527                           actualDeviceNameLength)==0
00528                && strncmp(profile->devices[i].oclDriverVersion, deviceDriverStart,
00529                           driverVersionLength)==0) {
00530               deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
00531               if (deviceNameStart==NULL) {
00532                 status = DS_PROFILE_FILE_ERROR;
00533                 goto cleanup;       
00534               }
00535               deviceScoreStart+=strlen(DS_TAG_SCORE);
00536               deviceScoreEnd = findString(deviceScoreStart, contentEnd,
00537                                           DS_TAG_SCORE_END);
00538               status = deserializer(profile->devices+i,
00539                                     (const unsigned char*)deviceScoreStart,
00540                                     deviceScoreEnd-deviceScoreStart);
00541               if (status != DS_SUCCESS) {
00542                 goto cleanup;
00543               }
00544             }
00545           }
00546         }
00547 
00548       }
00549       else if (deviceType == DS_DEVICE_NATIVE_CPU) {
00550         for (i = 0; i < profile->numDevices; i++) {
00551           if (profile->devices[i].type == DS_DEVICE_NATIVE_CPU) {
00552             deviceScoreStart = findString(dataStart, contentEnd, DS_TAG_SCORE);
00553             if (deviceScoreStart==NULL) {
00554               status = DS_PROFILE_FILE_ERROR;
00555               goto cleanup;       
00556             }
00557             deviceScoreStart+=strlen(DS_TAG_SCORE);
00558             deviceScoreEnd = findString(deviceScoreStart, contentEnd,
00559                                         DS_TAG_SCORE_END);
00560             status = deserializer(profile->devices+i,
00561                                   (const unsigned char*)deviceScoreStart,
00562                                   deviceScoreEnd-deviceScoreStart);
00563             if (status != DS_SUCCESS) {
00564               goto cleanup;
00565             }
00566           }
00567         }
00568       }
00569 
00570       // skip over the current one to find the next device
00571       currentPosition = dataEnd+strlen(DS_TAG_DEVICE_END);
00572     }
00573   }
00574 cleanup:
00575   if (contentStart!=NULL) free(contentStart);
00576   return status;
00577 }
00578 
00579 static ds_status getNumDeviceWithEmptyScore(ds_profile* profile,
00580                                             unsigned int* num) {
00581   unsigned int i;
00582   if (profile == NULL || num==NULL)
00583     return DS_MEMORY_ERROR;
00584   *num=0;
00585   for (i = 0; i < profile->numDevices; i++) {
00586     if (profile->devices[i].score == NULL) {
00587       *num++;
00588     }
00589   }
00590   return DS_SUCCESS;
00591 }
00592 
00593 #endif
00594 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines