dw_sparse_cg_kernels.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2008-2021 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 "dw_sparse_cg.h"
  17. #ifdef STARPU_USE_CUDA
  18. #include <starpu_cublas_v2.h>
  19. #endif
  20. /*
  21. * Algorithm :
  22. *
  23. * i = 0
  24. * r = b - A x
  25. * ( d = A x ; r = r - d )
  26. * d = r
  27. * delta_new = trans(r) r
  28. * delta_0 = delta_new
  29. *
  30. * while (i < i_max && delta_new > eps^2 delta_0)
  31. * {
  32. * q = A d
  33. * alpha = delta_new / ( trans(d) q )
  34. * x = x + alpha d
  35. * if ( i is divisible by 50 )
  36. * r = b - A x
  37. * else
  38. * r = r - alpha q
  39. * delta_old = delta_new
  40. * delta_new = trans(r) r
  41. * beta = delta_new / delta_old
  42. * d = r + beta d
  43. * i = i + 1
  44. * }
  45. */
  46. /*
  47. * compute r = b - A x
  48. *
  49. * descr[0] = A, descr[1] = x, descr [2] = r, descr[3] = b
  50. */
  51. void cpu_codelet_func_1(void *descr[], void *arg)
  52. {
  53. (void)arg;
  54. float *nzval = (float *)STARPU_CSR_GET_NZVAL(descr[0]);
  55. uint32_t *colind = STARPU_CSR_GET_COLIND(descr[0]);
  56. uint32_t *rowptr = STARPU_CSR_GET_ROWPTR(descr[0]);
  57. uint32_t firstentry = STARPU_CSR_GET_ELEMSIZE(descr[0]);
  58. float *vecx = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  59. float *vecr = (float *)STARPU_VECTOR_GET_PTR(descr[2]);
  60. float *vecb = (float *)STARPU_VECTOR_GET_PTR(descr[3]);
  61. uint32_t nrow;
  62. nrow = STARPU_CSR_GET_NROW(descr[0]);
  63. unsigned row;
  64. for (row = 0; row < nrow; row++)
  65. {
  66. float tmp = 0.0f;
  67. unsigned index;
  68. unsigned firstindex = rowptr[row] - firstentry;
  69. unsigned lastindex = rowptr[row+1] - firstentry;
  70. for (index = firstindex; index < lastindex; index++)
  71. {
  72. unsigned col;
  73. col = colind[index];
  74. tmp += nzval[index]*vecx[col];
  75. }
  76. vecr[row] = vecb[row] - tmp;
  77. }
  78. }
  79. /*
  80. * compute d = r
  81. * descr[0] = d, descr[1] = r
  82. */
  83. void cpu_codelet_func_2(void *descr[], void *arg)
  84. {
  85. (void)arg;
  86. /* simply copy r into d */
  87. uint32_t nx = STARPU_VECTOR_GET_NX(descr[0]);
  88. size_t elemsize = STARPU_VECTOR_GET_ELEMSIZE(descr[0]);
  89. STARPU_ASSERT(STARPU_VECTOR_GET_NX(descr[0]) == STARPU_VECTOR_GET_NX(descr[1]));
  90. STARPU_ASSERT(STARPU_VECTOR_GET_ELEMSIZE(descr[0]) == STARPU_VECTOR_GET_ELEMSIZE(descr[1]));
  91. float *src = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  92. float *dst = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  93. memcpy(dst, src, nx*elemsize);
  94. }
  95. /*
  96. * compute delta_new = trans(r) r
  97. * delta_0 = delta_new
  98. *
  99. * args = &delta_new, &delta_0
  100. */
  101. void cpu_codelet_func_3(void *descr[], void *arg)
  102. {
  103. struct cg_problem *pb = arg;
  104. float dot;
  105. float *vec;
  106. int size;
  107. /* get the vector */
  108. vec = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  109. size = (int)STARPU_VECTOR_GET_NX(descr[0]);
  110. dot = STARPU_SDOT(size, vec, 1, vec, 1);
  111. fprintf(stderr, "func 3 : DOT = %f\n", dot);
  112. pb->delta_new = dot;
  113. pb->delta_0 = dot;
  114. }
  115. #ifdef STARPU_USE_CUDA
  116. void cublas_codelet_func_3(void *descr[], void *arg)
  117. {
  118. struct cg_problem *pb = arg;
  119. float dot;
  120. float *vec;
  121. uint32_t size;
  122. /* get the vector */
  123. vec = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  124. size = STARPU_VECTOR_GET_NX(descr[0]);
  125. cublasStatus_t status = cublasSdot (starpu_cublas_get_local_handle(), size, vec, 1, vec, 1, &dot);
  126. if (status != CUBLAS_STATUS_SUCCESS)
  127. STARPU_CUBLAS_REPORT_ERROR(status);
  128. cudaStreamSynchronize(starpu_cuda_get_local_stream());
  129. pb->delta_new = dot;
  130. pb->delta_0 = dot;
  131. }
  132. #endif
  133. /*
  134. * compute q with : q = A d
  135. *
  136. * descr[0] = A, descr[1] = d, descr [2] = q
  137. */
  138. void cpu_codelet_func_4(void *descr[], void *arg)
  139. {
  140. (void)arg;
  141. float *nzval = (float *)STARPU_CSR_GET_NZVAL(descr[0]);
  142. uint32_t *colind = STARPU_CSR_GET_COLIND(descr[0]);
  143. uint32_t *rowptr = STARPU_CSR_GET_ROWPTR(descr[0]);
  144. uint32_t firstentry = STARPU_CSR_GET_FIRSTENTRY(descr[0]);
  145. float *vecd = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  146. float *vecq = (float *)STARPU_VECTOR_GET_PTR(descr[2]);
  147. uint32_t nrow;
  148. nrow = STARPU_CSR_GET_NROW(descr[0]);
  149. unsigned row;
  150. for (row = 0; row < nrow; row++)
  151. {
  152. float tmp = 0.0f;
  153. unsigned index;
  154. unsigned firstindex = rowptr[row] - firstentry;
  155. unsigned lastindex = rowptr[row+1] - firstentry;
  156. for (index = firstindex; index < lastindex; index++)
  157. {
  158. unsigned col;
  159. col = colind[index];
  160. tmp += nzval[index]*vecd[col];
  161. }
  162. vecq[row] = tmp;
  163. }
  164. }
  165. /*
  166. * compute alpha = delta_new / ( trans(d) q )
  167. *
  168. * descr[0] = d, descr[1] = q
  169. * args = &alpha, &delta_new
  170. */
  171. void cpu_codelet_func_5(void *descr[], void *arg)
  172. {
  173. float dot;
  174. struct cg_problem *pb = arg;
  175. float *vecd, *vecq;
  176. uint32_t size;
  177. /* get the vector */
  178. vecd = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  179. vecq = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  180. STARPU_ASSERT(STARPU_VECTOR_GET_NX(descr[0]) == STARPU_VECTOR_GET_NX(descr[1]));
  181. size = STARPU_VECTOR_GET_NX(descr[0]);
  182. dot = STARPU_SDOT(size, vecd, 1, vecq, 1);
  183. pb->alpha = pb->delta_new / dot;
  184. }
  185. #ifdef STARPU_USE_CUDA
  186. void cublas_codelet_func_5(void *descr[], void *arg)
  187. {
  188. float dot;
  189. struct cg_problem *pb = arg;
  190. float *vecd, *vecq;
  191. uint32_t size;
  192. /* get the vector */
  193. vecd = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  194. vecq = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  195. STARPU_ASSERT(STARPU_VECTOR_GET_NX(descr[0]) == STARPU_VECTOR_GET_NX(descr[1]));
  196. size = STARPU_VECTOR_GET_NX(descr[0]);
  197. cublasStatus_t status = cublasSdot (starpu_cublas_get_local_handle(), size, vecd, 1, vecq, 1, &dot);
  198. if (status != CUBLAS_STATUS_SUCCESS)
  199. STARPU_CUBLAS_REPORT_ERROR(status);
  200. cudaStreamSynchronize(starpu_cuda_get_local_stream());
  201. pb->alpha = pb->delta_new / dot;
  202. }
  203. #endif
  204. /*
  205. * compute x = x + alpha d
  206. *
  207. * descr[0] : x, descr[1] : d
  208. * args = &alpha
  209. */
  210. void cpu_codelet_func_6(void *descr[], void *arg)
  211. {
  212. struct cg_problem *pb = arg;
  213. float *vecx, *vecd;
  214. uint32_t size;
  215. /* get the vector */
  216. vecx = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  217. vecd = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  218. size = STARPU_VECTOR_GET_NX(descr[0]);
  219. STARPU_SAXPY(size, pb->alpha, vecd, 1, vecx, 1);
  220. }
  221. #ifdef STARPU_USE_CUDA
  222. void cublas_codelet_func_6(void *descr[], void *arg)
  223. {
  224. struct cg_problem *pb = arg;
  225. float *vecx, *vecd;
  226. uint32_t size;
  227. /* get the vector */
  228. vecx = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  229. vecd = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  230. size = STARPU_VECTOR_GET_NX(descr[0]);
  231. cublasStatus_t status = cublasSaxpy (starpu_cublas_get_local_handle(), size, &pb->alpha, vecd, 1, vecx, 1);
  232. if (status != CUBLAS_STATUS_SUCCESS)
  233. STARPU_CUBLAS_REPORT_ERROR(status);
  234. }
  235. #endif
  236. /*
  237. * compute r = r - alpha q
  238. *
  239. * descr[0] : r, descr[1] : q
  240. * args = &alpha
  241. */
  242. void cpu_codelet_func_7(void *descr[], void *arg)
  243. {
  244. struct cg_problem *pb = arg;
  245. float *vecr, *vecq;
  246. uint32_t size;
  247. /* get the vector */
  248. vecr = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  249. vecq = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  250. size = STARPU_VECTOR_GET_NX(descr[0]);
  251. STARPU_SAXPY(size, -pb->alpha, vecq, 1, vecr, 1);
  252. }
  253. #ifdef STARPU_USE_CUDA
  254. void cublas_codelet_func_7(void *descr[], void *arg)
  255. {
  256. struct cg_problem *pb = arg;
  257. float *vecr, *vecq;
  258. uint32_t size;
  259. /* get the vector */
  260. vecr = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  261. vecq = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  262. size = STARPU_VECTOR_GET_NX(descr[0]);
  263. float scal = -pb->alpha;
  264. cublasStatus_t status = cublasSaxpy (starpu_cublas_get_local_handle(), size, &scal, vecq, 1, vecr, 1);
  265. if (status != CUBLAS_STATUS_SUCCESS)
  266. STARPU_CUBLAS_REPORT_ERROR(status);
  267. }
  268. #endif
  269. /*
  270. * compute delta_old = delta_new
  271. * delta_new = trans(r) r
  272. * beta = delta_new / delta_old
  273. *
  274. * descr[0] = r
  275. * args = &delta_old, &delta_new, &beta
  276. */
  277. void cpu_codelet_func_8(void *descr[], void *arg)
  278. {
  279. float dot;
  280. struct cg_problem *pb = arg;
  281. float *vecr;
  282. uint32_t size;
  283. /* get the vector */
  284. vecr = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  285. size = STARPU_VECTOR_GET_NX(descr[0]);
  286. dot = STARPU_SDOT(size, vecr, 1, vecr, 1);
  287. pb->delta_old = pb->delta_new;
  288. pb->delta_new = dot;
  289. pb->beta = pb->delta_new/pb->delta_old;
  290. }
  291. #ifdef STARPU_USE_CUDA
  292. void cublas_codelet_func_8(void *descr[], void *arg)
  293. {
  294. float dot;
  295. struct cg_problem *pb = arg;
  296. float *vecr;
  297. uint32_t size;
  298. /* get the vector */
  299. vecr = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  300. size = STARPU_VECTOR_GET_NX(descr[0]);
  301. cublasStatus_t status = cublasSdot(starpu_cublas_get_local_handle(), size, vecr, 1, vecr, 1, &dot);
  302. if (status != CUBLAS_STATUS_SUCCESS) STARPU_CUBLAS_REPORT_ERROR(status);
  303. cudaStreamSynchronize(starpu_cuda_get_local_stream());
  304. pb->delta_old = pb->delta_new;
  305. pb->delta_new = dot;
  306. pb->beta = pb->delta_new/pb->delta_old;
  307. }
  308. #endif
  309. /*
  310. * compute d = r + beta d
  311. *
  312. * descr[0] : d, descr[1] : r
  313. * args = &beta
  314. *
  315. */
  316. void cpu_codelet_func_9(void *descr[], void *arg)
  317. {
  318. struct cg_problem *pb = arg;
  319. float *vecd, *vecr;
  320. uint32_t size;
  321. /* get the vector */
  322. vecd = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  323. vecr = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  324. size = STARPU_VECTOR_GET_NX(descr[0]);
  325. /* d = beta d */
  326. STARPU_SSCAL(size, pb->beta, vecd, 1);
  327. /* d = r + d */
  328. STARPU_SAXPY (size, 1.0f, vecr, 1, vecd, 1);
  329. }
  330. #ifdef STARPU_USE_CUDA
  331. void cublas_codelet_func_9(void *descr[], void *arg)
  332. {
  333. struct cg_problem *pb = arg;
  334. float *vecd, *vecr;
  335. uint32_t size;
  336. /* get the vector */
  337. vecd = (float *)STARPU_VECTOR_GET_PTR(descr[0]);
  338. vecr = (float *)STARPU_VECTOR_GET_PTR(descr[1]);
  339. size = STARPU_VECTOR_GET_NX(descr[0]);
  340. /* d = beta d */
  341. cublasStatus_t status;
  342. status = cublasSscal(starpu_cublas_get_local_handle(), size, &pb->beta, vecd, 1);
  343. if (status != CUBLAS_STATUS_SUCCESS)
  344. STARPU_CUBLAS_REPORT_ERROR(status);
  345. /* d = r + d */
  346. float scal = 1.0f;
  347. status = cublasSaxpy (starpu_cublas_get_local_handle(), size, &scal, vecr, 1, vecd, 1);
  348. if (status != CUBLAS_STATUS_SUCCESS)
  349. STARPU_CUBLAS_REPORT_ERROR(status);
  350. }
  351. #endif