test_interfaces.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011 Institut National de Recherche en Informatique et Automatique
  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. #ifdef STARPU_USE_OPENCL
  18. #include <starpu_opencl.h>
  19. #endif
  20. #include "test_interfaces.h"
  21. /* TODO :
  22. - OpenCL to OpenCL support
  23. - RAM to RAM ?
  24. - Asynchronous vs synchronous
  25. - Better error messages
  26. - call starpu_data_unregister
  27. */
  28. /* Interfaces to test */
  29. extern struct test_config vector_config;
  30. static struct test_config *tests[] = {
  31. &vector_config,
  32. NULL
  33. };
  34. static struct test_config *current_config;
  35. /*
  36. * This variable has to be either -1 or 1.
  37. * The kernels should check that the ith value stored in the data interface is
  38. * equal to i, if factor == 1, or -i, if factor == -1.
  39. */
  40. static int factor = -1;
  41. /*
  42. * Creates a complete task, only knowing on what device it should be executed.
  43. * Note that the global variable <current_config> is heavily used here.
  44. * Arguments :
  45. * - taskp : a pointer to a valid task
  46. * - type : STARPU_{CPU,CUDA,OPENCL}_WORKER. Gordon is not supported.
  47. * - id : -1 if you dont care about the device where the task will be
  48. * executed, as long as it has the right type.
  49. * >= 0 if you want to make sure the task will be executed on the
  50. * idth device that has the specified type.
  51. * Return values :
  52. * -ENODEV
  53. * 0 : success.
  54. */
  55. static int
  56. create_task(struct starpu_task **taskp, enum starpu_archtype type, int id)
  57. {
  58. static int cpu_workers[STARPU_MAXCPUS];
  59. static int cuda_workers[STARPU_MAXCUDADEVS];
  60. static int opencl_workers[STARPU_MAXOPENCLDEVS];
  61. static int n_cpus = -1;
  62. static int n_cudas = -1;
  63. static int n_opencls = -1;
  64. if (n_cpus == -1) /* First time here */
  65. {
  66. /* XXX Dont check them all at once. */
  67. /* XXX Error checking */
  68. n_cpus = starpu_worker_get_ids_by_type(STARPU_CPU_WORKER,
  69. cpu_workers,
  70. STARPU_MAXCPUS);
  71. n_cudas = starpu_worker_get_ids_by_type(STARPU_CUDA_WORKER,
  72. cuda_workers,
  73. STARPU_MAXCUDADEVS);
  74. n_opencls = starpu_worker_get_ids_by_type(STARPU_OPENCL_WORKER,
  75. opencl_workers,
  76. STARPU_MAXOPENCLDEVS);
  77. }
  78. int workerid;
  79. static struct starpu_codelet_t cl;
  80. cl.nbuffers = 1;
  81. switch (type)
  82. {
  83. case STARPU_CPU_WORKER:
  84. if (id != -1)
  85. {
  86. if (id >= n_cpus)
  87. {
  88. fprintf(stderr, "Not enough CPU workers\n");
  89. return -ENODEV;
  90. }
  91. workerid = *(cpu_workers + id);
  92. }
  93. cl.where = STARPU_CPU;
  94. cl.cpu_func = current_config->cpu_func;
  95. break;
  96. #ifdef STARPU_USE_CUDA
  97. case STARPU_CUDA_WORKER:
  98. if (id != -1)
  99. {
  100. if (id >= n_cudas)
  101. {
  102. fprintf(stderr, "Not enough CUDA workers\n");
  103. return -ENODEV;
  104. }
  105. workerid = cuda_workers[id];
  106. }
  107. cl.where = STARPU_CUDA;
  108. cl.cuda_func = current_config->cuda_func;
  109. break;
  110. #endif /* !STARPU_USE_CUDA */
  111. #ifdef STARPU_USE_OPENCL
  112. case STARPU_OPENCL_WORKER:
  113. if (id != -1)
  114. {
  115. if (id >= n_opencls)
  116. {
  117. fprintf(stderr, "Not enough OpenCL workers\n");
  118. return -ENODEV;
  119. }
  120. workerid = *(opencl_workers + id);
  121. }
  122. cl.where = STARPU_OPENCL;
  123. cl.opencl_func = current_config->opencl_func;
  124. break;
  125. #endif /* ! STARPU_USE_OPENCL */
  126. default:
  127. return -ENODEV;
  128. }
  129. struct starpu_task *task = starpu_task_create();
  130. task->synchronous = 1;
  131. task->cl = &cl;
  132. task->buffers[0].handle = current_config->register_func();
  133. task->buffers[0].mode = STARPU_RW;
  134. if (id != -1)
  135. {
  136. task->execute_on_a_specific_worker = 1;
  137. task->workerid = workerid;
  138. }
  139. factor = -factor;
  140. task->cl_arg = &factor;
  141. task->cl_arg_size = sizeof(&factor);
  142. *taskp = task;
  143. return 0;
  144. }
  145. /*
  146. * <device1>_to_<device2> functions.
  147. * They all create and submit a task that has to be executed on <device2>,
  148. * forcing a copy between <device1> and <device2>.
  149. * XXX : could we sometimes use starp_insert_task() ? It seems hars because we
  150. * need to set the execute_on_a_specific_worker field...
  151. */
  152. #ifdef STARPU_USE_CUDA
  153. static int
  154. ram_to_cuda(void)
  155. {
  156. int err;
  157. struct starpu_task *task;
  158. err = create_task(&task, STARPU_CUDA_WORKER, 0);
  159. if (err != 0)
  160. {
  161. fprintf(stderr, "Could not create task\n");
  162. return 1;
  163. }
  164. err = starpu_task_submit(task);
  165. if (err != 0)
  166. {
  167. fprintf(stderr, "Fail : %s\n", strerror(-err));
  168. return 1;
  169. }
  170. fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
  171. return current_config->copy_failed;
  172. }
  173. static int
  174. cuda_to_cuda(void)
  175. {
  176. int err;
  177. struct starpu_task *task;
  178. err = create_task(&task, STARPU_CUDA_WORKER, 1);
  179. if (err != 0)
  180. {
  181. return 1;
  182. }
  183. err = starpu_task_submit(task);
  184. if (err != 0)
  185. {
  186. return 1;
  187. }
  188. fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
  189. return current_config->copy_failed;
  190. }
  191. static int
  192. cuda_to_ram(void)
  193. {
  194. int err;
  195. struct starpu_task *task;
  196. err = create_task(&task, STARPU_CPU_WORKER, -1);
  197. if (err != 0)
  198. {
  199. fprintf(stderr, "Could not create the task\n");
  200. return 1;
  201. }
  202. err = starpu_task_submit(task);
  203. if (err != 0)
  204. {
  205. fprintf(stderr, "Fail : %s\n", strerror(-err));
  206. return 1;
  207. }
  208. fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
  209. return current_config->copy_failed;
  210. }
  211. #endif /* !STARPU_USE_CUDA */
  212. #ifdef STARPU_USE_OPENCL
  213. static int
  214. ram_to_opencl()
  215. {
  216. int err;
  217. struct starpu_task *task;
  218. err = create_task(&task, STARPU_OPENCL_WORKER, 0);
  219. if (err != 0)
  220. {
  221. fprintf(stderr, "Could not create the task\n");
  222. return 1;
  223. }
  224. err = starpu_task_submit(task);
  225. if (err != 0)
  226. {
  227. fprintf(stderr, "Fail : %s\n", strerror(-err));
  228. return 1;
  229. }
  230. fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
  231. return current_config->copy_failed;
  232. }
  233. static int
  234. opencl_to_ram()
  235. {
  236. int err;
  237. struct starpu_task *task;
  238. err = create_task(&task, STARPU_CPU_WORKER, -1);
  239. if (err != 0)
  240. {
  241. fprintf(stderr, "Could not create the task\n");
  242. return 1;
  243. }
  244. err = starpu_task_submit(task);
  245. if (err != 0)
  246. {
  247. fprintf(stderr, "Fail : %s\n", strerror(-err));
  248. return 1;
  249. }
  250. fprintf(stderr, "[%s] : %d\n", __func__, current_config->copy_failed);
  251. return current_config->copy_failed;
  252. }
  253. #endif /* !STARPU_USE_OPENCL */
  254. /* End of the <device1>_to_<device2> functions. */
  255. static int
  256. run(void)
  257. {
  258. int err;
  259. #ifdef STARPU_USE_CUDA
  260. /* RAM -> CUDA -> CUDA -> RAM */
  261. err = ram_to_cuda();
  262. if (err != 0)
  263. {
  264. fprintf(stderr, "RAM to CUDA failed\n");
  265. return 1;
  266. }
  267. #ifdef HAVE_CUDA_MEMCPY_PEER
  268. err = cuda_to_cuda();
  269. if (err != 0)
  270. {
  271. fprintf(stderr, "CUDA to RAM failed\n");
  272. return 1;
  273. }
  274. #endif /* !HAVE_CUDA_MEMCPY_PEER */
  275. err = cuda_to_ram();
  276. if (err != 0)
  277. {
  278. fprintf(stderr, "CUDA to RAM failed\n");
  279. return 1;
  280. }
  281. #endif /* !STARPU_USE_CUDA */
  282. #if STARPU_USE_OPENCL
  283. /* RAM -> OpenCL -> RAM */
  284. err = ram_to_opencl();
  285. if (err != 0)
  286. {
  287. fprintf(stderr, "RAM to OpenCL failed\n");
  288. return 1;
  289. }
  290. err = opencl_to_ram();
  291. if (err != 0)
  292. {
  293. fprintf(stderr, "OpenCL to RAM failed\n");
  294. return 1;
  295. }
  296. #endif /* !STARPU_USE_OPENCL */
  297. return 0;
  298. }
  299. static int
  300. load_conf(struct test_config *config)
  301. {
  302. if (!config ||
  303. !config->cpu_func ||
  304. #ifdef STARPU_USE_CUDA
  305. !config->cuda_func ||
  306. #endif
  307. #ifdef STARPU_USE_OPENCL
  308. !config->opencl_func ||
  309. #endif
  310. !config->register_func)
  311. {
  312. return 1;
  313. }
  314. current_config = config;
  315. return 0;
  316. }
  317. int
  318. main(void)
  319. {
  320. int i;
  321. int err;
  322. err = starpu_init(NULL);
  323. if (err != 0)
  324. {
  325. fprintf(stderr, "starpu_init failed, not running the tests\n");
  326. return EXIT_FAILURE;
  327. }
  328. for (i = 0; tests[i] != NULL; ++i)
  329. {
  330. err = load_conf(tests[i]);
  331. if (err != 0)
  332. {
  333. fprintf(stderr, "Skipping test, invalid conf\n");
  334. continue;
  335. }
  336. err = run();
  337. if (err != 0)
  338. fprintf(stderr, "%s : FAIL\n", current_config->name);
  339. else
  340. fprintf(stderr, "%s : OK\n", current_config->name);
  341. }
  342. starpu_shutdown();
  343. return EXIT_SUCCESS;
  344. }