[dense-linear-algebra-libraries/linalg.git] / src / ti / linalg / blasblisacc / src / ti_cblas_initfini.c
diff --git a/src/ti/linalg/blasblisacc/src/ti_cblas_initfini.c b/src/ti/linalg/blasblisacc/src/ti_cblas_initfini.c
index 65963d314a9c41065980c76bc60d14e7df366dd7..8549e92a97c5a8ba8b4e105c7b41a380cd9a3806 100644 (file)
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
- *****************************************************************************/
-
+ *****************************************************************************/
#include "ti_cblas_acc.h"
#include "../../ticblas/ticblas.h"
#include <pthread.h>
#include "ti_cblas_kernel.dsp_h"
#endif
+/*==============================================================================
+ * This file contains functions of the ARM wrapper of ARM+DSP CBLAS library.
+ * It has the initialization and finalization routines.
+ *
+ * The standard CBLAS API for each BLAS function can be found in file
+ * ti_cblas_cblas_<func_name>.c, such as ti_cblas_cblas_dgemm.c for DGEMM.
+ *============================================================================*/
+
#define TI_CBLAS_INITFINI_SUCCESS 0
#define TI_CBLAS_INITFINI_OCL_ERR 1
#define TI_CBLAS_INITFINI_BLI_ERR 2
/* Global variables */
-Context* ti_cblas_ocl_context = NULL;
-std::vector<Device>* ti_cblas_ocl_devices = NULL;
-CommandQueue* ti_cblas_ocl_Q = NULL;
-Program::Binaries* ti_cblas_ocl_binary = NULL;
-Program* ti_cblas_ocl_program = NULL;
+Context* ti_cblas_ocl_context = NULL;
+std::vector<Device>* ti_cblas_ocl_devices = NULL;
+CommandQueue* ti_cblas_ocl_Q = NULL;
+Program::Binaries* ti_cblas_ocl_binary = NULL;
+Program* ti_cblas_ocl_program = NULL;
int ti_cblas_init_done = 0; /* flag to check if init is complete */
int ti_cblas_disable_debug = 0; /* runtime toggle to disable debug */
int ti_cblas_offload = TI_CBLAS_OFFLOAD_SIZE;
-int ti_cblas_kernel_valid[TI_CBLAS_NUM_KERNELS];
int TI_CBLAS_L1_OFFLOAD = TI_CBLAS_OFFLOAD_NONE;
int TI_CBLAS_L2_OFFLOAD = TI_CBLAS_OFFLOAD_NONE;
int TI_CBLAS_L3_OFFLOAD = TI_CBLAS_OFFLOAD_NONE;
pthread_cond_t CV;
pthread_mutex_t MUTEX;
+/*============================================================================
+ * Function purpose: report error encoutered in ARM wrapper code.
+ *============================================================================*/
void ti_cblas_error(const char* msg, int code)
{
- fprintf(stderr, "ERROR: (%s,%d)\n", msg, code);
+ fprintf(stderr, "TI CBLAS wrapper ERROR: (%s,%d)\n", msg, code);
}
-extern "C"
+/*============================================================================
+ * Function purpose: initialize BLIS on both ARM and DSP
+ *============================================================================*/
int ti_blis_init(void)
{
- int r_val = TI_CBLAS_INITFINI_SUCCESS;
+ int r_val = TI_CBLAS_INITFINI_SUCCESS;
- TI_CBLAS_DEBUG_PRINT("Initializing BLIS on ARM...\n");
/* Initialize BLIS on ARM */
- bli_init();
- TI_CBLAS_DEBUG_PRINT("BLIS initialized on ARM.\n");
-
- /* Initialize BLIS on DSP */
- TI_CBLAS_DEBUG_PRINT("Initializing BLIS on DSP...\n");
- Event e;
- Kernel* __K;
-
- __K = ti_cblas_get_kernel(TI_CBLAS_CBLAS_CGEMM_IDX, "ocl_bli_init");
- try
- {
- TI_CBLAS_DEBUG_PRINT("Initializing BLIS on DSP...\n");
-
- int err_code;
- Buffer buf_err(*ti_cblas_ocl_context, CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, sizeof(int), &err_code);
- __K->setArg(0, buf_err);
-
- ti_cblas_ocl_Q->enqueueTask(*__K, 0, &e);
- e.wait();
-
- if(err_code != TICBLAS_SUCCESS) {
- TI_CBLAS_DEBUG_PRINT("Error in offloaded ocl_bli_init with error code %d!\n", err_code);
- r_val = TI_CBLAS_INITFINI_BLI_ERR;
- }
-
- ti_cblas_delete_kernel(__K);
- TI_CBLAS_DEBUG_PRINT("BLIS DSP initialization finished.\n");
- }
-
- catch (Error err)
- {
- ti_cblas_delete_kernel(__K);
- ti_cblas_error(err.what(),err.err());
- r_val = TI_CBLAS_INITFINI_OCL_ERR;
- }
+ TI_CBLAS_DEBUG_PRINT("Initializing BLIS on ARM...\n");
+ bli_init();
+ TI_CBLAS_DEBUG_PRINT("BLIS initialized on ARM.\n");
- return r_val;
-}
+ /* Initialize BLIS on DSP by offloading bli_init() on DSP */
+ TI_CBLAS_DEBUG_PRINT("Initializing BLIS on DSP...\n");
+ Event e;
+ Kernel* __K;
-extern "C"
-int ti_blis_finalize(void)
-{
- int r_val = TI_CBLAS_INITFINI_SUCCESS;
-
- TI_CBLAS_DEBUG_PRINT("Finalizing BLIS on ARM...\n");
- /* Finalize BLIS on ARM */
- bli_finalize();
- TI_CBLAS_DEBUG_PRINT("BLIS finalized on ARM.\n");
-
- Event e;
- Kernel* __K;
-
- __K = ti_cblas_get_kernel(TI_CBLAS_CBLAS_CGEMM_IDX, "ocl_bli_finalize");
+ __K = ti_cblas_get_kernel("ocl_bli_init");
+ try
+ {
+ int err_code;
+ Buffer buf_err(*ti_cblas_ocl_context, CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, sizeof(int), &err_code);
+ __K->setArg(0, buf_err);
- /* Finalize BLIS on DSP */
- TI_CBLAS_DEBUG_PRINT("Finalizing BLIS on DSP...\n");
- int err_code;
- Buffer buf_err(*ti_cblas_ocl_context, CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, sizeof(int), &err_code);
- __K->setArg(0, buf_err);
-
- try
- {
- ti_cblas_ocl_Q->enqueueTask(*__K, 0, &e);
- e.wait();
+ ti_cblas_ocl_Q->enqueueTask(*__K, 0, &e);
+ e.wait();
if(err_code != TICBLAS_SUCCESS) {
- TI_CBLAS_DEBUG_PRINT("Error in offloaded ocl_bli_finalize with error code %d!\n", err_code);
+ TI_CBLAS_DEBUG_PRINT("Error in offloaded ocl_bli_init with error code %d!\n", err_code);
r_val = TI_CBLAS_INITFINI_BLI_ERR;
}
- ti_cblas_delete_kernel(__K);
- }
-
- catch (Error err)
- {
- ti_cblas_error(err.what(),err.err());
- r_val = TI_CBLAS_INITFINI_OCL_ERR;
- }
-
- return r_val;
-}
-
-#ifdef __cplusplus
-extern "C"
-#endif
-int ti_cblas_finalize(void)
-{
- /* If ti_cblas_init_done is equal to 0,
- * then we know that ti_cblas_init was not called,
- * and so we can return early.
- */
- if(ti_cblas_init_done == 0) {
- return TI_CBLAS_INITFINI_SUCCESS;
+ ti_cblas_delete_kernel(__K);
+ TI_CBLAS_DEBUG_PRINT("BLIS DSP initialization finished.\n");
}
- int r_val = ti_blis_finalize();
- /*Using same name as ti_cblas_init critical region. See notes in bli_init*/
-#pragma omp critical (ti_cblas_init_critical)
- {
- // Destroy Pthread
- pthread_mutex_destroy(&MUTEX);
- pthread_cond_destroy (&CV);
-
- //destroy Command queue, program, devices and context.
- if(ti_cblas_ocl_Q != NULL)
- {
- delete(ti_cblas_ocl_Q);
- ti_cblas_ocl_Q = NULL;
- }
- if(ti_cblas_ocl_program != NULL)
- {
- delete(ti_cblas_ocl_program);
- ti_cblas_ocl_program = NULL;
- }
- if(ti_cblas_ocl_binary != NULL)
- {
- delete(ti_cblas_ocl_binary);
- ti_cblas_ocl_binary = NULL;
- }
- if(ti_cblas_ocl_devices != NULL)
- {
- delete(ti_cblas_ocl_devices);
- ti_cblas_ocl_devices = NULL;
- }
- if(ti_cblas_ocl_context != NULL)
- {
- delete(ti_cblas_ocl_context);
- ti_cblas_ocl_context = NULL;
- }
- }
-
- return r_val;
-}
-
-void ti_cblas_auto_finalize(void)
-{
- int r_val;
-
- r_val = ti_cblas_finalize();
- if (r_val != TI_CBLAS_INITFINI_SUCCESS)
+ catch (Error err)
{
- fprintf(stderr, "Error: ti_cblas_finalize failed with error code %d!\n", r_val);
+ ti_cblas_delete_kernel(__K);
+ ti_cblas_error(err.what(),err.err());
+ r_val = TI_CBLAS_INITFINI_OCL_ERR;
}
-}
-/* This function is invoked exactly once on startup */
-/* Its purpose is to parse the environment variables and do OpenCL init */
+ return r_val;
+} // ti_blis_init
+
+
+/*============================================================================
+ * Function purpose: initialize and prepare for CBLAS calls:
+ * - parse the environment variables
+ * - initialize OpenCL
+ * - initialize BLIS
+ *
+ * Note: this function is invoked exactly once on startup, when any CBLAS function
+ * is called the first time.
+ *============================================================================*/
void ti_cblas_init(void)
{
-#pragma omp critical (ti_cblas_init_critical)
- {
/* Add code for interception */
- if (!ti_cblas_init_done)
- {
#ifdef TI_CBLAS_DEBUG
char *no_debug_env = getenv("TI_CBLAS_NO_DEBUG");
if (no_debug_env) {
/* check environment variables */
const char *offload_env = getenv("TI_CBLAS_OFFLOAD");
if (!offload_env) {
- TI_CBLAS_DEBUG_PRINT("Using build time default for offload: TI_CBLAS_OFFLOAD=%s\n", TI_CBLAS_OFFLOAD);
- offload_env = TI_CBLAS_OFFLOAD;
+ TI_CBLAS_DEBUG_PRINT("Using build time default for offload: TI_CBLAS_OFFLOAD=%s\n", TI_CBLAS_OFFLOAD_DEF);
+ offload_env = TI_CBLAS_OFFLOAD_DEF;
}
else {
TI_CBLAS_DEBUG_PRINT("Using runtime override for offloads: TI_CBLAS_OFFLOAD=%s\n", offload_env);
ti_cblas_offload = atoi(offload_env);
if (ti_cblas_offload == TI_CBLAS_OFFLOAD_NONE) {
TI_CBLAS_DEBUG_PRINT("Disabling all offloads\n");
+ return;
}
}
+#pragma omp critical (ti_cblas_init_critical)
+ {
/* 3-digit value: 012
* Left-most digit => L1 (0)
* Middle-digit => L2 (1)
#else
const char binary[] = "./ti_cblas_kernel.out";
unsigned int bin_length;
-#ifdef __cplusplus
bin_length = ocl_read_binary(binary, (char*&)bin);
-#else
- FILE *fp = fopen(binary, "r");
- if (!fp) {
- TI_CBLAS_ERROR_EXIT("Could not open OpenCL pre-compiled binary %s for reading\n", binary);
- }
- struct stat fileinfo;
- stat(binary, &fileinfo);
- bin_length = fileinfo.st_size;
- bin = (char *)malloc(bin_length);
- if (!bin) {
- TI_CBLAS_ERROR_EXIT("Could not malloc of size %d for reading OpenCL binary\n", bin_length);
- }
- if (fread((char *)bin, bin_length, 1, fp) != 1) {
- TI_CBLAS_ERROR_EXIT("Could not read %d bytes of OpenCL binary\n", bin_length);
- }
- fclose(fp);
-#endif /* cplusplus */
#endif /* FAT_BINARY */
/* OpenCL init */
TI_CBLAS_DEBUG_PRINT("Initializing OpenCL\n");
-#ifdef __cplusplus
- ti_cblas_ocl_context = new Context(CL_DEVICE_TYPE_ACCELERATOR);
- ti_cblas_ocl_devices = new std::vector<Device> (ti_cblas_ocl_context->getInfo<CL_CONTEXT_DEVICES>());
- ti_cblas_ocl_binary = new Program::Binaries(1, std::make_pair(bin, bin_length));
- ti_cblas_ocl_program = new Program(*ti_cblas_ocl_context, *ti_cblas_ocl_devices, *ti_cblas_ocl_binary);
- ti_cblas_ocl_program->build(*ti_cblas_ocl_devices);
- ti_cblas_ocl_Q = new CommandQueue(*ti_cblas_ocl_context, ti_cblas_ocl_devices[0][0], CL_QUEUE_PROFILING_ENABLE);
-#else
- cl_int err;
- cl_device_id device;
- /* Create an in-order command queue by default*/
- int queue_flags = 0;
-#ifdef TI_CBLAS_PROFILE
- queue_flags |= CL_QUEUE_PROFILING_ENABLE;
-#endif
-
- ti_cblas_ocl_context = clCreateContextFromType(0,CL_DEVICE_TYPE_ACCELERATOR,0,0,&err);
- TI_CBLAS_OCL_CHKERROR("clCreateContextFromType",err);
- err = clGetDeviceIDs(0,CL_DEVICE_TYPE_ACCELERATOR,1,&device,0);
- TI_CBLAS_OCL_CHKERROR("clGetDeviceIDs",err);
- ti_cblas_ocl_Q = clCreateCommandQueue(ti_cblas_ocl_context, device, queue_flags, &err);
- TI_CBLAS_OCL_CHKERROR("clCreateCommandQueue",err);
- ti_cblas_ocl_program = clCreateProgramWithBinary(ti_cblas_ocl_context, 1, &device, &bin_length, &bin, NULL, &err);
- TI_CBLAS_OCL_CHKERROR("clCreateProgramWithBinary",err);
- const char *compile_options = "";
- err = clBuildProgram(ti_cblas_ocl_program, 1, &device, compile_options, 0, 0);
- TI_CBLAS_OCL_CHKERROR("clBuildProgram",err);
-
-#endif
+ ti_cblas_ocl_context = new Context(CL_DEVICE_TYPE_ACCELERATOR);
+ ti_cblas_ocl_devices = new std::vector<Device> (ti_cblas_ocl_context->getInfo<CL_CONTEXT_DEVICES>());
+ ti_cblas_ocl_binary = new Program::Binaries(1, std::make_pair(bin, bin_length));
+ ti_cblas_ocl_program = new Program(*ti_cblas_ocl_context, *ti_cblas_ocl_devices, *ti_cblas_ocl_binary);
+ ti_cblas_ocl_program->build(*ti_cblas_ocl_devices);
+ ti_cblas_ocl_Q = new CommandQueue(*ti_cblas_ocl_context, ti_cblas_ocl_devices[0][0], CL_QUEUE_PROFILING_ENABLE);
#ifndef TI_CBLAS_FAT_BINARY
-#ifdef __cplusplus
delete [] bin;
-#else
- free((char*)bin);
-#endif
#endif /* FAT_BINARY */
+
TI_CBLAS_DEBUG_PRINT("OpenCL initialized\n");
+ /* Initializing pthreads */
TI_CBLAS_DEBUG_PRINT("Initializing Pthreads\n");
- /* Initializing pthreads */
- pthread_cond_init (&CV, 0);
- pthread_mutex_init(&MUTEX, 0);
- TI_CBLAS_DEBUG_PRINT("Pthreads initialized\n");
- TI_CBLAS_DEBUG_PRINT("Initializing BLIS\n");
- if(ti_blis_init() == TI_CBLAS_INITFINI_SUCCESS) {
+ pthread_cond_init (&CV, 0);
+ pthread_mutex_init(&MUTEX, 0);
+ TI_CBLAS_DEBUG_PRINT("Pthreads initialized\n");
+ TI_CBLAS_DEBUG_PRINT("Initializing BLIS\n");
+ if(ti_blis_init() == TI_CBLAS_INITFINI_SUCCESS) {
TI_CBLAS_DEBUG_PRINT("BLIS initialized\n");\
}
else {
- TI_CBLAS_DEBUG_PRINT("BLIS NOT initialized!\n");\
+ TI_CBLAS_DEBUG_PRINT("BLIS NOT initialized!\n");\
}
-
- atexit(ti_cblas_auto_finalize);
+
+ /* Register auto finalization to be called when program exits */
+ atexit(ti_cblas_auto_finalize);
- TI_CBLAS_PROFILE_REPORT(" Initialization took %8.2f us\n", (float) clock_diff);
- ti_cblas_init_done = 1;
- TI_CBLAS_DEBUG_PRINT("ti_cblas_init: Finished OpenCL initialization\n");
- } //end of !ti_cblas_init_done
+ TI_CBLAS_PROFILE_REPORT("Initialization took %8.2f us\n", (float) clock_diff);
+ ti_cblas_init_done = 1;
+ TI_CBLAS_DEBUG_PRINT("ti_cblas_init: Finished initialization\n");
} // End of critical section
return;
-}
+} //ti_cblas_init
+/*============================================================================
+ * Function purpose: finalize BLIS on both ARM and DSP
+ *============================================================================*/
+int ti_blis_finalize(void)
+{
+ int r_val = TI_CBLAS_INITFINI_SUCCESS;
+
+ /* Finalize BLIS on ARM */
+ TI_CBLAS_DEBUG_PRINT("Finalizing BLIS on ARM...\n");
+ bli_finalize();
+ TI_CBLAS_DEBUG_PRINT("BLIS finalized on ARM.\n");
+ /* Finalize BLIS on DSP */
+ Event e;
+ Kernel* __K;
-void ti_cblas_mem_free(void *ptr)
+ __K = ti_cblas_get_kernel("ocl_bli_finalize");
+
+ TI_CBLAS_DEBUG_PRINT("Finalizing BLIS on DSP...\n");
+ int err_code;
+ Buffer buf_err(*ti_cblas_ocl_context, CL_MEM_READ_WRITE|CL_MEM_USE_HOST_PTR, sizeof(int), &err_code);
+ __K->setArg(0, buf_err);
+
+ try
+ {
+ ti_cblas_ocl_Q->enqueueTask(*__K, 0, &e);
+ e.wait();
+
+ if(err_code != TICBLAS_SUCCESS) {
+ TI_CBLAS_DEBUG_PRINT("Error in offloaded ocl_bli_finalize with error code %d!\n", err_code);
+ r_val = TI_CBLAS_INITFINI_BLI_ERR;
+ }
+
+ ti_cblas_delete_kernel(__K);
+ }
+
+ catch (Error err)
+ {
+ ti_cblas_error(err.what(),err.err());
+ r_val = TI_CBLAS_INITFINI_OCL_ERR;
+ }
+
+ return r_val;
+} // ti_blis_finalize
+
+/*============================================================================
+ * Function purpose: finalize after all CBLAS calls:
+ * - finalize BLIS
+ * - delete OpenCL context
+ *
+ * Note: this function is invoked exactly once on program exit.
+ *============================================================================*/
+int ti_cblas_finalize(void)
{
- pthread_mutex_lock(&MUTEX);
- __free_msmc(ptr);
- pthread_cond_broadcast(&CV);
- pthread_mutex_unlock(&MUTEX);
+ /* If ti_cblas_init_done is equal to 0,
+ * then we know that ti_cblas_init was not called,
+ * and so we can return early.
+ */
+ if(ti_cblas_init_done == 0) {
+ return TI_CBLAS_INITFINI_SUCCESS;
+ }
-}
+ int r_val = ti_blis_finalize();
+ /*Using same name as ti_cblas_init critical region. See notes in bli_init*/
+#pragma omp critical (ti_cblas_init_critical)
+ {
+ // Destroy Pthread
+ pthread_mutex_destroy(&MUTEX);
+ pthread_cond_destroy (&CV);
+
+ //destroy Command queue, program, devices and context.
+ if(ti_cblas_ocl_Q != NULL)
+ {
+ delete(ti_cblas_ocl_Q);
+ ti_cblas_ocl_Q = NULL;
+ }
+ if(ti_cblas_ocl_program != NULL)
+ {
+ delete(ti_cblas_ocl_program);
+ ti_cblas_ocl_program = NULL;
+ }
+ if(ti_cblas_ocl_binary != NULL)
+ {
+ delete(ti_cblas_ocl_binary);
+ ti_cblas_ocl_binary = NULL;
+ }
+ if(ti_cblas_ocl_devices != NULL)
+ {
+ delete(ti_cblas_ocl_devices);
+ ti_cblas_ocl_devices = NULL;
+ }
+ if(ti_cblas_ocl_context != NULL)
+ {
+ delete(ti_cblas_ocl_context);
+ ti_cblas_ocl_context = NULL;
+ }
+ }
+
+ return r_val;
+} // ti_cblas_finalize
-void *ti_cblas_mem_alloc(size_t size)
+
+/*============================================================================
+ * Function purpose: auto-finalize on program exit.
+ *============================================================================*/
+void ti_cblas_auto_finalize(void)
{
- void *ptr;
- pthread_mutex_lock(&MUTEX);
- /*-------------------------------------------------------------------------
+ int r_val;
- * Loop in case of false signal after broadcast.
+ r_val = ti_cblas_finalize();
+ if (r_val != TI_CBLAS_INITFINI_SUCCESS)
+ {
+ fprintf(stderr, "Error: ti_cblas_finalize failed with error code %d!\n", r_val);
+ }
+} //ti_cblas_auto_finalize
- *------------------------------------------------------------------------*/
- while ((ptr = __malloc_msmc(size)) == 0)
- pthread_cond_wait(&CV, &MUTEX);
- pthread_mutex_unlock(&MUTEX);
- return ptr;
+/*============================================================================
+ * Function purpose: free previously allocated MSMC memory
+ *============================================================================*/
+void ti_cblas_mem_free(void *ptr)
+{
+ pthread_mutex_lock(&MUTEX);
+ __free_msmc(ptr);
+ pthread_cond_broadcast(&CV);
+ pthread_mutex_unlock(&MUTEX);
}
+/*============================================================================
+ * Function purpose: allocate MSMC memory
+ *============================================================================*/
+void *ti_cblas_mem_alloc(size_t size)
+{
+ void *ptr;
+ pthread_mutex_lock(&MUTEX);
+
+ /*-------------------------------------------------------------------------
+ * Loop in case of false signal after broadcast.
+ *------------------------------------------------------------------------*/
+ while ((ptr = __malloc_msmc(size)) == 0)
+ {
+ pthread_cond_wait(&CV, &MUTEX);
+ }
+
+ pthread_mutex_unlock(&MUTEX);
+
+ return ptr;
+} //ti_cblas_mem_alloc
-/* Returns a handle to the kernel for the specified
- * function with index 'idx'. Initializes the handle if it's
- * not been used before, otherwise returns earlier handle
- */
-#ifdef __cplusplus
-Kernel*
-#else
-cl_kernel
-#endif
-ti_cblas_get_kernel(int idx, const char *fname)
+
+/*============================================================================
+ * Function purpose: create an OpenCL kernel
+ *============================================================================*/
+Kernel *ti_cblas_get_kernel(const char *fname)
{
-#ifdef __cplusplus
- Kernel* __K;
-#else
- cl_kernel __K;
-#endif
+ Kernel* __K;
-#ifdef __cplusplus
__K = new Kernel(*ti_cblas_ocl_program, fname);
-#else
- cl_int err;
- __K = clCreateKernel(ti_cblas_ocl_program,fname,&err);
- TI_CBLAS_OCL_CHKERROR("clCreateKernel",err);
-#endif
return __K;
}
-#ifdef __cplusplus
+/*============================================================================
+ * Function purpose: delete an OpenCL kernel
+ *============================================================================*/
int ti_cblas_delete_kernel(Kernel* K)
-#else
-int ti_cblas_delete_kernel(cl_kernel K)
-#endif
{
-#ifdef __cplusplus
- if(K != NULL)
- {
- delete(K);
- K=NULL;
- }
-#else
- clReleaseKernel(K);
-#endif
- return 0;
+ if(K != NULL)
+ {
+ delete(K);
+ K=NULL;
+ }
+
+ return 0;
}
-
+/* Nothing after this line */