starpu_task_wrapper.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2020 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. #undef NDEBUG
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <starpu.h>
  21. #define PY_SSIZE_T_CLEAN
  22. #include <Python.h>
  23. #ifdef STARPU_PYTHON_HAVE_NUMPY
  24. #include <numpy/arrayobject.h>
  25. #endif
  26. /*macro*/
  27. #if defined(Py_DEBUG) || defined(DEBUG)
  28. extern void _Py_CountReferences(FILE*);
  29. #define CURIOUS(x) { fprintf(stderr, __FILE__ ":%d ", __LINE__); x; }
  30. #else
  31. #define CURIOUS(x)
  32. #endif
  33. #define MARKER() CURIOUS(fprintf(stderr, "\n"))
  34. #define DESCRIBE(x) CURIOUS(fprintf(stderr, " " #x "=%d\n", x))
  35. #define DESCRIBE_HEX(x) CURIOUS(fprintf(stderr, " " #x "=%08x\n", x))
  36. #define COUNTREFS() CURIOUS(_Py_CountReferences(stderr))
  37. /*******/
  38. /*********************Functions passed in task_submit wrapper***********************/
  39. static PyObject *asyncio_module; /*python asyncio module*/
  40. static PyObject *cloudpickle_module; /*cloudpickle module*/
  41. /*structure contains parameters which are passed to starpu_task.cl_arg*/
  42. // struct codelet_args
  43. // {
  44. // PyObject *f; /*the python function passed in*/
  45. // PyObject *argList; /*argument list of python function passed in*/
  46. // PyObject *rv; /*return value when using PyObject_CallObject call the function f*/
  47. // PyObject *fut; /*asyncio.Future*/
  48. // PyObject *lp; /*asyncio.Eventloop*/
  49. // };
  50. static char* starpu_cloudpickle_dumps(PyObject *obj, PyObject **obj_bytes, Py_ssize_t* obj_data_size)
  51. {
  52. PyObject *dumps = PyObject_GetAttrString(cloudpickle_module, "dumps");
  53. *obj_bytes= PyObject_CallFunctionObjArgs(dumps, obj, NULL);
  54. char* obj_data;
  55. PyBytes_AsStringAndSize(*obj_bytes, &obj_data, obj_data_size);
  56. return obj_data;
  57. }
  58. static PyObject* starpu_cloudpickle_loads(char* pyString, Py_ssize_t pyString_size)
  59. {
  60. PyObject *loads = PyObject_GetAttrString(cloudpickle_module, "loads");
  61. PyObject *obj_bytes_str = PyBytes_FromStringAndSize(pyString, pyString_size);
  62. PyObject *obj = PyObject_CallFunctionObjArgs(loads, obj_bytes_str, NULL);
  63. Py_DECREF(obj_bytes_str);
  64. return obj;
  65. }
  66. /* prologue_callback_func*/
  67. void prologue_cb_func(void * cl_arg)
  68. {
  69. PyObject *func_data;
  70. Py_ssize_t func_data_size;
  71. PyObject *argList;
  72. PyObject *fut;
  73. PyObject *loop;
  74. int sb;
  75. /*make sure we own the GIL*/
  76. PyGILState_STATE state = PyGILState_Ensure();
  77. struct starpu_task *task = starpu_task_get_current();
  78. /*Initialize struct starpu_codelet_unpack_arg_data*/
  79. struct starpu_codelet_pack_arg_data data_org;
  80. starpu_codelet_unpack_arg_init(&data_org, &task->cl_arg, &task->cl_arg_size);
  81. /*get func_data and func_data_size*/
  82. starpu_codelet_pick_arg(&data_org, &func_data, &func_data_size);
  83. /*get argList*/
  84. starpu_codelet_unpack_arg(&data_org, &argList, sizeof(argList));
  85. /*get fut*/
  86. starpu_codelet_unpack_arg(&data_org, &fut, sizeof(fut));
  87. /*get loop*/
  88. starpu_codelet_unpack_arg(&data_org, &loop, sizeof(loop));
  89. /*get sb*/
  90. starpu_codelet_unpack_arg(&data_org, &sb, sizeof(sb));
  91. /*Repack the data*/
  92. /*Initialize struct starpu_codelet_pack_arg_data*/
  93. struct starpu_codelet_pack_arg_data data;
  94. starpu_codelet_pack_arg_init(&data);
  95. /*repack func_data*/
  96. starpu_codelet_pack_arg(&data, func_data, func_data_size);
  97. /*check if there is Future in argList, if so, get the Future result*/
  98. int i;
  99. for(i=0; i < PyTuple_Size(argList); i++)
  100. {
  101. PyObject *obj=PyTuple_GetItem(argList, i);
  102. const char* tp = Py_TYPE(obj)->tp_name;
  103. if(strcmp(tp, "_asyncio.Future") == 0)
  104. {
  105. /*if one of arguments is Future, get its result*/
  106. PyObject *fut_result = PyObject_CallMethod(obj, "result", NULL);
  107. /*replace the Future argument to its result*/
  108. PyTuple_SetItem(argList, i, fut_result);
  109. }
  110. }
  111. /*use cloudpickle to dump dumps argList*/
  112. Py_ssize_t arg_data_size;
  113. PyObject* arg_bytes;
  114. char* arg_data = starpu_cloudpickle_dumps(argList, &arg_bytes, &arg_data_size);
  115. starpu_codelet_pack_arg(&data, arg_data, arg_data_size);
  116. Py_DECREF(arg_bytes);
  117. /*repack fut*/
  118. starpu_codelet_pack_arg(&data, &fut, sizeof(fut));
  119. /*repack loop*/
  120. starpu_codelet_pack_arg(&data, &loop, sizeof(loop));
  121. /*repack sb*/
  122. starpu_codelet_pack_arg(&data, &sb, sizeof(sb));
  123. /*finish repacking data and store the struct in cl_arg*/
  124. starpu_codelet_pack_arg_fini(&data, &task->cl_arg, &task->cl_arg_size);
  125. /*restore previous GIL state*/
  126. PyGILState_Release(state);
  127. }
  128. /*function passed to starpu_codelet.cpu_func*/
  129. void starpupy_codelet_func(void *buffers[], void *cl_arg)
  130. {
  131. char * func_data;
  132. Py_ssize_t func_data_size;
  133. PyObject *func_py; /*the python function passed in*/
  134. char * arg_data;
  135. Py_ssize_t arg_data_size;
  136. PyObject *argList; /*argument list of python function passed in*/
  137. //struct codelet_args *cst = (struct codelet_args*) cl_arg;
  138. struct starpu_task *task = starpu_task_get_current();
  139. /*Initialize struct starpu_codelet_unpack_arg_data*/
  140. struct starpu_codelet_pack_arg_data data;
  141. starpu_codelet_unpack_arg_init(&data, &task->cl_arg, &task->cl_arg_size);
  142. /*get func_py char*/
  143. // starpu_codelet_unpack_arg(&data, &func_data_size, sizeof(func_data_size));
  144. // func_data = (char *)malloc(func_data_size);
  145. // starpu_codelet_unpack_arg(&data, func_data, func_data_size);
  146. /*skip func_data_size*/
  147. //starpu_codelet_unpack_discard_arg(&data);
  148. /*get func_data*/
  149. starpu_codelet_pick_arg(&data, &func_data, &func_data_size);
  150. //starpu_codelet_unpack_arg(&data, &func_py, sizeof(func_py));
  151. /*get argList char*/
  152. // starpu_codelet_unpack_arg(&data, &arg_data_size, sizeof(arg_data_size));
  153. // arg_data = (char *)malloc(arg_data_size);
  154. // starpu_codelet_unpack_arg(&data, arg_data, arg_data_size);
  155. /*skip arg_data_size*/
  156. //starpu_codelet_unpack_discard_arg(&data);
  157. /*get arg_data*/
  158. starpu_codelet_pick_arg(&data, &arg_data, &arg_data_size);
  159. //starpu_codelet_unpack_arg(&data, &argList, sizeof(argList));
  160. /*skip fut*/
  161. starpu_codelet_unpack_discard_arg(&data);
  162. /*skip loop*/
  163. starpu_codelet_unpack_discard_arg(&data);
  164. /*skip sb*/
  165. starpu_codelet_unpack_discard_arg(&data);
  166. /*make sure we own the GIL*/
  167. PyGILState_STATE state = PyGILState_Ensure();
  168. /*use cloudpickle to load func_py and argList*/
  169. func_py=starpu_cloudpickle_loads(func_data, func_data_size);
  170. argList=starpu_cloudpickle_loads(arg_data, arg_data_size);
  171. /*verify that the function is a proper callable*/
  172. if (!PyCallable_Check(func_py))
  173. {
  174. printf("py_callback: expected a callable function\n");
  175. exit(1);
  176. }
  177. /*call the python function get the return value rv*/
  178. //PyObject *pRetVal = PyObject_CallObject(cst->f, cst->argList);
  179. //cst->rv = pRetVal;
  180. PyObject *rv = PyObject_CallObject(func_py, argList);
  181. /*if the result is None type, pack NULL without using cloudpickle*/
  182. if (rv==Py_None)
  183. {
  184. char* rv_data=NULL;
  185. Py_ssize_t rv_data_size=0;
  186. starpu_codelet_pack_arg(&data, &rv_data_size, sizeof(rv_data_size));
  187. starpu_codelet_pack_arg(&data, &rv_data, sizeof(rv_data));
  188. }
  189. /*else use cloudpickle to dump rv*/
  190. else
  191. {
  192. Py_ssize_t rv_data_size;
  193. PyObject *rv_bytes;
  194. char* rv_data = starpu_cloudpickle_dumps(rv, &rv_bytes, &rv_data_size);
  195. starpu_codelet_pack_arg(&data, &rv_data_size, sizeof(rv_data_size));
  196. starpu_codelet_pack_arg(&data, rv_data, rv_data_size);
  197. Py_DECREF(rv_bytes);
  198. }
  199. //starpu_codelet_pack_arg(&data, &rv, sizeof(rv));
  200. starpu_codelet_pack_arg_fini(&data, &task->cl_arg, &task->cl_arg_size);
  201. //Py_DECREF(cst->f);
  202. Py_DECREF(func_py);
  203. Py_DECREF(argList);
  204. /*restore previous GIL state*/
  205. PyGILState_Release(state);
  206. }
  207. /*function passed to starpu_task.callback_func*/
  208. void cb_func(void *v)
  209. {
  210. PyObject *fut; /*asyncio.Future*/
  211. PyObject *loop; /*asyncio.Eventloop*/
  212. char * rv_data;
  213. Py_ssize_t rv_data_size;
  214. PyObject *rv; /*return value when using PyObject_CallObject call the function f*/
  215. struct starpu_task *task = starpu_task_get_current();
  216. //struct codelet_args *cst = (struct codelet_args*) task->cl_arg;
  217. /*Initialize struct starpu_codelet_unpack_arg_data*/
  218. struct starpu_codelet_pack_arg_data data;
  219. starpu_codelet_unpack_arg_init(&data, &task->cl_arg, &task->cl_arg_size);
  220. /*skip func_py*/
  221. //starpu_codelet_unpack_discard_arg(&data);
  222. starpu_codelet_unpack_discard_arg(&data);
  223. /*skip argList*/
  224. //starpu_codelet_unpack_discard_arg(&data);
  225. starpu_codelet_unpack_discard_arg(&data);
  226. /*get fut*/
  227. starpu_codelet_unpack_arg(&data, &fut, sizeof(fut));
  228. /*get loop*/
  229. starpu_codelet_unpack_arg(&data, &loop, sizeof(loop));
  230. /*skip sb*/
  231. starpu_codelet_unpack_discard_arg(&data);
  232. /*get rv_data_size*/
  233. starpu_codelet_unpack_arg(&data, &rv_data_size, sizeof(rv_data_size));
  234. //starpu_codelet_pick_arg(&data, &rv_data, &rv_data_size);
  235. //starpu_codelet_unpack_arg(&data, &rv, sizeof(rv));
  236. /*make sure we own the GIL*/
  237. PyGILState_STATE state = PyGILState_Ensure();
  238. /*if the rv_data_size is 0, the result is None type*/
  239. if (rv_data_size==0)
  240. {
  241. rv=Py_None;
  242. }
  243. /*else use cloudpickle to load rv*/
  244. else
  245. {
  246. // rv_data = (char *)malloc(rv_data_size);
  247. // starpu_codelet_unpack_arg(&data, rv_data, rv_data_size);
  248. starpu_codelet_pick_arg(&data, &rv_data, &rv_data_size);
  249. rv=starpu_cloudpickle_loads(rv_data, rv_data_size);
  250. }
  251. /*set the Future result and mark the Future as done*/
  252. PyObject *set_result = PyObject_GetAttrString(fut, "set_result");
  253. PyObject *loop_callback = PyObject_CallMethod(loop, "call_soon_threadsafe", "(O,O)", set_result, rv);
  254. Py_DECREF(loop_callback);
  255. Py_DECREF(set_result);
  256. Py_DECREF(rv);
  257. Py_DECREF(fut);
  258. Py_DECREF(loop);
  259. //Py_DECREF(argList);
  260. //Py_DECREF(perfmodel);
  261. struct starpu_codelet *func_cl=(struct starpu_codelet *) task->cl;
  262. if (func_cl->model != NULL)
  263. {
  264. struct starpu_perfmodel *perf =(struct starpu_perfmodel *) func_cl->model;
  265. PyObject *perfmodel=PyCapsule_New(perf, "Perf", 0);
  266. Py_DECREF(perfmodel);
  267. }
  268. /*restore previous GIL state*/
  269. PyGILState_Release(state);
  270. /*deallocate task*/
  271. free(task->cl);
  272. free(task->cl_arg);
  273. }
  274. /***********************************************************************************/
  275. /*PyObject*->struct starpu_task**/
  276. static struct starpu_task *PyTask_AsTask(PyObject *obj)
  277. {
  278. return (struct starpu_task *) PyCapsule_GetPointer(obj, "Task");
  279. }
  280. /* destructor function for task */
  281. static void del_Task(PyObject *obj)
  282. {
  283. struct starpu_task *obj_task=PyTask_AsTask(obj);
  284. obj_task->destroy=1; /*XXX we should call starpu task destroy*/
  285. }
  286. /*struct starpu_task*->PyObject**/
  287. static PyObject *PyTask_FromTask(struct starpu_task *task)
  288. {
  289. return PyCapsule_New(task, "Task", del_Task);
  290. }
  291. /***********************************************************************************/
  292. static size_t sizebase (struct starpu_task *task, unsigned nimpl)
  293. {
  294. int sb;
  295. //struct codelet_args *cst = (struct codelet_args*) task->cl_arg;
  296. /*Initialize struct starpu_codelet_unpack_arg_data*/
  297. struct starpu_codelet_pack_arg_data data;
  298. starpu_codelet_unpack_arg_init(&data, &task->cl_arg, &task->cl_arg_size);
  299. /*skip func_py*/
  300. //starpu_codelet_unpack_discard_arg(&data);
  301. starpu_codelet_unpack_discard_arg(&data);
  302. /*skip argList*/
  303. //starpu_codelet_unpack_discard_arg(&data);
  304. starpu_codelet_unpack_discard_arg(&data);
  305. /*skip fut*/
  306. starpu_codelet_unpack_discard_arg(&data);
  307. /*skip loop*/
  308. starpu_codelet_unpack_discard_arg(&data);
  309. /*get sb*/
  310. starpu_codelet_unpack_arg(&data, &sb, sizeof(sb));
  311. /*skip rv*/
  312. starpu_codelet_unpack_discard_arg(&data);
  313. starpu_codelet_unpack_discard_arg(&data);
  314. //starpu_codelet_unpack_args(task_submit->cl_arg, &func_py, &argList, &fut, &loop, &sb, &rv);
  315. return sb;
  316. }
  317. static void del_Perf(PyObject *obj)
  318. {
  319. struct starpu_perfmodel *perf=(struct starpu_perfmodel*)PyCapsule_GetPointer(obj, "Perf");
  320. free(perf);
  321. }
  322. /*initialization of perfmodel*/
  323. static PyObject* init_perfmodel(PyObject *self, PyObject *args)
  324. {
  325. char *sym;
  326. if (!PyArg_ParseTuple(args, "s", &sym))
  327. return NULL;
  328. /*allocate a perfmodel structure*/
  329. struct starpu_perfmodel *perf=(struct starpu_perfmodel*)calloc(1, sizeof(struct starpu_perfmodel));
  330. /*get the perfmodel symbol*/
  331. char *p =strdup(sym);
  332. perf->symbol=p;
  333. perf->type=STARPU_HISTORY_BASED;
  334. /*struct perfmodel*->PyObject**/
  335. PyObject *perfmodel=PyCapsule_New(perf, "Perf", NULL);
  336. return perfmodel;
  337. }
  338. /*free perfmodel*/
  339. static PyObject* free_perfmodel(PyObject *self, PyObject *args)
  340. {
  341. PyObject *perfmodel;
  342. if (!PyArg_ParseTuple(args, "O", &perfmodel))
  343. return NULL;
  344. /*PyObject*->struct perfmodel**/
  345. struct starpu_perfmodel *perf=PyCapsule_GetPointer(perfmodel, "Perf");
  346. starpu_save_history_based_model(perf);
  347. //starpu_perfmodel_unload_model(perf);
  348. //free(perf->symbol);
  349. starpu_perfmodel_deinit(perf);
  350. free(perf);
  351. /*return type is void*/
  352. Py_INCREF(Py_None);
  353. return Py_None;
  354. }
  355. static PyObject* starpu_save_history_based_model_wrapper(PyObject *self, PyObject *args)
  356. {
  357. PyObject *perfmodel;
  358. if (!PyArg_ParseTuple(args, "O", &perfmodel))
  359. return NULL;
  360. /*PyObject*->struct perfmodel**/
  361. struct starpu_perfmodel *perf=PyCapsule_GetPointer(perfmodel, "Perf");
  362. starpu_save_history_based_model(perf);
  363. /*return type is void*/
  364. Py_INCREF(Py_None);
  365. return Py_None;
  366. }
  367. /*****************************Wrappers of StarPU methods****************************/
  368. /*wrapper submit method*/
  369. static PyObject* starpu_task_submit_wrapper(PyObject *self, PyObject *args)
  370. {
  371. /*get the running Event loop*/
  372. PyObject *loop = PyObject_CallMethod(asyncio_module, "get_running_loop", NULL);
  373. /*create a asyncio.Future object*/
  374. PyObject *fut = PyObject_CallMethod(loop, "create_future", NULL);
  375. /*first argument in args is always the python function passed in*/
  376. PyObject *func_py = PyTuple_GetItem(args, 0);
  377. Py_INCREF(fut);
  378. Py_INCREF(loop);
  379. Py_INCREF(func_py);
  380. /*allocate a task structure and initialize it with default values*/
  381. struct starpu_task *task=starpu_task_create();
  382. task->destroy=0;
  383. PyObject *PyTask=PyTask_FromTask(task);
  384. /*set one of fut attribute to the task pointer*/
  385. PyObject_SetAttrString(fut, "starpu_task", PyTask);
  386. /*check the arguments of python function passed in*/
  387. int i;
  388. for(i=1; i < PyTuple_Size(args)-1; i++)
  389. {
  390. PyObject *obj=PyTuple_GetItem(args, i);
  391. const char* tp = Py_TYPE(obj)->tp_name;
  392. if(strcmp(tp, "_asyncio.Future") == 0)
  393. {
  394. /*if one of arguments is Future, get its corresponding task*/
  395. PyObject *fut_task=PyObject_GetAttrString(obj, "starpu_task");
  396. /*declare task dependencies between the current task and the corresponding task of Future argument*/
  397. starpu_task_declare_deps(task, 1, PyTask_AsTask(fut_task));
  398. Py_DECREF(fut_task);
  399. }
  400. }
  401. /*allocate a codelet structure*/
  402. struct starpu_codelet *func_cl=(struct starpu_codelet*)malloc(sizeof(struct starpu_codelet));
  403. /*initialize func_cl with default values*/
  404. starpu_codelet_init(func_cl);
  405. func_cl->cpu_funcs[0]=&starpupy_codelet_func;
  406. func_cl->cpu_funcs_name[0]="starpupy_codelet_func";
  407. /*check whether the option perfmodel is None*/
  408. PyObject *dict_option = PyTuple_GetItem(args, PyTuple_Size(args)-1);/*the last argument is the option dictionary*/
  409. PyObject *perfmodel = PyDict_GetItemString(dict_option, "perfmodel");
  410. const char *tp_perf = Py_TYPE(perfmodel)->tp_name;
  411. if (strcmp(tp_perf, "PyCapsule")==0)
  412. {
  413. /*PyObject*->struct perfmodel**/
  414. struct starpu_perfmodel *perf=PyCapsule_GetPointer(perfmodel, "Perf");
  415. func_cl->model=perf;
  416. Py_INCREF(perfmodel);
  417. }
  418. /*allocate a new codelet structure to pass the python function, asyncio.Future and Event loop*/
  419. //struct codelet_args *cst = (struct codelet_args*)malloc(sizeof(struct codelet_args));
  420. //cst->f = func_py;
  421. //cst->fut = fut;
  422. //cst->lp = loop;
  423. /*Initialize struct starpu_codelet_pack_arg_data*/
  424. struct starpu_codelet_pack_arg_data data;
  425. starpu_codelet_pack_arg_init(&data);
  426. /*argument list of python function passed in*/
  427. PyObject *argList;
  428. /*pass args in argList*/
  429. if (PyTuple_Size(args)==2)/*function no arguments*/
  430. argList = PyTuple_New(0);
  431. else
  432. {/*function has arguments*/
  433. argList = PyTuple_New(PyTuple_Size(args)-2);
  434. int i;
  435. for(i=0; i < PyTuple_Size(args)-2; i++)
  436. {
  437. PyObject *tmp=PyTuple_GetItem(args, i+1);
  438. PyTuple_SetItem(argList, i, tmp);
  439. Py_INCREF(PyTuple_GetItem(argList, i));
  440. }
  441. }
  442. /*use cloudpickle to dump func_py*/
  443. Py_ssize_t func_data_size;
  444. PyObject* func_bytes;
  445. char* func_data = starpu_cloudpickle_dumps(func_py, &func_bytes, &func_data_size);
  446. starpu_codelet_pack_arg(&data, func_data, func_data_size);
  447. Py_DECREF(func_bytes);
  448. //starpu_codelet_pack_arg(&data, &func_py, sizeof(func_py));
  449. /*pack argList*/
  450. starpu_codelet_pack_arg(&data, &argList, sizeof(argList));
  451. /*pack fut*/
  452. starpu_codelet_pack_arg(&data, &fut, sizeof(fut));
  453. /*pack loop*/
  454. starpu_codelet_pack_arg(&data, &loop, sizeof(loop));
  455. task->cl=func_cl;
  456. //task->cl_arg=cst;
  457. /*pass optional values name=None, synchronous=1, priority=0, color=None, flops=None, perfmodel=None, sizebase=0*/
  458. /*const char * name*/
  459. PyObject *PyName = PyDict_GetItemString(dict_option, "name");
  460. if (PyName!=Py_None)
  461. {
  462. char* name_str = PyUnicode_AsUTF8(PyName);
  463. char* name = strdup(name_str);
  464. //printf("name is %s\n", name);
  465. task->name=name;
  466. }
  467. /*unsigned synchronous:1*/
  468. PyObject *PySync = PyDict_GetItemString(dict_option, "synchronous");
  469. unsigned sync=PyLong_AsUnsignedLong(PySync);
  470. //printf("sync is %u\n", sync);
  471. task->synchronous=sync;
  472. /*int priority*/
  473. PyObject *PyPrio = PyDict_GetItemString(dict_option, "priority");
  474. int prio=PyLong_AsLong(PyPrio);
  475. //printf("prio is %d\n", prio);
  476. task->priority=prio;
  477. /*unsigned color*/
  478. PyObject *PyColor = PyDict_GetItemString(dict_option, "color");
  479. if (PyColor!=Py_None)
  480. {
  481. unsigned color=PyLong_AsUnsignedLong(PyColor);
  482. //printf("color is %u\n", color);
  483. task->color=color;
  484. }
  485. /*double flops*/
  486. PyObject *PyFlops = PyDict_GetItemString(dict_option, "flops");
  487. if (PyFlops!=Py_None)
  488. {
  489. double flops=PyFloat_AsDouble(PyFlops);
  490. //printf("flops is %f\n", flops);
  491. task->flops=flops;
  492. }
  493. /*int sizebase*/
  494. PyObject *PySB = PyDict_GetItemString(dict_option, "sizebase");
  495. int sb=PyLong_AsLong(PySB);
  496. //printf("pack sizebase is %d\n", sb);
  497. /*pack sb*/
  498. starpu_codelet_pack_arg(&data, &sb, sizeof(sb));
  499. /*finish packing data and store the struct in cl_arg*/
  500. starpu_codelet_pack_arg_fini(&data, &task->cl_arg, &task->cl_arg_size);
  501. task->prologue_callback_func=&prologue_cb_func;
  502. task->callback_func=&cb_func;
  503. /*call starpu_task_submit method*/
  504. Py_BEGIN_ALLOW_THREADS
  505. int ret = starpu_task_submit(task);
  506. assert(ret==0);
  507. Py_END_ALLOW_THREADS
  508. if (strcmp(tp_perf, "PyCapsule")==0)
  509. {
  510. struct starpu_perfmodel *perf =(struct starpu_perfmodel *) func_cl->model;
  511. perf->size_base=&sizebase;
  512. }
  513. //printf("the number of reference is %ld\n", Py_REFCNT(func_py));
  514. //_Py_PrintReferences(stderr);
  515. //COUNTREFS();
  516. return fut;
  517. }
  518. /*wrapper wait for all method*/
  519. static PyObject* starpu_task_wait_for_all_wrapper(PyObject *self, PyObject *args)
  520. {
  521. /*call starpu_task_wait_for_all method*/
  522. Py_BEGIN_ALLOW_THREADS
  523. starpu_task_wait_for_all();
  524. Py_END_ALLOW_THREADS
  525. /*return type is void*/
  526. Py_INCREF(Py_None);
  527. return Py_None;
  528. }
  529. /*wrapper pause method*/
  530. static PyObject* starpu_pause_wrapper(PyObject *self, PyObject *args)
  531. {
  532. /*call starpu_pause method*/
  533. starpu_pause();
  534. /*return type is void*/
  535. Py_INCREF(Py_None);
  536. return Py_None;
  537. }
  538. /*wrapper resume method*/
  539. static PyObject* starpu_resume_wrapper(PyObject *self, PyObject *args)
  540. {
  541. /*call starpu_resume method*/
  542. starpu_resume();
  543. /*return type is void*/
  544. Py_INCREF(Py_None);
  545. return Py_None;
  546. }
  547. /*wrapper get count cpu method*/
  548. static PyObject* starpu_cpu_worker_get_count_wrapper(PyObject *self, PyObject *args)
  549. {
  550. /*call starpu_cpu_worker_get_count method*/
  551. int num_cpu=starpu_cpu_worker_get_count();
  552. /*return type is unsigned*/
  553. return Py_BuildValue("I", num_cpu);
  554. }
  555. /*wrapper get min priority method*/
  556. static PyObject* starpu_sched_get_min_priority_wrapper(PyObject *self, PyObject *args)
  557. {
  558. /*call starpu_sched_get_min_priority*/
  559. int min_prio=starpu_sched_get_min_priority();
  560. /*return type is int*/
  561. return Py_BuildValue("i", min_prio);
  562. }
  563. /*wrapper get max priority method*/
  564. static PyObject* starpu_sched_get_max_priority_wrapper(PyObject *self, PyObject *args)
  565. {
  566. /*call starpu_sched_get_max_priority*/
  567. int max_prio=starpu_sched_get_max_priority();
  568. /*return type is int*/
  569. return Py_BuildValue("i", max_prio);
  570. }
  571. /*wrapper get the number of no completed submitted tasks method*/
  572. static PyObject* starpu_task_nsubmitted_wrapper(PyObject *self, PyObject *args)
  573. {
  574. /*call starpu_task_nsubmitted*/
  575. int num_task=starpu_task_nsubmitted();
  576. /*Return the number of submitted tasks which have not completed yet */
  577. return Py_BuildValue("i", num_task);
  578. }
  579. /***********************************************************************************/
  580. /***************The module’s method table and initialization function**************/
  581. /*method table*/
  582. static PyMethodDef starpupyMethods[] =
  583. {
  584. {"_task_submit", starpu_task_submit_wrapper, METH_VARARGS, "submit the task"}, /*submit method*/
  585. {"task_wait_for_all", starpu_task_wait_for_all_wrapper, METH_VARARGS, "wait the task"}, /*wait for all method*/
  586. {"pause", starpu_pause_wrapper, METH_VARARGS, "suspend the processing of new tasks by workers"}, /*pause method*/
  587. {"resume", starpu_resume_wrapper, METH_VARARGS, "resume the workers polling for new tasks"}, /*resume method*/
  588. {"cpu_worker_get_count", starpu_cpu_worker_get_count_wrapper, METH_VARARGS, "return the number of CPUs controlled by StarPU"}, /*get count cpu method*/
  589. {"init_perfmodel", init_perfmodel, METH_VARARGS, "initialize struct starpu_perfmodel"}, /*initialize perfmodel*/
  590. {"free_perfmodel", free_perfmodel, METH_VARARGS, "free struct starpu_perfmodel"}, /*free perfmodel*/
  591. {"save_history_based_model", starpu_save_history_based_model_wrapper, METH_VARARGS, "save the performance model"}, /*save the performance model*/
  592. {"sched_get_min_priority", starpu_sched_get_min_priority_wrapper, METH_VARARGS, "get the number of min priority"}, /*get the number of min priority*/
  593. {"sched_get_max_priority", starpu_sched_get_max_priority_wrapper, METH_VARARGS, "get the number of max priority"}, /*get the number of max priority*/
  594. {"task_nsubmitted", starpu_task_nsubmitted_wrapper, METH_VARARGS, "get the number of submitted tasks which have not completed yet"}, /*get the number of submitted tasks which have not completed yet*/
  595. {NULL, NULL}
  596. };
  597. /*deallocation function*/
  598. static void starpupyFree(void *self)
  599. {
  600. starpu_shutdown();
  601. Py_DECREF(asyncio_module);
  602. //COUNTREFS();
  603. }
  604. /*module definition structure*/
  605. static struct PyModuleDef starpupymodule =
  606. {
  607. PyModuleDef_HEAD_INIT,
  608. "starpupy", /*name of module*/
  609. NULL,
  610. -1,
  611. starpupyMethods, /*method table*/
  612. NULL,
  613. NULL,
  614. NULL,
  615. starpupyFree /*deallocation function*/
  616. };
  617. /*initialization function*/
  618. PyMODINIT_FUNC
  619. PyInit_starpupy(void)
  620. {
  621. PyEval_InitThreads();
  622. /*starpu initialization*/
  623. int ret = starpu_init(NULL);
  624. assert(ret==0);
  625. /*python asysncio import*/
  626. asyncio_module = PyImport_ImportModule("asyncio");
  627. /*cloudpickle import*/
  628. cloudpickle_module = PyImport_ImportModule("cloudpickle");
  629. #ifdef STARPU_PYTHON_HAVE_NUMPY
  630. /*numpy import array*/
  631. import_array();
  632. #endif
  633. /*module import initialization*/
  634. return PyModule_Create(&starpupymodule);
  635. }
  636. /***********************************************************************************/