test_interfaces.c 8.0 KB

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