cl_buildprogram.c 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2012,2016-2018 CNRS
  4. * Copyright (C) 2010-2012,2018 Université de Bordeaux
  5. * Copyright (C) 2011,2012 Inria
  6. *
  7. * StarPU is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published by
  9. * the Free Software Foundation; either version 2.1 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * StarPU is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. *
  16. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  17. */
  18. #include "socl.h"
  19. struct bp_data
  20. {
  21. cl_program program;
  22. char * options;
  23. const cl_device_id * device_list;
  24. cl_uint num_devices;
  25. };
  26. static void soclBuildProgram_task(void *data)
  27. {
  28. struct bp_data *d = (struct bp_data*)data;
  29. cl_device_id device;
  30. cl_int err;
  31. unsigned int i;
  32. int wid = starpu_worker_get_id_check();
  33. /* Check if the kernel has to be built for this device */
  34. for (i=0; i <= d->num_devices; i++)
  35. {
  36. if (i == d->num_devices)
  37. return;
  38. if (d->device_list[i]->worker_id == wid)
  39. break;
  40. }
  41. int range = starpu_worker_get_range();
  42. starpu_opencl_get_device(wid, &device);
  43. DEBUG_MSG("[Worker %d] Building program...\n", wid);
  44. cl_device_type dev_type;
  45. clGetDeviceInfo(device, CL_DEVICE_TYPE, sizeof(cl_device_type), &dev_type, NULL);
  46. char * dev_type_str = (dev_type == CL_DEVICE_TYPE_CPU ? "CPU" :
  47. dev_type == CL_DEVICE_TYPE_GPU ? "GPU" :
  48. dev_type == CL_DEVICE_TYPE_ACCELERATOR ? "ACCELERATOR" : "UNKNOWN");
  49. char opts[4096];
  50. snprintf(opts, sizeof(opts), "-DSOCL_DEVICE_TYPE_%s %s",
  51. dev_type_str, (d->options != NULL ? d->options : ""));
  52. err = clBuildProgram(d->program->cl_programs[range], 1, &device, opts, NULL, NULL);
  53. if (err != CL_SUCCESS)
  54. {
  55. size_t len;
  56. clGetProgramBuildInfo(d->program->cl_programs[range], device, CL_PROGRAM_BUILD_LOG, 0, NULL, &len);
  57. char * buffer = malloc(len+1);
  58. buffer[len] = '\0';
  59. clGetProgramBuildInfo(d->program->cl_programs[range], device, CL_PROGRAM_BUILD_LOG, len, buffer, NULL);
  60. DEBUG_CL("clBuildProgram", err);
  61. ERROR_MSG("clBuildProgram: %s\n Aborting.\n", buffer);
  62. free(buffer);
  63. }
  64. DEBUG_MSG("[Worker %d] Done building.\n", wid);
  65. }
  66. CL_API_SUFFIX__VERSION_1_0
  67. CL_API_ENTRY cl_int CL_API_CALL
  68. soclBuildProgram(cl_program program,
  69. cl_uint num_devices,
  70. const cl_device_id * device_list,
  71. const char * options,
  72. void (*pfn_notify)(cl_program program, void * user_data),
  73. void * user_data)
  74. {
  75. struct bp_data *data;
  76. program->options = options != NULL ? strdup(options) : NULL;
  77. program->options_size = options != NULL ? strlen(options)+1 : 0;
  78. data = (struct bp_data*)malloc(sizeof(struct bp_data));
  79. gc_entity_store(&data->program, program);
  80. data->options = (char*)options;
  81. /* If the device list is empty, we compile for every device in the context associated to the program */
  82. if (device_list == NULL)
  83. {
  84. num_devices = program->context->num_devices;
  85. device_list = program->context->devices;
  86. }
  87. data->num_devices = num_devices;
  88. data->device_list = device_list;
  89. /*FIXME: starpu_execute_on_specific_workers is synchronous.
  90. * However pfn_notify is useful only because build is supposed to be asynchronous
  91. */
  92. unsigned workers[num_devices];
  93. unsigned i;
  94. for (i=0; i<num_devices; i++)
  95. {
  96. workers[i] = device_list[i]->worker_id;
  97. }
  98. starpu_execute_on_specific_workers(soclBuildProgram_task, data, num_devices, workers, "SOCL_BUILD_PROGRAM");
  99. if (pfn_notify != NULL)
  100. pfn_notify(program, user_data);
  101. gc_entity_unstore(&data->program);
  102. free(data);
  103. return CL_SUCCESS;
  104. }