Added option to OpenCL to disable cache/regenerate profile.
diff --git a/MagickCore/opencl.c b/MagickCore/opencl.c
index c028801..66d6a12 100644
--- a/MagickCore/opencl.c
+++ b/MagickCore/opencl.c
@@ -96,8 +96,10 @@
   cl_device_id device;
   cl_context context;
 
+  MagickBooleanType disableProgramCache; /* disable the OpenCL program cache */
   cl_program programs[MAGICK_OPENCL_NUM_PROGRAMS]; /* one program object maps one kernel source file */
 
+  MagickBooleanType regenerateProfile;   /* re-run the microbenchmark in auto device selection mode */ 
   SemaphoreInfo* lock;
 };
 
@@ -327,6 +329,22 @@
     (void) ThrowMagickException(exception, GetMagickModule(), ModuleWarning, "SetMagickOpenCLEnvParm cannot modify the OpenCL initialization state.", "'%s'", ".");
     break;
 
+  case MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED:
+    if (dataSize != sizeof(clEnv->disableProgramCache))
+      goto cleanup;
+    clEnv->disableProgramCache =  *((MagickBooleanType*)data);
+    clEnv->OpenCLInitialized = MagickFalse;
+    status = MagickTrue;
+    break;
+
+  case MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE:
+    if (dataSize != sizeof(clEnv->regenerateProfile))
+      goto cleanup;
+    clEnv->regenerateProfile =  *((MagickBooleanType*)data);
+    clEnv->OpenCLInitialized = MagickFalse;
+    status = MagickTrue;
+    break;
+
   default:
     goto cleanup;
   };
@@ -418,6 +436,20 @@
     status = MagickTrue;
     break;
 
+  case MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED:
+    if (dataSize != sizeof(clEnv->disableProgramCache))
+      goto cleanup;
+    *((MagickBooleanType*)data) = clEnv->disableProgramCache;
+    status = MagickTrue;
+    break;
+
+  case MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE:
+    if (dataSize != sizeof(clEnv->regenerateProfile))
+      goto cleanup;
+    *((MagickBooleanType*)data) = clEnv->regenerateProfile;
+    status = MagickTrue;
+    break;
+
   default:
     goto cleanup;
   };
@@ -477,7 +509,7 @@
     }
     ptr++;
   }
-  (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s_%s_%02d_%08x_%d.bin"
+  (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s_%s_%02d_%08x_%d.bin",
          GetOpenCLCachedFilesDirectory(),DirectorySeparator,prefix,deviceName,
          (unsigned int)prog,signature,sizeof(char*)*8);
   name = (char*)AcquireMagickMemory(strlen(path)+1);
@@ -704,7 +736,8 @@
     unsigned int programSignature = stringSignature(MagickOpenCLProgramStrings[i]) ^ optionsSignature;
 
     /* try to load the binary first */
-    if (!getenv("MAGICK_OCL_REC"))
+    if (clEnv->disableProgramCache != MagickTrue
+        && !getenv("MAGICK_OCL_REC"))
       loadSuccessful = loadBinaryCLProgram(clEnv, (MagickOpenCLProgram)i, programSignature);
 
     if (loadSuccessful == MagickFalse)
@@ -1339,8 +1372,8 @@
     clGetPlatformIDs(numPlatforms, platforms, NULL);
     for (i = 0; i < (unsigned int)numPlatforms; i++) {
       cl_uint num;
-      clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU, 0, NULL, &num);
-      numDevices+=num;
+      if (clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU, 0, NULL, &num) == CL_SUCCESS)
+        numDevices+=num;
     }
   }
 
@@ -1991,6 +2024,9 @@
   else
     ReturnStatus(DS_PERF_EVALUATOR_ERROR);
 
+  /* recompile the OpenCL kernels if it needs to */
+  clEnv->disableProgramCache = defaultCLEnv->disableProgramCache;
+
   InitOpenCLEnvInternal(clEnv,exception);
   oldClEnv=defaultCLEnv;
   defaultCLEnv=clEnv;
@@ -2110,6 +2146,7 @@
   AccelerateScoreType bestScore;
   char path[MaxTextExtent];
   MagickBooleanType flag;
+  ds_evaluation_type profileType;
 
   LockDefaultOpenCLEnv();
 
@@ -2128,8 +2165,15 @@
          ,GetOpenCLCachedFilesDirectory()
          ,DirectorySeparator,IMAGEMAGICK_PROFILE_FILE);
 
-  readProfileFromFile(profile, AccelerateScoreDeserializer, path);
-  status = profileDevices(profile, DS_EVALUATE_NEW_ONLY, AcceleratePerfEvaluator, NULL, &numDeviceProfiled);
+  if (clEnv->regenerateProfile == MagickTrue) {
+    profileType = DS_EVALUATE_ALL;
+  }
+  else {
+    readProfileFromFile(profile, AccelerateScoreDeserializer, path);
+    profileType = DS_EVALUATE_NEW_ONLY;
+  }
+  status = profileDevices(profile, profileType, AcceleratePerfEvaluator, NULL, &numDeviceProfiled);
+
   if (status!=DS_SUCCESS) {
     (void) ThrowMagickException(exception, GetMagickModule(), ModuleFatalError, "Error when initializing the profile", "'%s'", ".");
     goto cleanup;
@@ -2259,6 +2303,15 @@
       }
       break;
 
+    case MAGICK_OPENCL_DEVICE_SELECT_AUTO_CLEAR_CACHE:
+        flag = MagickTrue;
+        SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED
+          , sizeof(MagickBooleanType), &flag, exception);
+        flag = MagickTrue;
+        SetMagickOpenCLEnvParam(clEnv, MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE
+          , sizeof(MagickBooleanType), &flag, exception);
+
+    /* fall through here!! */
     case MAGICK_OPENCL_DEVICE_SELECT_AUTO:
     default:
       {
@@ -2281,7 +2334,7 @@
 }
 
 
-MagickExport
+MagickPrivate
 MagickBooleanType OpenCLThrowMagickException(ExceptionInfo *exception,
   const char *module,const char *function,const size_t line,
   const ExceptionType severity,const char *tag,const char *format,...) {
@@ -2466,7 +2519,7 @@
 }
 
 
-MagickExport
+MagickPrivate
 MagickBooleanType OpenCLThrowMagickException(ExceptionInfo *exception,
   const char *module,const char *function,const size_t line,
   const ExceptionType severity,const char *tag,const char *format,...) 
diff --git a/MagickCore/opencl.h b/MagickCore/opencl.h
index f3838d8..19ab40a 100644
--- a/MagickCore/opencl.h
+++ b/MagickCore/opencl.h
@@ -47,9 +47,13 @@
 
 /* Parameter type accepted by SetMagickOpenCLEnvParm and GetMagickOpenCLEnvParm */
 typedef enum {
-    MAGICK_OPENCL_ENV_PARAM_DEVICE                  /* cl_device_id (from OpenCL) */
-  , MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED         /* MagickBooleanType */
-  , MAGICK_OPENCL_ENV_PARAM_OPENCL_INITIALIZED      /* MagickBooleanType */
+    MAGICK_OPENCL_ENV_PARAM_DEVICE                 /* cl_device_id (from OpenCL) */
+  , MAGICK_OPENCL_ENV_PARAM_OPENCL_DISABLED        /* MagickBooleanType */
+  , MAGICK_OPENCL_ENV_PARAM_OPENCL_INITIALIZED     /* MagickBooleanType */
+  , MAGICK_OPENCL_ENV_PARAM_PROGRAM_CACHE_DISABLED /* MagickBooleanType */
+                                                   /* if true, disable the kernel binary cache */
+  , MAGICK_OPENCL_ENV_PARAM_REGENERATE_PROFILE     /* MagickBooleanType */
+                                                   /* if true, rerun microbenchmark in auto device selection */
 } MagickOpenCLEnvParam;
 
 extern MagickExport
@@ -66,13 +70,12 @@
   MAGICK_OPENCL_OFF = 0
 , MAGICK_OPENCL_DEVICE_SELECT_AUTO = 1
 , MAGICK_OPENCL_DEVICE_SELECT_USER = 2
+, MAGICK_OPENCL_DEVICE_SELECT_AUTO_CLEAR_CACHE = 3
 } ImageMagickOpenCLMode ;
 
 extern MagickExport
 MagickBooleanType InitImageMagickOpenCL(ImageMagickOpenCLMode, void*, void*, ExceptionInfo*);
 
-
-
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif