cl_createkernel.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010,2011 Université de Bordeaux
  4. * Copyright (C) 2016, 2017 CNRS
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. #include "socl.h"
  18. static void soclCreateKernel_task(void *data)
  19. {
  20. struct _cl_kernel *k = (struct _cl_kernel *)data;
  21. int range = starpu_worker_get_range();
  22. cl_int err;
  23. if (k->program->cl_programs[range] == NULL)
  24. {
  25. k->errcodes[range] = CL_SUCCESS;
  26. DEBUG_MSG("[Device %u] Kernel creation skipped: program has not been built for this device.\n", starpu_worker_get_id_check());
  27. return;
  28. }
  29. DEBUG_MSG("[Device %u] Creating kernel...\n", starpu_worker_get_id_check());
  30. k->cl_kernels[range] = clCreateKernel(k->program->cl_programs[range], k->kernel_name, &err);
  31. if (err != CL_SUCCESS)
  32. {
  33. k->errcodes[range] = err;
  34. ERROR_STOP("[Device %u] Unable to create kernel. Error %d. Aborting.\n", starpu_worker_get_id_check(), err);
  35. return;
  36. }
  37. /* One worker creates argument structures */
  38. if (__sync_bool_compare_and_swap(&k->num_args, 0, 666))
  39. {
  40. unsigned int i;
  41. cl_uint num_args;
  42. err = clGetKernelInfo(k->cl_kernels[range], CL_KERNEL_NUM_ARGS, sizeof(num_args), &num_args, NULL);
  43. if (err != CL_SUCCESS)
  44. {
  45. DEBUG_CL("clGetKernelInfo", err);
  46. ERROR_STOP("Unable to get kernel argument count. Aborting.\n");
  47. }
  48. k->num_args = num_args;
  49. DEBUG_MSG("Kernel has %d arguments\n", num_args);
  50. k->arg_size = (size_t*)malloc(sizeof(size_t) * num_args);
  51. k->arg_value = (void**)malloc(sizeof(void*) * num_args);
  52. k->arg_type = (enum kernel_arg_type*)malloc(sizeof(enum kernel_arg_type) * num_args);
  53. /* Settings default type to NULL */
  54. for (i=0; i<num_args; i++)
  55. {
  56. k->arg_value[i] = NULL;
  57. k->arg_type[i] = Null;
  58. }
  59. }
  60. }
  61. static void release_callback_kernel(void * e)
  62. {
  63. cl_kernel kernel = (cl_kernel)e;
  64. //Free args
  65. unsigned int i;
  66. for (i=0; i<kernel->num_args; i++)
  67. {
  68. switch (kernel->arg_type[i])
  69. {
  70. case Null:
  71. case Buffer:
  72. break;
  73. case Immediate:
  74. free(kernel->arg_value[i]);
  75. break;
  76. }
  77. }
  78. if (kernel->arg_size != NULL)
  79. free(kernel->arg_size);
  80. if (kernel->arg_value != NULL)
  81. free(kernel->arg_value);
  82. if (kernel->arg_type != NULL)
  83. free(kernel->arg_type);
  84. //Release real kernels...
  85. for (i=0; i<socl_device_count; i++)
  86. {
  87. if (kernel->cl_kernels[i] != NULL)
  88. {
  89. cl_int err = clReleaseKernel(kernel->cl_kernels[i]);
  90. if (err != CL_SUCCESS)
  91. DEBUG_CL("clReleaseKernel", err);
  92. }
  93. }
  94. //Release perfmodel
  95. //FIXME: we cannot release performance models before StarPU shutdown as it
  96. //will use them to store kernel execution times
  97. //free(kernel->perfmodel);
  98. //free(kernel->kernel_name);
  99. gc_entity_unstore(&kernel->program);
  100. free(kernel->cl_kernels);
  101. free(kernel->errcodes);
  102. }
  103. CL_API_ENTRY cl_kernel CL_API_CALL
  104. soclCreateKernel(cl_program program,
  105. const char * kernel_name,
  106. cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0
  107. {
  108. cl_kernel k;
  109. if (program == NULL)
  110. {
  111. if (errcode_ret != NULL)
  112. *errcode_ret = CL_INVALID_PROGRAM;
  113. return NULL;
  114. }
  115. //TODO: check programs (see opencl specs)
  116. /* Create Kernel structure */
  117. k = (cl_kernel)gc_entity_alloc(sizeof(struct _cl_kernel), release_callback_kernel, "kernel");
  118. if (k == NULL)
  119. {
  120. if (errcode_ret != NULL)
  121. *errcode_ret = CL_OUT_OF_HOST_MEMORY;
  122. return NULL;
  123. }
  124. gc_entity_store(&k->program, program);
  125. k->kernel_name = strdup(kernel_name);
  126. k->perfmodel = malloc(sizeof(struct starpu_perfmodel));
  127. memset(k->perfmodel, 0, sizeof(struct starpu_perfmodel));
  128. k->perfmodel->type = STARPU_HISTORY_BASED;
  129. k->perfmodel->symbol = k->kernel_name;
  130. k->num_args = 0;
  131. k->arg_value = NULL;
  132. k->arg_size = NULL;
  133. k->split_func = NULL;
  134. k->split_space = 0;
  135. k->split_data = NULL;
  136. k->split_perfs = NULL;
  137. STARPU_PTHREAD_MUTEX_INIT(&k->split_lock, NULL);
  138. #ifdef DEBUG
  139. static int id = 0;
  140. k->id = id++;
  141. #endif
  142. k->cl_kernels = (cl_kernel*)malloc(socl_device_count * sizeof(cl_kernel));
  143. k->errcodes = (cl_int*)malloc(socl_device_count * sizeof(cl_int));
  144. {
  145. unsigned int i;
  146. for (i=0; i<socl_device_count; i++)
  147. {
  148. k->cl_kernels[i] = NULL;
  149. k->errcodes[i] = -9999;
  150. }
  151. }
  152. /* Create kernel on each device */
  153. DEBUG_MSG("[Kernel %d] Create %u kernels (name \"%s\")\n", k->id, socl_device_count, kernel_name);
  154. starpu_execute_on_each_worker_ex(soclCreateKernel_task, k, STARPU_OPENCL, "SOCL_CREATE_KERNEL");
  155. if (errcode_ret != NULL)
  156. {
  157. unsigned int i;
  158. *errcode_ret = CL_SUCCESS;
  159. for (i=0; i<socl_device_count; i++)
  160. {
  161. switch (k->errcodes[i])
  162. {
  163. #define CASE_RET(e) case e: *errcode_ret = e; return k
  164. CASE_RET(CL_INVALID_PROGRAM);
  165. CASE_RET(CL_INVALID_PROGRAM_EXECUTABLE);
  166. CASE_RET(CL_INVALID_KERNEL_NAME);
  167. CASE_RET(CL_INVALID_KERNEL_DEFINITION);
  168. CASE_RET(CL_INVALID_VALUE);
  169. CASE_RET(CL_OUT_OF_RESOURCES);
  170. CASE_RET(CL_OUT_OF_HOST_MEMORY);
  171. #undef CASE_RET
  172. }
  173. }
  174. if (k->num_args == 666)
  175. {
  176. *errcode_ret = CL_INVALID_PROGRAM_EXECUTABLE;
  177. return k;
  178. }
  179. }
  180. return k;
  181. }