cl_createkernel.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010-2020 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  4. *
  5. * StarPU is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * StarPU is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include "socl.h"
  17. static void soclCreateKernel_task(void *data)
  18. {
  19. struct _cl_kernel *k = (struct _cl_kernel *)data;
  20. int range = starpu_worker_get_range();
  21. cl_int err;
  22. if (k->program->cl_programs[range] == NULL)
  23. {
  24. k->errcodes[range] = CL_SUCCESS;
  25. DEBUG_MSG("[Device %u] Kernel creation skipped: program has not been built for this device.\n", starpu_worker_get_id_check());
  26. return;
  27. }
  28. DEBUG_MSG("[Device %u] Creating kernel...\n", starpu_worker_get_id_check());
  29. k->cl_kernels[range] = clCreateKernel(k->program->cl_programs[range], k->kernel_name, &err);
  30. if (err != CL_SUCCESS)
  31. {
  32. k->errcodes[range] = err;
  33. ERROR_STOP("[Device %u] Unable to create kernel. Error %d. Aborting.\n", starpu_worker_get_id_check(), err);
  34. return;
  35. }
  36. /* One worker creates argument structures */
  37. if (__sync_bool_compare_and_swap(&k->num_args, 0, 666))
  38. {
  39. unsigned int i;
  40. cl_uint num_args;
  41. err = clGetKernelInfo(k->cl_kernels[range], CL_KERNEL_NUM_ARGS, sizeof(num_args), &num_args, NULL);
  42. if (err != CL_SUCCESS)
  43. {
  44. DEBUG_CL("clGetKernelInfo", err);
  45. ERROR_STOP("Unable to get kernel argument count. Aborting.\n");
  46. }
  47. k->num_args = num_args;
  48. DEBUG_MSG("Kernel has %u arguments\n", num_args);
  49. k->arg_size = (size_t*)malloc(sizeof(size_t) * num_args);
  50. k->arg_value = (void**)malloc(sizeof(void*) * num_args);
  51. k->arg_type = (enum kernel_arg_type*)malloc(sizeof(enum kernel_arg_type) * num_args);
  52. /* Settings default type to NULL */
  53. for (i=0; i<num_args; i++)
  54. {
  55. k->arg_value[i] = NULL;
  56. k->arg_type[i] = Null;
  57. }
  58. }
  59. }
  60. static void release_callback_kernel(void * e)
  61. {
  62. cl_kernel kernel = (cl_kernel)e;
  63. //Free args
  64. unsigned int i;
  65. for (i=0; i<kernel->num_args; i++)
  66. {
  67. switch (kernel->arg_type[i])
  68. {
  69. case Null:
  70. case Buffer:
  71. break;
  72. case Immediate:
  73. free(kernel->arg_value[i]);
  74. break;
  75. }
  76. }
  77. if (kernel->arg_size != NULL)
  78. free(kernel->arg_size);
  79. if (kernel->arg_value != NULL)
  80. free(kernel->arg_value);
  81. if (kernel->arg_type != NULL)
  82. free(kernel->arg_type);
  83. //Release real kernels...
  84. for (i=0; i<socl_device_count; i++)
  85. {
  86. if (kernel->cl_kernels[i] != NULL)
  87. {
  88. cl_int err = clReleaseKernel(kernel->cl_kernels[i]);
  89. if (err != CL_SUCCESS)
  90. DEBUG_CL("clReleaseKernel", err);
  91. }
  92. }
  93. //Release perfmodel
  94. //FIXME: we cannot release performance models before StarPU shutdown as it
  95. //will use them to store kernel execution times
  96. //free(kernel->perfmodel);
  97. //free(kernel->kernel_name);
  98. gc_entity_unstore(&kernel->program);
  99. free(kernel->cl_kernels);
  100. free(kernel->errcodes);
  101. }
  102. CL_API_SUFFIX__VERSION_1_0
  103. CL_API_ENTRY cl_kernel CL_API_CALL
  104. soclCreateKernel(cl_program program,
  105. const char * kernel_name,
  106. cl_int * errcode_ret)
  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. }