cl_createkernel.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010,2011 University of Bordeaux
  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. struct _cl_kernel *k = (struct _cl_kernel *)data;
  19. int range = starpu_worker_get_range();
  20. cl_int err;
  21. if (k->program->cl_programs[range] == NULL) {
  22. k->errcodes[range] = CL_SUCCESS;
  23. DEBUG_MSG("[Device %d] Kernel creation skipped: program has not been built for this device.\n", starpu_worker_get_id());
  24. return;
  25. }
  26. DEBUG_MSG("[Device %d] Creating kernel...\n", starpu_worker_get_id());
  27. k->cl_kernels[range] = clCreateKernel(k->program->cl_programs[range], k->kernel_name, &err);
  28. if (err != CL_SUCCESS) {
  29. k->errcodes[range] = err;
  30. ERROR_STOP("[Device %d] Unable to create kernel. Error %d. Aborting.\n", starpu_worker_get_id(), err);
  31. return;
  32. }
  33. /* One worker creates argument structures */
  34. if (__sync_bool_compare_and_swap(&k->num_args, 0, 666)) {
  35. unsigned int i;
  36. cl_uint num_args;
  37. err = clGetKernelInfo(k->cl_kernels[range], CL_KERNEL_NUM_ARGS, sizeof(num_args), &num_args, NULL);
  38. if (err != CL_SUCCESS) {
  39. DEBUG_CL("clGetKernelInfo", err);
  40. ERROR_STOP("Unable to get kernel argument count. Aborting.\n");
  41. }
  42. k->num_args = num_args;
  43. DEBUG_MSG("Kernel has %d arguments\n", num_args);
  44. k->arg_size = (size_t*)malloc(sizeof(size_t) * num_args);
  45. k->arg_value = (void**)malloc(sizeof(void*) * num_args);
  46. k->arg_type = (enum kernel_arg_type*)malloc(sizeof(enum kernel_arg_type) * num_args);
  47. /* Settings default type to NULL */
  48. for (i=0; i<num_args; i++) {
  49. k->arg_value[i] = NULL;
  50. k->arg_type[i] = Null;
  51. }
  52. }
  53. }
  54. static void release_callback_kernel(void * e) {
  55. cl_kernel kernel = (cl_kernel)e;
  56. //Free args
  57. unsigned int i;
  58. for (i=0; i<kernel->num_args; i++) {
  59. switch (kernel->arg_type[i]) {
  60. case Null:
  61. break;
  62. case Buffer:
  63. gc_entity_unstore((cl_mem*)&kernel->arg_value[i]);
  64. break;
  65. case Immediate:
  66. free(kernel->arg_value[i]);
  67. break;
  68. }
  69. }
  70. if (kernel->arg_size != NULL)
  71. free(kernel->arg_size);
  72. if (kernel->arg_value != NULL)
  73. free(kernel->arg_value);
  74. if (kernel->arg_type != NULL)
  75. free(kernel->arg_type);
  76. //Release real kernels...
  77. for (i=0; i<socl_device_count; i++) {
  78. if (kernel->cl_kernels[i] != NULL) {
  79. cl_int err = clReleaseKernel(kernel->cl_kernels[i]);
  80. if (err != CL_SUCCESS)
  81. DEBUG_CL("clReleaseKernel", err);
  82. }
  83. }
  84. //Release perfmodel
  85. free(kernel->perfmodel);
  86. gc_entity_unstore(&kernel->program);
  87. free(kernel->kernel_name);
  88. free(kernel->cl_kernels);
  89. free(kernel->errcodes);
  90. }
  91. CL_API_ENTRY cl_kernel CL_API_CALL
  92. soclCreateKernel(cl_program program,
  93. const char * kernel_name,
  94. cl_int * errcode_ret) CL_API_SUFFIX__VERSION_1_0
  95. {
  96. cl_kernel k;
  97. if (program == NULL) {
  98. if (errcode_ret != NULL)
  99. *errcode_ret = CL_INVALID_PROGRAM;
  100. return NULL;
  101. }
  102. //TODO: check programs (see opencl specs)
  103. /* Create Kernel structure */
  104. k = (cl_kernel)gc_entity_alloc(sizeof(struct _cl_kernel), release_callback_kernel);
  105. if (k == NULL) {
  106. if (errcode_ret != NULL)
  107. *errcode_ret = CL_OUT_OF_HOST_MEMORY;
  108. return NULL;
  109. }
  110. gc_entity_store(&k->program, program);
  111. k->kernel_name = strdup(kernel_name);
  112. k->perfmodel = malloc(sizeof(struct starpu_perfmodel));
  113. memset(k->perfmodel, 0, sizeof(struct starpu_perfmodel));
  114. k->perfmodel->type = STARPU_HISTORY_BASED;
  115. k->perfmodel->symbol = k->kernel_name;
  116. k->num_args = 0;
  117. k->arg_value = NULL;
  118. k->arg_size = NULL;
  119. #ifdef DEBUG
  120. static int id = 0;
  121. k->id = id++;
  122. #endif
  123. k->cl_kernels = (cl_kernel*)malloc(socl_device_count * sizeof(cl_kernel));
  124. k->errcodes = (cl_int*)malloc(socl_device_count * sizeof(cl_int));
  125. {
  126. unsigned int i;
  127. for (i=0; i<socl_device_count; i++) {
  128. k->cl_kernels[i] = NULL;
  129. k->errcodes[i] = -9999;
  130. }
  131. }
  132. /* Create kernel on each device */
  133. DEBUG_MSG("[Kernel %d] Create %d kernels (name \"%s\")\n", k->id, socl_device_count, kernel_name);
  134. starpu_execute_on_each_worker_ex(soclCreateKernel_task, k, STARPU_OPENCL, "SOCL_CREATE_KERNEL");
  135. if (errcode_ret != NULL) {
  136. unsigned int i;
  137. *errcode_ret = CL_SUCCESS;
  138. for (i=0; i<socl_device_count; i++) {
  139. switch (k->errcodes[i]) {
  140. #define CASE_RET(e) case e: *errcode_ret = e; return k;
  141. CASE_RET(CL_INVALID_PROGRAM)
  142. CASE_RET(CL_INVALID_PROGRAM_EXECUTABLE)
  143. CASE_RET(CL_INVALID_KERNEL_NAME)
  144. CASE_RET(CL_INVALID_KERNEL_DEFINITION)
  145. CASE_RET(CL_INVALID_VALUE)
  146. CASE_RET(CL_OUT_OF_RESOURCES)
  147. CASE_RET(CL_OUT_OF_HOST_MEMORY)
  148. #undef CASE_RET
  149. }
  150. }
  151. if (k->num_args == 666) {
  152. *errcode_ret = CL_INVALID_PROGRAM_EXECUTABLE;
  153. return k;
  154. }
  155. }
  156. return k;
  157. }