starpu_task_wrapper.c 24 KB

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