replay_sched.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. /*SCHED.REC*/
  2. #include <starpu.h>
  3. #include <unistd.h>
  4. #include <stdio.h>
  5. #include <math.h>
  6. #include <common/uthash.h>
  7. #include <common/utils.h>
  8. #define CPY(src, dst, n) memcpy(dst, src, n * sizeof(*dst))
  9. static unsigned eosw;
  10. static unsigned priority;
  11. static unsigned workerorder;
  12. static unsigned workers[STARPU_NMAXWORKERS];
  13. static unsigned dependson[STARPU_NMAXBUFS];
  14. static unsigned nworkers;
  15. static unsigned nparam;
  16. static unsigned memnode;
  17. static unsigned ndependson;
  18. static unsigned submitorder; /* Also use as prefetchtag */
  19. static unsigned parameters[STARPU_NMAXBUFS];
  20. static unsigned add_to_hash = 0;
  21. static int sched_type = -1;
  22. /* sched_type is called s_type in the structure struct task
  23. - If s_type == -1, no task has been added to the structure
  24. - If s_type == 0, a false task has been added to the structure (at index 1)
  25. - If s_type == 1, scheduling info has been added into the non-false task (at index 0) of the structure
  26. - If s_type == 2, a false and a true task have been added into the structure
  27. */
  28. static struct starpu_codelet cl_prefetch = {
  29. .where = STARPU_NOWHERE,
  30. .nbuffers = 1,
  31. .modes = { STARPU_R },
  32. };
  33. static struct task
  34. {
  35. UT_hash_handle hh;
  36. unsigned submitorder;
  37. int pref_dep;
  38. unsigned send;
  39. /* "Prefetch dependence" is the submit order of the dependence for the prefetch, we've chosen to work with only one value, but it can be more (in this case rearrange the code
  40. and add eventually a new field in this structure named npref_dep or something like that) */
  41. struct starpu_task tasks[2]; /* It seems that we only need 2 slots, one for the scheduling info (stored in a task), and another for the false task */
  42. struct starpu_task pref_task;
  43. unsigned dependson[STARPU_NMAXBUFS];
  44. unsigned ndependson;
  45. unsigned parameters[STARPU_NMAXBUFS];
  46. unsigned nparameters;
  47. unsigned memory_node;
  48. unsigned s_type;
  49. } *sched_data;
  50. /* TODO : respecter l'ordre de soumission des tâches SubmitOrder */
  51. // TODO: call SchedRecInit
  52. void checkField(char * s)
  53. {
  54. if (!strncmp(s, "SubmitOrder: ", sizeof("SubmitOrder: ")))
  55. {
  56. s = s + sizeof("SubmitOrder: ");
  57. submitorder = strtol(s, NULL, 16);
  58. sched_type += 2;
  59. }
  60. else if (!strncmp(s, "Priority: ", sizeof("Prioriyty: ")))
  61. {
  62. s = s + sizeof("Priority: ");
  63. priority = strtol(s, NULL, 10);
  64. }
  65. else if (!strncmp(s, "ExecuteOnSpecificWorker: ", sizeof("ExecuteOnSpecificWorker: ")))
  66. {
  67. eosw = strtol(s, NULL, 10);
  68. }
  69. else if (!strncmp(s, "Workers: ", sizeof("Workers: ")))
  70. {
  71. s = s + sizeof("Workers: ");
  72. char * delim = " ";
  73. char * token = strtok(s, delim);
  74. int i = 0;
  75. while (token != NULL)
  76. {
  77. int k = strtol(token, NULL, 10);
  78. workers[k/sizeof(*workers)] |= (1 << (k%(sizeof(*workers))));
  79. i++;
  80. }
  81. nworkers = i;
  82. }
  83. else if (!strncmp(s, "DependsOn: ", sizeof("DependsOn: ")))
  84. {
  85. /* NOTE : dependsons (in the sched.rec) should be the submit orders of the dependences,
  86. otherwise it can occur an undefined behaviour
  87. (contrary to the tasks.rec where dependences are jobids */
  88. unsigned i = 0;
  89. char * delim = " ";
  90. char * token = strtok(s+sizeof("DependsOn: "), delim);
  91. while (token != NULL)
  92. {
  93. dependson[i] = strtol(token, NULL, 10);
  94. i++;
  95. }
  96. ndependson = i;
  97. }
  98. else if (!strncmp(s, "PrefetchTag: ", sizeof("PrefetchTag: ")))
  99. {
  100. s = s + sizeof("PrefecthTag: ");
  101. submitorder = strtol(s, NULL, 10);
  102. sched_type += 1;
  103. }
  104. else if (!strncmp(s, "Parameters: ", sizeof("Parameters: ")))
  105. {
  106. s = s + sizeof("Parameters: ");
  107. char * delim = " ";
  108. char * token = strtok(s, delim);
  109. int i = 0;
  110. while (token != NULL)
  111. {
  112. parameters[i] = strtol(token, NULL, 10);
  113. i++;
  114. }
  115. nparam = i;
  116. }
  117. else if (!strncmp(s, "MemoryNode: ", sizeof("MemoryNode: ")))
  118. {
  119. s = s + sizeof("MemoryNode: ");
  120. memnode = strtol(s, NULL, 10);
  121. }
  122. else if (!strncmp(s, "Workerorder: ", sizeof("Workerorder: ")))
  123. {
  124. s = s + sizeof("Workerorder: ");
  125. workerorder = strtol(s, NULL, 10);
  126. }
  127. }
  128. void recordSchedInfo(FILE * f)
  129. {
  130. size_t lnsize = 128;
  131. char * s = malloc(sizeof(*s) * lnsize);
  132. while(!feof(f))
  133. {
  134. fgets(s, lnsize, f); /* Get the line */
  135. while(!strcmp(s, "\n")) /* As long as the line is not only a newline symbol (emptyline) do {...} */
  136. {
  137. checkField(s);
  138. }
  139. struct task * task;
  140. HASH_FIND(hh, sched_data, &submitorder, sizeof(submitorder), task);
  141. if (sched_type == 1) /* Only 2 conditions are possible (== 1 or == 0) */
  142. {
  143. if (task == NULL)
  144. {
  145. _STARPU_MALLOC(task, sizeof(*task));
  146. task->s_type = sched_type;
  147. task->submitorder = submitorder;
  148. CPY(dependson, task->dependson, ndependson);
  149. task->ndependson = ndependson;
  150. task->pref_dep = -1;
  151. add_to_hash = 1;
  152. }
  153. else
  154. {
  155. task->s_type += sched_type;
  156. CPY(dependson, task->dependson, ndependson);
  157. task->ndependson = ndependson;
  158. task->pref_dep = -1;
  159. }
  160. starpu_task_init(&task->tasks[0]);
  161. task->tasks[0].workerorder = workerorder;
  162. task->tasks[0].priority = priority;
  163. task->tasks[0].workerids = workers;
  164. task->tasks[0].workerids_len = nworkers;
  165. unsigned i;
  166. for(i = 0; i < ndependson ; i++)
  167. {
  168. /* Create false task as dependences (they are added later) */
  169. struct task * taskdep;
  170. HASH_FIND(hh, sched_data, &dependson[i], sizeof(dependson[i]), taskdep);
  171. if (taskdep == NULL)
  172. {
  173. _STARPU_MALLOC(taskdep, sizeof(*taskdep));
  174. starpu_task_init(&taskdep->tasks[1]);
  175. taskdep->submitorder = dependson[i];
  176. taskdep->tasks[1].cl = NULL;
  177. taskdep->tasks[1].destroy = 0;
  178. taskdep->tasks[1]. no_submitorder = 1;
  179. HASH_ADD(hh, sched_data, submitorder, sizeof(submitorder), taskdep);
  180. }
  181. }
  182. if (add_to_ash)
  183. HASH_ADD(hh, sched_data, submitorder, sizeof(submitorder), task)
  184. }
  185. else
  186. {
  187. if (task == NULL)
  188. {
  189. _STARPU_MALLOC(task, sizeof(*task));
  190. task->s_type = sched_type;
  191. task->submitorder = submitorder;
  192. add_to_hash = 1;
  193. }
  194. else
  195. {
  196. task->s_type += shced_type;
  197. }
  198. task->pref_dep = dependson[0];
  199. struct task * deptask;
  200. HASH_FIND(hh, sched_data, &task->pref_dep, sizeof(task->pref_dep), deptask);
  201. if (deptask == NULL)
  202. {
  203. _STARPU_MALLOC(deptask, sizeof(*deptask));
  204. deptask->submitorder = task->pref_dep;
  205. }
  206. deptask->send = 1;
  207. deptask->nparameters = nparam;
  208. CPY(parameters, deptask->parameters, nparam);
  209. starpu_task_create(task->pref_task);
  210. deptask->pref_task.cl_prefetch;
  211. deptask->pref_task.no_submitorder = 1;
  212. deptask->pref_task.destroy = 1;
  213. HASH_ADD(hh, sched_data, task->pref_dep, sizeof(task->pref_dep), deptask);
  214. task->memory_node = memnode;
  215. if (add_to_ash)
  216. HASH_ADD(hh, sched_data, submitorder, sizeof(submitorder), task)
  217. }
  218. /* reset some values */
  219. sched_type = -1;
  220. add_to_hash = 0;
  221. }
  222. }
  223. void parsing(FILE * f)
  224. {
  225. recordSchedInfo(f);
  226. }
  227. void put_info(struct starpu_task * task, unsigned submit_order)
  228. {
  229. struct task * tmptask;
  230. HASH_FIND(hh, sched_data, &submit_order, sizeof(submitorder), tmptask);
  231. if (tmptask == NULL)
  232. return;
  233. if (tmptask->s_type == 2 || tmptask->s_type == 1)
  234. {
  235. task->workerorder = tmptask->tasks[0].workerorder;
  236. task->priority = tmptask->tasks[0].priority;
  237. task->workerids_len = tmptask->tasks[0].workerids_len;
  238. CPY(tmptask->tasks[0].workerids, task->workerids, task->workerids_len);
  239. struct starpu_task * deps[tmptask->ndependson];
  240. unsigned i;
  241. for(i = 0; i < tmptask->ndependson ; i++)
  242. {
  243. struct task * taskdep;
  244. HASH_FIND(hh, sched_data, &tmptask->dependson[i], sizeof(tmptask->dependson[i]), taskdep);
  245. if (taskdep == NULL)
  246. {
  247. fprintf(stderr, "Can not find the dependence of task(submitorder: %d) according the sched.rec\n", submit_order);
  248. exit(EXIT_FAILURE);
  249. }
  250. deps[i] = &taskdep->tasks[1];
  251. }
  252. /* According to the StarPU documentation, these dependences will be added
  253. to other existing dependences for this task */
  254. starpu_task_declare_deps_array(task, tmptask->ndependson, deps);
  255. }
  256. if (tmptask->s_type == 0 || tmptask->s_type == 2)
  257. {
  258. int ret = starpu_task_submit(&tmptask->tasks[1]);
  259. if (ret != 0)
  260. {
  261. fprintf(stderr, "Unable to submit a the false task (corresponding to a false task of the task with the submitorder: %d)", submit_order);
  262. }
  263. }
  264. if(tmptask->pref_dep != -1) /* If the task has a dependence for prefetch */
  265. {
  266. struct task * receive_data;
  267. HASH_FIND(sched_data, &submit_order, sizeof(submit_order), receive_data);
  268. /* TODO : mettre le handle de receive_data->task dans task.handles */
  269. }
  270. if (tmptask->send) /* If the task has stored data to be prefetched */
  271. {
  272. struct task * send_data;
  273. HASH_FIND(hh, sched_data, &submit_order, sizeof(submit_order), send_data);
  274. if(send_data == NULL)
  275. {
  276. fprintf(stderr, "Unable to send_data data for prefetch (submitorder: %d)", submit_order);
  277. exit(EXIT_FAILURE);
  278. }
  279. CPY(&task.handles, send_data->pref_task.handles[0], send_data)
  280. send_data->pref_task.handles[0] = task->handles[0];
  281. send_data->pref_task.callback_arg = &tmptask->memory_node;
  282. /* NOTE : Do it need a function in .callback_func ? */
  283. }
  284. }
  285. FILE * schedRecInit(const char * filename)
  286. {
  287. FILE * f = fopen(filename, "r");
  288. if(f == NULL)
  289. {
  290. return NULL;
  291. }
  292. parsing(f);
  293. return f;
  294. }
  295. void applySchedRec(struct starpu_task * task, unsigned submit_order)
  296. {
  297. put_info(task, submit_order);
  298. return;
  299. }