driver_opencl_utils.c 22 KB

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