driver_opencl_utils.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806
  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 <starpu.h>
  17. #include <sys/stat.h>
  18. #include <stdlib.h>
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include <sys/types.h>
  22. #include <common/config.h>
  23. #ifdef HAVE_UNISTD_H
  24. #include <unistd.h>
  25. #endif
  26. #include <starpu_opencl.h>
  27. #include <starpu_profiling.h>
  28. #include <core/workers.h>
  29. #include <common/utils.h>
  30. #include "driver_opencl_utils.h"
  31. #include "driver_opencl.h"
  32. #ifdef HAVE_CL_CL_EXT_H
  33. #include <CL/cl_ext.h>
  34. #endif
  35. char *_starpu_opencl_program_dir;
  36. #define _STARPU_STRINGIFY_(x) #x
  37. #define _STARPU_STRINGIFY(x) _STARPU_STRINGIFY_(x)
  38. static
  39. int _starpu_opencl_locate_file(const char *source_file_name, char **located_file_name, char **located_dir_name)
  40. {
  41. int ret = EXIT_FAILURE;
  42. *located_file_name = NULL;
  43. *located_dir_name = NULL;
  44. _STARPU_DEBUG("Trying to locate <%s>\n", source_file_name);
  45. if (access(source_file_name, R_OK) == 0)
  46. {
  47. _STARPU_CALLOC(*located_file_name, 1, strlen(source_file_name)+1);
  48. snprintf(*located_file_name, strlen(source_file_name)+1, "%s", source_file_name);
  49. ret = EXIT_SUCCESS;
  50. }
  51. if (ret == EXIT_FAILURE && _starpu_opencl_program_dir)
  52. {
  53. _STARPU_CALLOC(*located_file_name, 1, strlen(_starpu_opencl_program_dir)+1+strlen(source_file_name)+1);
  54. snprintf(*located_file_name, strlen(_starpu_opencl_program_dir)+1+strlen(source_file_name)+1, "%s/%s", _starpu_opencl_program_dir, source_file_name);
  55. _STARPU_DEBUG("Trying to locate <%s>\n", *located_file_name);
  56. if (access(*located_file_name, R_OK) == 0)
  57. ret = EXIT_SUCCESS;
  58. }
  59. #ifdef STARPU_DEVEL
  60. if (ret == EXIT_FAILURE)
  61. {
  62. _STARPU_CALLOC(*located_file_name, 1, strlen(STARPU_SRC_DIR)+1+strlen(source_file_name)+1);
  63. snprintf(*located_file_name, strlen(STARPU_SRC_DIR)+1+strlen(source_file_name)+1, "%s/%s", STARPU_SRC_DIR, source_file_name);
  64. _STARPU_DEBUG("Trying to locate <%s>\n", *located_file_name);
  65. if (access(*located_file_name, R_OK) == 0)
  66. ret = EXIT_SUCCESS;
  67. }
  68. #endif
  69. if (ret == EXIT_FAILURE)
  70. {
  71. _STARPU_CALLOC(*located_file_name, 1, strlen(_STARPU_STRINGIFY(STARPU_OPENCL_DATADIR))+1+strlen(source_file_name)+1);
  72. snprintf(*located_file_name, strlen(_STARPU_STRINGIFY(STARPU_OPENCL_DATADIR))+1+strlen(source_file_name)+1, "%s/%s", _STARPU_STRINGIFY(STARPU_OPENCL_DATADIR), source_file_name);
  73. _STARPU_DEBUG("Trying to locate <%s>\n", *located_file_name);
  74. if (access(*located_file_name, R_OK) == 0)
  75. ret = EXIT_SUCCESS;
  76. }
  77. if (ret == EXIT_FAILURE)
  78. {
  79. _STARPU_ERROR("Cannot locate file <%s>\n", source_file_name);
  80. }
  81. else
  82. {
  83. char *last = strrchr(*located_file_name, '/');
  84. if (!last)
  85. {
  86. _STARPU_CALLOC(*located_dir_name, 2, sizeof(char));
  87. snprintf(*located_dir_name, 2, "%s", "");
  88. }
  89. else
  90. {
  91. _STARPU_CALLOC(*located_dir_name, 1, 1+strlen(*located_file_name));
  92. snprintf(*located_dir_name, 1+strlen(*located_file_name), "%s", *located_file_name);
  93. (*located_dir_name)[strlen(*located_file_name)-strlen(last)+1] = '\0';
  94. }
  95. }
  96. return ret;
  97. }
  98. cl_int starpu_opencl_load_kernel(cl_kernel *kernel, cl_command_queue *queue, struct starpu_opencl_program *opencl_programs,
  99. const char *kernel_name, int devid)
  100. {
  101. cl_int err;
  102. cl_device_id device;
  103. cl_program program;
  104. starpu_opencl_get_device(devid, &device);
  105. starpu_opencl_get_queue(devid, queue);
  106. program = opencl_programs->programs[devid];
  107. if (!program)
  108. {
  109. _STARPU_DISP("Program not available for device <%d>\n", devid);
  110. return CL_INVALID_PROGRAM;
  111. }
  112. // Create the compute kernel in the program we wish to run
  113. *kernel = clCreateKernel(program, kernel_name, &err);
  114. if (STARPU_UNLIKELY(err != CL_SUCCESS))
  115. STARPU_OPENCL_REPORT_ERROR(err);
  116. return CL_SUCCESS;
  117. }
  118. cl_int starpu_opencl_release_kernel(cl_kernel kernel)
  119. {
  120. cl_int err;
  121. err = clReleaseKernel(kernel);
  122. if (STARPU_UNLIKELY(err != CL_SUCCESS))
  123. STARPU_OPENCL_REPORT_ERROR(err);
  124. return CL_SUCCESS;
  125. }
  126. static
  127. char *_starpu_opencl_load_program_source(const char *filename)
  128. {
  129. struct stat statbuf;
  130. FILE *fh;
  131. char *source;
  132. int x;
  133. int c;
  134. int err;
  135. fh = fopen(filename, "r");
  136. if (!fh)
  137. return NULL;
  138. err = stat(filename, &statbuf);
  139. STARPU_ASSERT_MSG(err == 0, "could not open file %s\n", filename);
  140. _STARPU_MALLOC(source, statbuf.st_size + 1);
  141. for(c=fgetc(fh), x=0 ; c != EOF ; c =fgetc(fh), x++)
  142. {
  143. source[x] = (char)c;
  144. }
  145. source[x] = '\0';
  146. _STARPU_EXTRA_DEBUG("OpenCL kernel <%s>\n", source);
  147. fclose(fh);
  148. return source;
  149. }
  150. static
  151. char *_starpu_opencl_load_program_binary(const char *filename, size_t *len)
  152. {
  153. struct stat statbuf;
  154. FILE *fh;
  155. char *binary;
  156. int err;
  157. fh = fopen(filename, "r");
  158. if (fh == 0)
  159. return NULL;
  160. err = stat(filename, &statbuf);
  161. STARPU_ASSERT_MSG(err == 0, "could not open file %s\n", filename);
  162. binary = (char *) malloc(statbuf.st_size);
  163. if (!binary)
  164. {
  165. fclose(fh);
  166. return binary;
  167. }
  168. err = fread(binary, statbuf.st_size, 1, fh);
  169. STARPU_ASSERT_MSG(err == 1, "could not read from file %s\n", filename);
  170. fclose(fh);
  171. *len = statbuf.st_size;
  172. return binary;
  173. }
  174. static
  175. void _starpu_opencl_create_binary_directory(char *path, size_t maxlen)
  176. {
  177. static int _directory_created = 0;
  178. snprintf(path, maxlen, "%s/.starpu/opencl/", _starpu_get_home_path());
  179. if (_directory_created == 0)
  180. {
  181. _STARPU_DEBUG("Creating directory %s\n", path);
  182. _starpu_mkpath_and_check(path, S_IRWXU);
  183. _directory_created = 1;
  184. }
  185. }
  186. char *_starpu_opencl_get_device_type_as_string(int id)
  187. {
  188. cl_device_type type;
  189. type = _starpu_opencl_get_device_type(id);
  190. switch (type)
  191. {
  192. case CL_DEVICE_TYPE_GPU: return "gpu";
  193. case CL_DEVICE_TYPE_ACCELERATOR: return "acc";
  194. case CL_DEVICE_TYPE_CPU: return "cpu";
  195. default: return "unk";
  196. }
  197. }
  198. static
  199. int _starpu_opencl_get_binary_name(char *binary_file_name, size_t maxlen, const char *source_file_name, int dev, cl_device_id device)
  200. {
  201. char binary_directory[1024];
  202. char *p;
  203. cl_int err;
  204. cl_uint vendor_id;
  205. _starpu_opencl_create_binary_directory(binary_directory, sizeof(binary_directory));
  206. p = strrchr(source_file_name, '/');
  207. snprintf(binary_file_name, maxlen, "%s/%s", binary_directory, p?p:source_file_name);
  208. p = strstr(binary_file_name, ".cl");
  209. if (p == NULL) p=binary_file_name + strlen(binary_file_name);
  210. err = clGetDeviceInfo(device, CL_DEVICE_VENDOR_ID, sizeof(vendor_id), &vendor_id, NULL);
  211. if (STARPU_UNLIKELY(err != CL_SUCCESS)) STARPU_OPENCL_REPORT_ERROR(err);
  212. sprintf(p, ".%s.vendor_id_%d_device_id_%d", _starpu_opencl_get_device_type_as_string(dev), (int)vendor_id, dev);
  213. return CL_SUCCESS;
  214. }
  215. static
  216. int _starpu_opencl_compile_or_load_opencl_from_string(const char *opencl_program_source, const char* build_options,
  217. struct starpu_opencl_program *opencl_programs, const char* source_file_name)
  218. {
  219. unsigned int dev;
  220. unsigned int nb_devices;
  221. nb_devices = _starpu_opencl_get_device_count();
  222. // Iterate over each device
  223. for(dev = 0; dev < nb_devices; dev ++)
  224. {
  225. cl_device_id device;
  226. cl_context context;
  227. cl_program program;
  228. cl_int err;
  229. if (opencl_programs)
  230. {
  231. opencl_programs->programs[dev] = NULL;
  232. }
  233. starpu_opencl_get_device(dev, &device);
  234. starpu_opencl_get_context(dev, &context);
  235. if (context == NULL)
  236. {
  237. _STARPU_DEBUG("[%u] is not a valid OpenCL context\n", dev);
  238. continue;
  239. }
  240. // Create the compute program from the source buffer
  241. program = clCreateProgramWithSource(context, 1, (const char **) &opencl_program_source, NULL, &err);
  242. if (!program || err != CL_SUCCESS)
  243. {
  244. _STARPU_DISP("Error: Failed to load program source with options %s!\n", build_options);
  245. return EXIT_FAILURE;
  246. }
  247. // Build the program executable
  248. err = clBuildProgram(program, 1, &device, build_options, NULL, NULL);
  249. // Get the status
  250. {
  251. cl_build_status status;
  252. size_t len;
  253. clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &len);
  254. if (len > 2)
  255. {
  256. char *buffer;
  257. _STARPU_MALLOC(buffer, len);
  258. clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, len, buffer, &len);
  259. _STARPU_DISP("Compilation output\n%s\n", buffer);
  260. free(buffer);
  261. }
  262. clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS, sizeof(status), &status, NULL);
  263. if (err != CL_SUCCESS || status != CL_BUILD_SUCCESS)
  264. {
  265. _STARPU_DISP("Error: Failed to build program executable!\n");
  266. _STARPU_DISP("clBuildProgram: %d - clGetProgramBuildInfo: %d\n", err, status);
  267. return EXIT_FAILURE;
  268. }
  269. }
  270. // Store program
  271. if (opencl_programs)
  272. {
  273. opencl_programs->programs[dev] = program;
  274. }
  275. else
  276. {
  277. char binary_file_name[2048];
  278. char *binary;
  279. size_t binary_len;
  280. FILE *fh;
  281. err = _starpu_opencl_get_binary_name(binary_file_name, sizeof(binary_file_name), source_file_name, dev, device);
  282. if (STARPU_UNLIKELY(err != CL_SUCCESS)) STARPU_OPENCL_REPORT_ERROR(err);
  283. err = clGetProgramInfo(program, CL_PROGRAM_BINARY_SIZES, sizeof(size_t), &binary_len, NULL);
  284. if (STARPU_UNLIKELY(err != CL_SUCCESS)) STARPU_OPENCL_REPORT_ERROR(err);
  285. _STARPU_MALLOC(binary, binary_len);
  286. err = clGetProgramInfo(program, CL_PROGRAM_BINARIES, sizeof(binary), &binary, NULL);
  287. if (STARPU_UNLIKELY(err != CL_SUCCESS)) STARPU_OPENCL_REPORT_ERROR(err);
  288. fh = fopen(binary_file_name, "w");
  289. if (fh == NULL)
  290. {
  291. _STARPU_DISP("Error: Failed to open file <%s>\n", binary_file_name);
  292. perror("fopen");
  293. return EXIT_FAILURE;
  294. }
  295. fwrite(binary, binary_len, 1, fh);
  296. fclose(fh);
  297. free(binary);
  298. _STARPU_DEBUG("File <%s> created\n", binary_file_name);
  299. err = clReleaseProgram(program);
  300. if (STARPU_UNLIKELY(err != CL_SUCCESS)) STARPU_OPENCL_REPORT_ERROR(err);
  301. }
  302. }
  303. return EXIT_SUCCESS;
  304. }
  305. void starpu_opencl_load_program_source_malloc(const char *source_file_name, char **located_file_name, char **located_dir_name, char **opencl_program_source)
  306. {
  307. // Locate source file
  308. _starpu_opencl_locate_file(source_file_name, located_file_name, located_dir_name);
  309. _STARPU_DEBUG("Source file name : <%s>\n", *located_file_name);
  310. _STARPU_DEBUG("Source directory name : <%s>\n", *located_dir_name);
  311. // Load the compute program from disk into a char *
  312. char *source = _starpu_opencl_load_program_source(*located_file_name);
  313. if(!source)
  314. _STARPU_ERROR("Failed to load compute program from file <%s>!\n", *located_file_name);
  315. _STARPU_MALLOC(*opencl_program_source, strlen(source)+1);
  316. snprintf(*opencl_program_source, strlen(source)+1, "%s", source);
  317. free(source);
  318. }
  319. void starpu_opencl_load_program_source(const char *source_file_name, char *located_file_name, char *located_dir_name, char *opencl_program_source)
  320. {
  321. char *_located_file_name;
  322. char *_located_dir_name;
  323. // Locate source file
  324. _starpu_opencl_locate_file(source_file_name, &_located_file_name, &_located_dir_name);
  325. _STARPU_DEBUG("Source file name : <%s>\n", _located_file_name);
  326. _STARPU_DEBUG("Source directory name : <%s>\n", _located_dir_name);
  327. // Load the compute program from disk into a char *
  328. char *source = _starpu_opencl_load_program_source(_located_file_name);
  329. if(!source)
  330. _STARPU_ERROR("Failed to load compute program from file <%s>!\n", _located_file_name);
  331. sprintf(located_file_name, "%s", _located_file_name);
  332. free(_located_file_name);
  333. sprintf(located_dir_name, "%s", _located_dir_name);
  334. free(_located_dir_name);
  335. sprintf(opencl_program_source, "%s", source);
  336. free(source);
  337. }
  338. static
  339. int _starpu_opencl_compile_or_load_opencl_from_file(const char *source_file_name, struct starpu_opencl_program *opencl_programs, const char* build_options)
  340. {
  341. int nb_devices;
  342. int ret;
  343. char *located_file_name;
  344. char *located_dir_name;
  345. char new_build_options[1024];
  346. char *opencl_program_source;
  347. // Do not try to load and compile the file if there is no devices
  348. nb_devices = starpu_opencl_worker_get_count();
  349. if (nb_devices == 0) return EXIT_SUCCESS;
  350. starpu_opencl_load_program_source_malloc(source_file_name, &located_file_name, &located_dir_name, &opencl_program_source);
  351. if (!build_options)
  352. build_options = "";
  353. if (!strcmp(located_dir_name, ""))
  354. {
  355. snprintf(new_build_options, sizeof(new_build_options), "%s", build_options);
  356. }
  357. else
  358. {
  359. snprintf(new_build_options, sizeof(new_build_options), "-I %s %s", located_dir_name, build_options);
  360. }
  361. _STARPU_DEBUG("Build options: <%s>\n", new_build_options);
  362. ret = _starpu_opencl_compile_or_load_opencl_from_string(opencl_program_source, new_build_options, opencl_programs, source_file_name);
  363. _STARPU_DEBUG("located_file_name : <%s>\n", located_file_name);
  364. _STARPU_DEBUG("located_dir_name : <%s>\n", located_dir_name);
  365. free(located_file_name);
  366. free(located_dir_name);
  367. free(opencl_program_source);
  368. return ret;
  369. }
  370. int starpu_opencl_compile_opencl_from_file(const char *source_file_name, const char* build_options)
  371. {
  372. return _starpu_opencl_compile_or_load_opencl_from_file(source_file_name, NULL, build_options);
  373. }
  374. int starpu_opencl_compile_opencl_from_string(const char *opencl_program_source, const char *file_name, const char* build_options)
  375. {
  376. return _starpu_opencl_compile_or_load_opencl_from_string(opencl_program_source, build_options, NULL, file_name);
  377. }
  378. int starpu_opencl_load_opencl_from_string(const char *opencl_program_source, struct starpu_opencl_program *opencl_programs,
  379. const char* build_options)
  380. {
  381. return _starpu_opencl_compile_or_load_opencl_from_string(opencl_program_source, build_options, opencl_programs, NULL);
  382. }
  383. int starpu_opencl_load_opencl_from_file(const char *source_file_name, struct starpu_opencl_program *opencl_programs,
  384. const char* build_options)
  385. {
  386. return _starpu_opencl_compile_or_load_opencl_from_file(source_file_name, opencl_programs, build_options);
  387. }
  388. int starpu_opencl_load_binary_opencl(const char *kernel_id, struct starpu_opencl_program *opencl_programs)
  389. {
  390. unsigned int dev;
  391. unsigned int nb_devices;
  392. nb_devices = _starpu_opencl_get_device_count();
  393. // Iterate over each device
  394. for(dev = 0; dev < nb_devices; dev ++)
  395. {
  396. cl_device_id device;
  397. cl_context context;
  398. cl_program program;
  399. cl_int err;
  400. char *binary;
  401. char binary_file_name[1024];
  402. size_t length;
  403. cl_int binary_status;
  404. opencl_programs->programs[dev] = NULL;
  405. starpu_opencl_get_device(dev, &device);
  406. starpu_opencl_get_context(dev, &context);
  407. if (context == NULL)
  408. {
  409. _STARPU_DEBUG("[%u] is not a valid OpenCL context\n", dev);
  410. continue;
  411. }
  412. // Load the binary buffer
  413. err = _starpu_opencl_get_binary_name(binary_file_name, sizeof(binary_file_name), kernel_id, dev, device);
  414. if (STARPU_UNLIKELY(err != CL_SUCCESS)) STARPU_OPENCL_REPORT_ERROR(err);
  415. binary = _starpu_opencl_load_program_binary(binary_file_name, &length);
  416. // Create the compute program from the binary buffer
  417. program = clCreateProgramWithBinary(context, 1, &device, &length, (const unsigned char **) &binary, &binary_status, &err);
  418. if (!program || err != CL_SUCCESS)
  419. {
  420. _STARPU_DISP("Error: Failed to load program binary!\n");
  421. return EXIT_FAILURE;
  422. }
  423. // Build the program executable
  424. err = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
  425. // Get the status
  426. {
  427. cl_build_status status;
  428. size_t len;
  429. clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, 0, NULL, &len);
  430. if (len > 2)
  431. {
  432. char *buffer;
  433. _STARPU_MALLOC(buffer, len);
  434. clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG, len, buffer, &len);
  435. _STARPU_DISP("Compilation output\n%s\n", buffer);
  436. free(buffer);
  437. }
  438. clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_STATUS, sizeof(status), &status, NULL);
  439. if (err != CL_SUCCESS || status != CL_BUILD_SUCCESS)
  440. {
  441. _STARPU_DISP("Error: Failed to build program executable!\n");
  442. _STARPU_DISP("clBuildProgram: %d - clGetProgramBuildInfo: %d\n", err, status);
  443. return EXIT_FAILURE;
  444. }
  445. }
  446. // Store program
  447. opencl_programs->programs[dev] = program;
  448. free(binary);
  449. }
  450. return 0;
  451. }
  452. int starpu_opencl_unload_opencl(struct starpu_opencl_program *opencl_programs)
  453. {
  454. unsigned int dev;
  455. unsigned int nb_devices;
  456. if (!starpu_opencl_worker_get_count())
  457. return 0;
  458. nb_devices = _starpu_opencl_get_device_count();
  459. // Iterate over each device
  460. for(dev = 0; dev < nb_devices; dev ++)
  461. {
  462. if (opencl_programs->programs[dev])
  463. {
  464. cl_int err;
  465. err = clReleaseProgram(opencl_programs->programs[dev]);
  466. if (STARPU_UNLIKELY(err != CL_SUCCESS))
  467. STARPU_OPENCL_REPORT_ERROR(err);
  468. }
  469. }
  470. return 0;
  471. }
  472. int starpu_opencl_collect_stats(cl_event event STARPU_ATTRIBUTE_UNUSED)
  473. {
  474. #if defined(CL_PROFILING_CLOCK_CYCLE_COUNT)||defined(CL_PROFILING_STALL_CYCLE_COUNT)||defined(CL_PROFILING_POWER_CONSUMED)
  475. struct starpu_task *task = starpu_task_get_current();
  476. struct starpu_profiling_task_info *info = task->profiling_info;
  477. #endif
  478. #ifdef CL_PROFILING_CLOCK_CYCLE_COUNT
  479. if (starpu_profiling_status_get() && info)
  480. {
  481. cl_int err;
  482. unsigned int clock_cycle_count;
  483. size_t size;
  484. err = clGetEventProfilingInfo(event, CL_PROFILING_CLOCK_CYCLE_COUNT, sizeof(clock_cycle_count), &clock_cycle_count, &size);
  485. if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
  486. STARPU_ASSERT(size == sizeof(clock_cycle_count));
  487. info->used_cycles += clock_cycle_count;
  488. }
  489. #endif
  490. #ifdef CL_PROFILING_STALL_CYCLE_COUNT
  491. if (starpu_profiling_status_get() && info)
  492. {
  493. cl_int err;
  494. unsigned int stall_cycle_count;
  495. size_t size;
  496. err = clGetEventProfilingInfo(event, CL_PROFILING_STALL_CYCLE_COUNT, sizeof(stall_cycle_count), &stall_cycle_count, &size);
  497. if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
  498. STARPU_ASSERT(size == sizeof(stall_cycle_count));
  499. info->stall_cycles += stall_cycle_count;
  500. }
  501. #endif
  502. #ifdef CL_PROFILING_POWER_CONSUMED
  503. if (info && (starpu_profiling_status_get() || (task->cl && task->cl->energy_model && task->cl->energy_model->benchmarking)))
  504. {
  505. cl_int err;
  506. double energy_consumed;
  507. size_t size;
  508. err = clGetEventProfilingInfo(event, CL_PROFILING_POWER_CONSUMED, sizeof(energy_consumed), &energy_consumed, &size);
  509. if (err != CL_SUCCESS) STARPU_OPENCL_REPORT_ERROR(err);
  510. STARPU_ASSERT(size == sizeof(energy_consumed));
  511. info->energy_consumed += energy_consumed;
  512. }
  513. #endif
  514. return 0;
  515. }
  516. const char *starpu_opencl_error_string(cl_int status)
  517. {
  518. const char *errormsg;
  519. switch (status)
  520. {
  521. case CL_SUCCESS:
  522. errormsg = "Success";
  523. break;
  524. case CL_DEVICE_NOT_FOUND:
  525. errormsg = "Device not found";
  526. break;
  527. case CL_DEVICE_NOT_AVAILABLE:
  528. errormsg = "Device not available";
  529. break;
  530. case CL_COMPILER_NOT_AVAILABLE:
  531. errormsg = "Compiler not available";
  532. break;
  533. case CL_MEM_OBJECT_ALLOCATION_FAILURE:
  534. errormsg = "Memory object allocation failure";
  535. break;
  536. case CL_OUT_OF_RESOURCES:
  537. errormsg = "Out of resources";
  538. break;
  539. case CL_OUT_OF_HOST_MEMORY:
  540. errormsg = "Out of host memory";
  541. break;
  542. case CL_PROFILING_INFO_NOT_AVAILABLE:
  543. errormsg = "Profiling info not available";
  544. break;
  545. case CL_MEM_COPY_OVERLAP:
  546. errormsg = "Memory copy overlap";
  547. break;
  548. case CL_IMAGE_FORMAT_MISMATCH:
  549. errormsg = "Image format mismatch";
  550. break;
  551. case CL_IMAGE_FORMAT_NOT_SUPPORTED:
  552. errormsg = "Image format not supported";
  553. break;
  554. case CL_BUILD_PROGRAM_FAILURE:
  555. errormsg = "Build program failure";
  556. break;
  557. case CL_MAP_FAILURE:
  558. errormsg = "Map failure";
  559. break;
  560. case CL_INVALID_VALUE:
  561. errormsg = "Invalid value";
  562. break;
  563. case CL_INVALID_DEVICE_TYPE:
  564. errormsg = "Invalid device type";
  565. break;
  566. case CL_INVALID_PLATFORM:
  567. errormsg = "Invalid platform";
  568. break;
  569. case CL_INVALID_DEVICE:
  570. errormsg = "Invalid device";
  571. break;
  572. case CL_INVALID_CONTEXT:
  573. errormsg = "Invalid context";
  574. break;
  575. case CL_INVALID_QUEUE_PROPERTIES:
  576. errormsg = "Invalid queue properties";
  577. break;
  578. case CL_INVALID_COMMAND_QUEUE:
  579. errormsg = "Invalid command queue";
  580. break;
  581. case CL_INVALID_HOST_PTR:
  582. errormsg = "Invalid host pointer";
  583. break;
  584. case CL_INVALID_MEM_OBJECT:
  585. errormsg = "Invalid memory object";
  586. break;
  587. case CL_INVALID_IMAGE_FORMAT_DESCRIPTOR:
  588. errormsg = "Invalid image format descriptor";
  589. break;
  590. case CL_INVALID_IMAGE_SIZE:
  591. errormsg = "Invalid image size";
  592. break;
  593. case CL_INVALID_SAMPLER:
  594. errormsg = "Invalid sampler";
  595. break;
  596. case CL_INVALID_BINARY:
  597. errormsg = "Invalid binary";
  598. break;
  599. case CL_INVALID_BUILD_OPTIONS:
  600. errormsg = "Invalid build options";
  601. break;
  602. case CL_INVALID_PROGRAM:
  603. errormsg = "Invalid program";
  604. break;
  605. case CL_INVALID_PROGRAM_EXECUTABLE:
  606. errormsg = "Invalid program executable";
  607. break;
  608. case CL_INVALID_KERNEL_NAME:
  609. errormsg = "Invalid kernel name";
  610. break;
  611. case CL_INVALID_KERNEL_DEFINITION:
  612. errormsg = "Invalid kernel definition";
  613. break;
  614. case CL_INVALID_KERNEL:
  615. errormsg = "Invalid kernel";
  616. break;
  617. case CL_INVALID_ARG_INDEX:
  618. errormsg = "Invalid argument index";
  619. break;
  620. case CL_INVALID_ARG_VALUE:
  621. errormsg = "Invalid argument value";
  622. break;
  623. case CL_INVALID_ARG_SIZE:
  624. errormsg = "Invalid argument size";
  625. break;
  626. case CL_INVALID_KERNEL_ARGS:
  627. errormsg = "Invalid kernel arguments";
  628. break;
  629. case CL_INVALID_WORK_DIMENSION:
  630. errormsg = "Invalid work dimension";
  631. break;
  632. case CL_INVALID_WORK_GROUP_SIZE:
  633. errormsg = "Invalid work group size";
  634. break;
  635. case CL_INVALID_WORK_ITEM_SIZE:
  636. errormsg = "Invalid work item size";
  637. break;
  638. case CL_INVALID_GLOBAL_OFFSET:
  639. errormsg = "Invalid global offset";
  640. break;
  641. case CL_INVALID_EVENT_WAIT_LIST:
  642. errormsg = "Invalid event wait list";
  643. break;
  644. case CL_INVALID_EVENT:
  645. errormsg = "Invalid event";
  646. break;
  647. case CL_INVALID_OPERATION:
  648. errormsg = "Invalid operation";
  649. break;
  650. case CL_INVALID_GL_OBJECT:
  651. errormsg = "Invalid GL object";
  652. break;
  653. case CL_INVALID_BUFFER_SIZE:
  654. errormsg = "Invalid buffer size";
  655. break;
  656. case CL_INVALID_MIP_LEVEL:
  657. errormsg = "Invalid MIP level";
  658. break;
  659. #ifdef CL_PLATFORM_NOT_FOUND_KHR
  660. case CL_PLATFORM_NOT_FOUND_KHR:
  661. errormsg = "Platform not found";
  662. break;
  663. #endif
  664. default:
  665. errormsg = "unknown OpenCL error";
  666. break;
  667. }
  668. return errormsg;
  669. }
  670. void starpu_opencl_display_error(const char *func, const char *file, int line, const char* msg, cl_int status)
  671. {
  672. _STARPU_MSG("oops in %s (%s:%d) (%s) ... <%s> (%d) \n", func, file, line, msg, starpu_opencl_error_string (status), status);
  673. }
  674. int starpu_opencl_set_kernel_args(cl_int *error, cl_kernel *kernel, ...)
  675. {
  676. int i;
  677. va_list ap;
  678. va_start(ap, kernel);
  679. for (i = 0; ; i++)
  680. {
  681. int size = va_arg(ap, int);
  682. if (size == 0)
  683. break;
  684. cl_mem *ptr = va_arg(ap, cl_mem *);
  685. int err = clSetKernelArg(*kernel, i, size, ptr);
  686. if (STARPU_UNLIKELY(err != CL_SUCCESS))
  687. {
  688. *error = err;
  689. break;
  690. }
  691. }
  692. va_end(ap);
  693. return i;
  694. }