cg_kernels.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * StarPU
  3. * Copyright (C) Université Bordeaux 1, CNRS 2008-2010 (see AUTHORS file)
  4. *
  5. * This program 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. * This program 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 "cg.h"
  17. /*
  18. * DOT kernel : s = dot(v1, v2)
  19. */
  20. static void dot_kernel_cuda(void *descr[], void *cl_arg)
  21. {
  22. TYPE *dot = (TYPE *)STARPU_VARIABLE_GET_PTR(descr[0]);
  23. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  24. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[2]);
  25. unsigned n = STARPU_VECTOR_GET_NX(descr[1]);
  26. /* Get current value */
  27. TYPE host_dot;
  28. cudaMemcpy(&host_dot, dot, sizeof(TYPE), cudaMemcpyDeviceToHost);
  29. cudaThreadSynchronize();
  30. TYPE local_dot = cublasdot(n, v1, 1, v2, 1);
  31. host_dot += local_dot;
  32. cudaThreadSynchronize();
  33. cudaMemcpy(dot, &host_dot, sizeof(TYPE), cudaMemcpyHostToDevice);
  34. cudaThreadSynchronize();
  35. }
  36. static void dot_kernel_cpu(void *descr[], void *cl_arg)
  37. {
  38. TYPE *dot = (TYPE *)STARPU_VARIABLE_GET_PTR(descr[0]);
  39. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  40. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[2]);
  41. unsigned n = STARPU_VECTOR_GET_NX(descr[1]);
  42. TYPE local_dot;
  43. local_dot = DOT(n, v1, 1, v2, 1);
  44. *dot += local_dot;
  45. }
  46. static struct starpu_perfmodel_t dot_kernel_model = {
  47. .type = STARPU_HISTORY_BASED,
  48. .symbol = "dot_kernel"
  49. };
  50. static starpu_codelet dot_kernel_cl = {
  51. .where = STARPU_CPU|STARPU_CUDA,
  52. .cpu_func = dot_kernel_cpu,
  53. .cuda_func = dot_kernel_cuda,
  54. .nbuffers = 3,
  55. .model = &dot_kernel_model
  56. };
  57. static void bzero_variable_cuda(void *descr[], void *cl_arg)
  58. {
  59. TYPE *v = (TYPE *)STARPU_VARIABLE_GET_PTR(descr[0]);
  60. TYPE zero = 0.0;
  61. cudaMemcpy(v, &zero, sizeof(TYPE), cudaMemcpyHostToDevice);
  62. cudaThreadSynchronize();
  63. }
  64. static void bzero_variable_cpu(void *descr[], void *cl_arg)
  65. {
  66. TYPE *v = (TYPE *)STARPU_VARIABLE_GET_PTR(descr[0]);
  67. memset(v, 0, sizeof(TYPE));
  68. }
  69. static struct starpu_perfmodel_t bzero_variable_model = {
  70. .type = STARPU_HISTORY_BASED,
  71. .symbol = "bzero_variable"
  72. };
  73. static starpu_codelet bzero_variable_cl = {
  74. .where = STARPU_CPU|STARPU_CUDA,
  75. .cpu_func = bzero_variable_cpu,
  76. .cuda_func = bzero_variable_cuda,
  77. .nbuffers = 1,
  78. .model = &bzero_variable_model
  79. };
  80. void dot_kernel(starpu_data_handle v1,
  81. starpu_data_handle v2,
  82. starpu_data_handle s,
  83. unsigned nblocks)
  84. {
  85. int ret;
  86. struct starpu_task *task;
  87. /* Blank the accumulation variable */
  88. task = starpu_task_create();
  89. task->cl = &bzero_variable_cl;
  90. task->buffers[0].handle = s;
  91. task->buffers[0].mode = STARPU_W;
  92. ret = starpu_task_submit(task);
  93. assert(!ret);
  94. unsigned b;
  95. for (b = 0; b < nblocks; b++)
  96. {
  97. task = starpu_task_create();
  98. task->cl = &dot_kernel_cl;
  99. task->buffers[0].handle = s;
  100. task->buffers[0].mode = STARPU_RW;
  101. task->buffers[1].handle = starpu_data_get_sub_data(v1, 1, b);
  102. task->buffers[1].mode = STARPU_R;
  103. task->buffers[2].handle = starpu_data_get_sub_data(v2, 1, b);
  104. task->buffers[2].mode = STARPU_R;
  105. ret = starpu_task_submit(task);
  106. assert(!ret);
  107. }
  108. }
  109. /*
  110. * GEMV kernel : v1 = p1 * v1 + p2 * M v2
  111. */
  112. struct kernel_params {
  113. TYPE p1;
  114. TYPE p2;
  115. };
  116. static void gemv_kernel_cuda(void *descr[], void *cl_arg)
  117. {
  118. struct kernel_params *params = cl_arg;
  119. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  120. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[2]);
  121. TYPE *M = (TYPE *)STARPU_MATRIX_GET_PTR(descr[1]);
  122. unsigned ld = STARPU_MATRIX_GET_LD(descr[1]);
  123. unsigned nx = STARPU_MATRIX_GET_NX(descr[1]);
  124. unsigned ny = STARPU_MATRIX_GET_NY(descr[1]);
  125. TYPE alpha = params->p2;
  126. TYPE beta = params->p1;
  127. /* Compute v1 = alpha M v2 + beta v1 */
  128. cublasgemv('N', nx, ny, alpha, M, ld, v2, 1, beta, v1, 1);
  129. cudaThreadSynchronize();
  130. free(params);
  131. }
  132. #if 0
  133. static void print_vector_from_descr(unsigned nx, TYPE *v)
  134. {
  135. unsigned i;
  136. for (i = 0; i < nx; i++)
  137. {
  138. fprintf(stderr, "%2.2e ", v[i]);
  139. }
  140. fprintf(stderr, "\n");
  141. }
  142. static void print_matrix_from_descr(unsigned nx, unsigned ny, unsigned ld, TYPE *mat)
  143. {
  144. unsigned i, j;
  145. for (j = 0; j < nx; j++)
  146. {
  147. for (i = 0; i < ny; i++)
  148. {
  149. fprintf(stderr, "%2.2e ", mat[j+i*ld]);
  150. }
  151. fprintf(stderr, "\n");
  152. }
  153. }
  154. #endif
  155. static void gemv_kernel_cpu(void *descr[], void *cl_arg)
  156. {
  157. struct kernel_params *params = cl_arg;
  158. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  159. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[2]);
  160. TYPE *M = (TYPE *)STARPU_MATRIX_GET_PTR(descr[1]);
  161. unsigned ld = STARPU_MATRIX_GET_LD(descr[1]);
  162. unsigned nx = STARPU_MATRIX_GET_NX(descr[1]);
  163. unsigned ny = STARPU_MATRIX_GET_NY(descr[1]);
  164. TYPE alpha = params->p2;
  165. TYPE beta = params->p1;
  166. /* Compute v1 = alpha M v2 + beta v1 */
  167. GEMV("N", nx, ny, alpha, M, ld, v2, 1, beta, v1, 1);
  168. free(params);
  169. }
  170. static struct starpu_perfmodel_t gemv_kernel_model = {
  171. .type = STARPU_HISTORY_BASED,
  172. .symbol = "gemv_kernel"
  173. };
  174. static starpu_codelet gemv_kernel_cl = {
  175. .where = STARPU_CPU|STARPU_CUDA,
  176. .cpu_func = gemv_kernel_cpu,
  177. .cuda_func = gemv_kernel_cuda,
  178. .nbuffers = 3,
  179. .model = &gemv_kernel_model
  180. };
  181. void gemv_kernel(starpu_data_handle v1,
  182. starpu_data_handle matrix,
  183. starpu_data_handle v2,
  184. TYPE p1, TYPE p2,
  185. unsigned nblocks)
  186. {
  187. int ret;
  188. unsigned b1, b2;
  189. for (b2 = 0; b2 < nblocks; b2++)
  190. {
  191. for (b1 = 0; b1 < nblocks; b1++)
  192. {
  193. struct starpu_task *task = starpu_task_create();
  194. task->cl = &gemv_kernel_cl;
  195. task->buffers[0].handle = starpu_data_get_sub_data(v1, 1, b2);
  196. task->buffers[0].mode = STARPU_RW;
  197. task->buffers[1].handle = starpu_data_get_sub_data(matrix, 2, b2, b1);
  198. task->buffers[1].mode = STARPU_R;
  199. task->buffers[2].handle = starpu_data_get_sub_data(v2, 1, b1);
  200. task->buffers[2].mode = STARPU_R;
  201. struct kernel_params *params = malloc(sizeof(struct kernel_params));
  202. assert(params);
  203. params->p1 = (b1==0)?p1:1.0;
  204. params->p2 = p2;
  205. task->cl_arg = params;
  206. ret = starpu_task_submit(task);
  207. assert(!ret);
  208. }
  209. }
  210. }
  211. /*
  212. * AXPY + SCAL kernel : v1 = p1 * v1 + p2 * v2
  213. */
  214. static void scal_axpy_kernel_cuda(void *descr[], void *cl_arg)
  215. {
  216. struct kernel_params *params = cl_arg;
  217. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  218. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  219. unsigned n = STARPU_MATRIX_GET_NX(descr[0]);
  220. /* Compute v1 = p1 * v1 + p2 * v2.
  221. * v1 = p1 v1
  222. * v1 = v1 + p2 v2
  223. */
  224. cublasscal(n, params->p1, v1, 1);
  225. cublasaxpy(n, params->p2, v2, 1, v1, 1);
  226. cudaThreadSynchronize();
  227. free(params);
  228. }
  229. static void scal_axpy_kernel_cpu(void *descr[], void *cl_arg)
  230. {
  231. struct kernel_params *params = cl_arg;
  232. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  233. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  234. unsigned nx = STARPU_MATRIX_GET_NX(descr[0]);
  235. /* Compute v1 = p1 * v1 + p2 * v2.
  236. * v1 = p1 v1
  237. * v1 = v1 + p2 v2
  238. */
  239. SCAL(nx, params->p1, v1, 1);
  240. AXPY(nx, params->p2, v2, 1, v1, 1);
  241. free(params);
  242. }
  243. static struct starpu_perfmodel_t scal_axpy_kernel_model = {
  244. .type = STARPU_HISTORY_BASED,
  245. .symbol = "scal_axpy_kernel"
  246. };
  247. static starpu_codelet scal_axpy_kernel_cl = {
  248. .where = STARPU_CPU|STARPU_CUDA,
  249. .cpu_func = scal_axpy_kernel_cpu,
  250. .cuda_func = scal_axpy_kernel_cuda,
  251. .nbuffers = 2,
  252. .model = &scal_axpy_kernel_model
  253. };
  254. void scal_axpy_kernel(starpu_data_handle v1, TYPE p1,
  255. starpu_data_handle v2, TYPE p2,
  256. unsigned nblocks)
  257. {
  258. int ret;
  259. unsigned b;
  260. for (b = 0; b < nblocks; b++)
  261. {
  262. struct starpu_task *task = starpu_task_create();
  263. task->cl = &scal_axpy_kernel_cl;
  264. task->buffers[0].handle = starpu_data_get_sub_data(v1, 1, b);
  265. task->buffers[0].mode = STARPU_RW;
  266. task->buffers[1].handle = starpu_data_get_sub_data(v2, 1, b);
  267. task->buffers[1].mode = STARPU_R;
  268. struct kernel_params *params = malloc(sizeof(struct kernel_params));
  269. assert(params);
  270. params->p1 = p1;
  271. params->p2 = p2;
  272. task->cl_arg = params;
  273. ret = starpu_task_submit(task);
  274. assert(!ret);
  275. }
  276. }
  277. /*
  278. * AXPY kernel : v1 = v1 + p1 * v2
  279. */
  280. static void axpy_kernel_cuda(void *descr[], void *cl_arg)
  281. {
  282. struct kernel_params *params = cl_arg;
  283. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  284. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  285. unsigned n = STARPU_MATRIX_GET_NX(descr[0]);
  286. /* Compute v1 = v1 + p1 * v2.
  287. */
  288. cublasaxpy(n, params->p1, v2, 1, v1, 1);
  289. cudaThreadSynchronize();
  290. free(params);
  291. }
  292. static void axpy_kernel_cpu(void *descr[], void *cl_arg)
  293. {
  294. struct kernel_params *params = cl_arg;
  295. TYPE *v1 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  296. TYPE *v2 = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  297. unsigned nx = STARPU_MATRIX_GET_NX(descr[0]);
  298. /* Compute v1 = p1 * v1 + p2 * v2.
  299. */
  300. AXPY(nx, params->p1, v2, 1, v1, 1);
  301. free(params);
  302. }
  303. static struct starpu_perfmodel_t axpy_kernel_model = {
  304. .type = STARPU_HISTORY_BASED,
  305. .symbol = "axpy_kernel"
  306. };
  307. static starpu_codelet axpy_kernel_cl = {
  308. .where = STARPU_CPU|STARPU_CUDA,
  309. .cpu_func = axpy_kernel_cpu,
  310. .cuda_func = axpy_kernel_cuda,
  311. .nbuffers = 2,
  312. .model = &axpy_kernel_model
  313. };
  314. void axpy_kernel(starpu_data_handle v1,
  315. starpu_data_handle v2, TYPE p1,
  316. unsigned nblocks)
  317. {
  318. int ret;
  319. unsigned b;
  320. for (b = 0; b < nblocks; b++)
  321. {
  322. struct starpu_task *task = starpu_task_create();
  323. task->cl = &axpy_kernel_cl;
  324. task->buffers[0].handle = starpu_data_get_sub_data(v1, 1, b);
  325. task->buffers[0].mode = STARPU_RW;
  326. task->buffers[1].handle = starpu_data_get_sub_data(v2, 1, b);
  327. task->buffers[1].mode = STARPU_R;
  328. struct kernel_params *params = malloc(sizeof(struct kernel_params));
  329. assert(params);
  330. params->p1 = p1;
  331. task->cl_arg = params;
  332. ret = starpu_task_submit(task);
  333. assert(!ret);
  334. }
  335. }
  336. /*
  337. * COPY kernel : vector_dst <- vector_src
  338. */
  339. static void copy_handle_cpu(void *descr[], void *cl_arg)
  340. {
  341. TYPE *dst = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  342. TYPE *src = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  343. unsigned nx = STARPU_VECTOR_GET_NX(descr[0]);
  344. size_t elemsize = STARPU_VECTOR_GET_ELEMSIZE(descr[0]);
  345. memcpy(dst, src, nx*elemsize);
  346. }
  347. static void copy_handle_cuda(void *descr[], void *cl_arg)
  348. {
  349. TYPE *dst = (TYPE *)STARPU_VECTOR_GET_PTR(descr[0]);
  350. TYPE *src = (TYPE *)STARPU_VECTOR_GET_PTR(descr[1]);
  351. unsigned nx = STARPU_VECTOR_GET_NX(descr[0]);
  352. size_t elemsize = STARPU_VECTOR_GET_ELEMSIZE(descr[0]);
  353. cudaMemcpy(dst, src, nx*elemsize, cudaMemcpyDeviceToDevice);
  354. cudaThreadSynchronize();
  355. }
  356. static struct starpu_perfmodel_t copy_handle_model = {
  357. .type = STARPU_HISTORY_BASED,
  358. .symbol = "copy_handle"
  359. };
  360. static starpu_codelet copy_handle_cl = {
  361. .where = STARPU_CPU|STARPU_CUDA,
  362. .cpu_func = copy_handle_cpu,
  363. .cuda_func = copy_handle_cuda,
  364. .nbuffers = 2,
  365. .model = &copy_handle_model
  366. };
  367. void copy_handle(starpu_data_handle dst, starpu_data_handle src, unsigned nblocks)
  368. {
  369. int ret;
  370. unsigned b;
  371. for (b = 0; b < nblocks; b++)
  372. {
  373. struct starpu_task *task = starpu_task_create();
  374. task->cl = &copy_handle_cl;
  375. task->buffers[0].handle = starpu_data_get_sub_data(dst, 1, b);
  376. task->buffers[0].mode = STARPU_W;
  377. task->buffers[1].handle = starpu_data_get_sub_data(src, 1, b);
  378. task->buffers[1].mode = STARPU_R;
  379. ret = starpu_task_submit(task);
  380. assert(!ret);
  381. }
  382. }