component_sched.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2013, 2017 INRIA
  4. * Copyright (C) 2013 Simon Archipoff
  5. * Copyright (C) 2016 CNRS
  6. *
  7. * StarPU is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as published by
  9. * the Free Software Foundation; either version 2.1 of the License, or (at
  10. * your option) any later version.
  11. *
  12. * StarPU is distributed in the hope that it will be useful, but
  13. * WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. *
  16. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  17. */
  18. #include <core/jobs.h>
  19. #include <core/workers.h>
  20. #include <starpu_sched_component.h>
  21. #include <starpu_thread_util.h>
  22. #include <float.h>
  23. #include "sched_component.h"
  24. /******************************************************************************
  25. * Generic Scheduling Components' helper functions *
  26. ******************************************************************************/
  27. /* this function find the best implementation or an implementation that need to be calibrated for a worker available
  28. * and set prediction in *length. nan if a implementation need to be calibrated, 0.0 if no perf model are available
  29. * return false if no worker on the component can execute that task
  30. */
  31. int starpu_sched_component_execute_preds(struct starpu_sched_component * component, struct starpu_task * task, double * length)
  32. {
  33. STARPU_ASSERT(component && task);
  34. int can_execute = 0;
  35. starpu_task_bundle_t bundle = task->bundle;
  36. double len = DBL_MAX;
  37. int workerid;
  38. for(workerid = starpu_bitmap_first(component->workers_in_ctx);
  39. workerid != -1;
  40. workerid = starpu_bitmap_next(component->workers_in_ctx, workerid))
  41. {
  42. struct starpu_perfmodel_arch* archtype = starpu_worker_get_perf_archtype(workerid, component->tree->sched_ctx_id);
  43. int nimpl;
  44. for(nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
  45. {
  46. if(starpu_worker_can_execute_task(workerid,task,nimpl)
  47. || starpu_combined_worker_can_execute_task(workerid, task, nimpl))
  48. {
  49. double d;
  50. can_execute = 1;
  51. if(bundle)
  52. d = starpu_task_bundle_expected_length(bundle, archtype, nimpl);
  53. else
  54. d = starpu_task_expected_length(task, archtype, nimpl);
  55. if(isnan(d))
  56. {
  57. *length = d;
  58. return can_execute;
  59. }
  60. if(_STARPU_IS_ZERO(d))
  61. {
  62. continue;
  63. }
  64. STARPU_ASSERT_MSG(d >= 0, "workerid=%d, nimpl=%d, bundle=%p, d=%lf\n", workerid, nimpl, bundle, d);
  65. if(d < len)
  66. {
  67. len = d;
  68. }
  69. }
  70. }
  71. if(STARPU_SCHED_COMPONENT_IS_HOMOGENEOUS(component))
  72. break;
  73. }
  74. if(len == DBL_MAX) /* we dont have perf model */
  75. len = 0.0;
  76. if(length)
  77. *length = len;
  78. return can_execute;
  79. }
  80. /* very similar function that dont compute prediction */
  81. int starpu_sched_component_can_execute_task(struct starpu_sched_component * component, struct starpu_task * task)
  82. {
  83. STARPU_ASSERT(task);
  84. STARPU_ASSERT(component);
  85. unsigned nimpl;
  86. int worker;
  87. for (nimpl = 0; nimpl < STARPU_MAXIMPLEMENTATIONS; nimpl++)
  88. for(worker = starpu_bitmap_first(component->workers_in_ctx);
  89. -1 != worker;
  90. worker = starpu_bitmap_next(component->workers_in_ctx, worker))
  91. if (starpu_worker_can_execute_task(worker, task, nimpl)
  92. || starpu_combined_worker_can_execute_task(worker, task, nimpl))
  93. return 1;
  94. return 0;
  95. }
  96. /* compute the average of transfer length for tasks on all workers
  97. * maybe this should be optimised if all workers are under the same numa component
  98. */
  99. double starpu_sched_component_transfer_length(struct starpu_sched_component * component, struct starpu_task * task)
  100. {
  101. STARPU_ASSERT(component && task);
  102. int nworkers = starpu_bitmap_cardinal(component->workers_in_ctx);
  103. double sum = 0.0;
  104. int worker;
  105. if(STARPU_SCHED_COMPONENT_IS_SINGLE_MEMORY_NODE(component))
  106. {
  107. unsigned memory_node = starpu_worker_get_memory_node(starpu_bitmap_first(component->workers_in_ctx));
  108. if(task->bundle)
  109. return starpu_task_bundle_expected_data_transfer_time(task->bundle,memory_node);
  110. else
  111. return starpu_task_expected_data_transfer_time(memory_node, task);
  112. }
  113. for(worker = starpu_bitmap_first(component->workers_in_ctx);
  114. worker != -1;
  115. worker = starpu_bitmap_next(component->workers_in_ctx, worker))
  116. {
  117. unsigned memory_node = starpu_worker_get_memory_node(worker);
  118. if(task->bundle)
  119. {
  120. sum += starpu_task_bundle_expected_data_transfer_time(task->bundle,memory_node);
  121. }
  122. else
  123. {
  124. sum += starpu_task_expected_data_transfer_time(memory_node, task);
  125. /* sum += starpu_task_expected_conversion_time(task, starpu_worker_get_perf_archtype(worker, component->tree->sched_ctx_id), impl ?)
  126. * I dont know what to do as we dont know what implementation would be used here...
  127. */
  128. }
  129. }
  130. return sum / nworkers;
  131. }
  132. /* This function can be called by components when they think that a prefetching request can be submitted.
  133. * For example, it is currently used by the MCT component to begin the prefetching on accelerators
  134. * on which it pushed tasks as soon as possible.
  135. */
  136. void starpu_sched_component_prefetch_on_node(struct starpu_sched_component * component, struct starpu_task * task)
  137. {
  138. if (starpu_get_prefetch_flag() && (!task->prefetched)
  139. && (component->properties >= STARPU_SCHED_COMPONENT_SINGLE_MEMORY_NODE))
  140. {
  141. int worker = starpu_bitmap_first(component->workers_in_ctx);
  142. unsigned memory_node = starpu_worker_get_memory_node(worker);
  143. starpu_prefetch_task_input_on_node(task, memory_node);
  144. task->prefetched = 1;
  145. }
  146. }
  147. /* remove all child
  148. * for all child of component, if child->parents[x] == component, set child->parents[x] to null
  149. * call component->deinit_data
  150. */
  151. void starpu_sched_component_destroy(struct starpu_sched_component *component)
  152. {
  153. STARPU_ASSERT(component);
  154. unsigned i,j;
  155. for(i = 0; i < component->nchildren; i++)
  156. {
  157. struct starpu_sched_component * child = component->children[i];
  158. for(j = 0; j < child->nparents; j++)
  159. if(child->parents[j] == component)
  160. child->remove_parent(child,component);
  161. }
  162. while(component->nchildren != 0)
  163. component->remove_child(component, component->children[0]);
  164. for(i = 0; i < component->nparents; i++)
  165. {
  166. struct starpu_sched_component * parent = component->parents[i];
  167. for(j = 0; j < parent->nchildren; j++)
  168. if(parent->children[j] == component)
  169. parent->remove_child(parent,component);
  170. }
  171. while(component->nparents != 0)
  172. component->remove_parent(component, component->parents[0]);
  173. component->deinit_data(component);
  174. free(component->children);
  175. free(component->parents);
  176. free(component->name);
  177. starpu_bitmap_destroy(component->workers);
  178. starpu_bitmap_destroy(component->workers_in_ctx);
  179. free(component);
  180. }
  181. void starpu_sched_component_destroy_rec(struct starpu_sched_component * component)
  182. {
  183. if(component == NULL)
  184. return;
  185. unsigned i = 0;
  186. while(i < component->nchildren)
  187. {
  188. if (starpu_sched_component_is_worker(component->children[i]))
  189. i++;
  190. else
  191. starpu_sched_component_destroy_rec(component->children[i]);
  192. }
  193. if (!starpu_sched_component_is_worker(component))
  194. starpu_sched_component_destroy(component);
  195. }
  196. void set_properties(struct starpu_sched_component * component)
  197. {
  198. STARPU_ASSERT(component);
  199. component->properties = 0;
  200. int worker = starpu_bitmap_first(component->workers_in_ctx);
  201. if (worker == -1)
  202. return;
  203. #ifdef STARPU_DEVEL
  204. #warning FIXME: Not all CUDA devices have the same speed
  205. #endif
  206. uint32_t first_worker = _starpu_get_worker_struct(worker)->worker_mask;
  207. unsigned first_memory_node = _starpu_get_worker_struct(worker)->memory_node;
  208. int is_homogeneous = 1;
  209. int is_all_same_component = 1;
  210. for(;
  211. worker != -1;
  212. worker = starpu_bitmap_next(component->workers_in_ctx, worker))
  213. {
  214. if(first_worker != _starpu_get_worker_struct(worker)->worker_mask)
  215. is_homogeneous = 0;
  216. if(first_memory_node != _starpu_get_worker_struct(worker)->memory_node)
  217. is_all_same_component = 0;
  218. }
  219. if(is_homogeneous)
  220. component->properties |= STARPU_SCHED_COMPONENT_HOMOGENEOUS;
  221. if(is_all_same_component)
  222. component->properties |= STARPU_SCHED_COMPONENT_SINGLE_MEMORY_NODE;
  223. }
  224. /* recursively set the component->workers member of component's subtree
  225. */
  226. void _starpu_sched_component_update_workers(struct starpu_sched_component * component)
  227. {
  228. STARPU_ASSERT(component);
  229. if(starpu_sched_component_is_worker(component))
  230. return;
  231. starpu_bitmap_unset_all(component->workers);
  232. unsigned i;
  233. for(i = 0; i < component->nchildren; i++)
  234. {
  235. _starpu_sched_component_update_workers(component->children[i]);
  236. starpu_bitmap_or(component->workers, component->children[i]->workers);
  237. }
  238. component->notify_change_workers(component);
  239. }
  240. /* recursively set the component->workers_in_ctx in component's subtree
  241. */
  242. void _starpu_sched_component_update_workers_in_ctx(struct starpu_sched_component * component, unsigned sched_ctx_id)
  243. {
  244. STARPU_ASSERT(component);
  245. /* worker components are shared among sched_ctxs, thus we do not apply the sched_ctx worker mask to them.
  246. * per-ctx filtering is performed higher in the tree */
  247. if(starpu_sched_component_is_worker(component))
  248. return;
  249. struct starpu_bitmap * workers_in_ctx = _starpu_get_worker_mask(sched_ctx_id);
  250. starpu_bitmap_unset_and(component->workers_in_ctx,component->workers, workers_in_ctx);
  251. unsigned i;
  252. for(i = 0; i < component->nchildren; i++)
  253. {
  254. struct starpu_sched_component * child = component->children[i];
  255. _starpu_sched_component_update_workers_in_ctx(child, sched_ctx_id);
  256. }
  257. set_properties(component);
  258. component->notify_change_workers(component);
  259. }
  260. /******************************************************************************
  261. * Scheduling Trees' helper functions *
  262. ******************************************************************************/
  263. struct starpu_bitmap * _starpu_get_worker_mask(unsigned sched_ctx_id)
  264. {
  265. STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
  266. struct starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  267. STARPU_ASSERT(t);
  268. return t->workers;
  269. }
  270. void starpu_sched_tree_update_workers_in_ctx(struct starpu_sched_tree * t)
  271. {
  272. STARPU_ASSERT(t);
  273. _starpu_sched_component_update_workers_in_ctx(t->root, t->sched_ctx_id);
  274. }
  275. void starpu_sched_tree_update_workers(struct starpu_sched_tree * t)
  276. {
  277. STARPU_ASSERT(t);
  278. _starpu_sched_component_update_workers(t->root);
  279. }
  280. /******************************************************************************
  281. * Scheduling Trees' Functions *
  282. * Most of them are used to define the starpu_sched_policy interface *
  283. ******************************************************************************/
  284. void starpu_sched_component_connect(struct starpu_sched_component *parent, struct starpu_sched_component *child)
  285. {
  286. parent->add_child(parent, child);
  287. child->add_parent(child, parent);
  288. _STARPU_TRACE_SCHED_COMPONENT_CONNECT(parent,child);
  289. }
  290. int starpu_sched_tree_push_task(struct starpu_task * task)
  291. {
  292. STARPU_ASSERT(task);
  293. unsigned sched_ctx_id = task->sched_ctx;
  294. struct starpu_sched_tree *tree = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  295. int ret_val = starpu_sched_component_push_task(NULL, tree->root,task);
  296. return ret_val;
  297. }
  298. int starpu_sched_component_push_task(struct starpu_sched_component *from STARPU_ATTRIBUTE_UNUSED, struct starpu_sched_component *to, struct starpu_task *task)
  299. {
  300. _STARPU_TRACE_SCHED_COMPONENT_PUSH(from, to, task);
  301. return to->push_task(to, task);
  302. }
  303. struct starpu_task * starpu_sched_tree_pop_task(unsigned sched_ctx)
  304. {
  305. unsigned workerid = starpu_worker_get_id_check();
  306. struct starpu_sched_component * component = starpu_sched_component_worker_get(sched_ctx, workerid);
  307. /* _starpu_sched_component_lock_worker(workerid) is called by component->pull_task()
  308. */
  309. struct starpu_task * task = starpu_sched_component_pull_task(component,NULL);
  310. return task;
  311. }
  312. struct starpu_task * starpu_sched_component_pull_task(struct starpu_sched_component *from, struct starpu_sched_component *to STARPU_ATTRIBUTE_UNUSED)
  313. {
  314. struct starpu_task *task = from->pull_task(from);
  315. if (task)
  316. _STARPU_TRACE_SCHED_COMPONENT_PULL(from, to, task);
  317. return task;
  318. }
  319. /* Pump mechanic to get the task flow rolling. Takes tasks from component and send them to the child.
  320. To be used by components with only one child */
  321. struct starpu_task* starpu_sched_component_pump_downstream(struct starpu_sched_component *component, int* success)
  322. {
  323. int ret = 0;
  324. STARPU_ASSERT(component->nchildren == 1);
  325. struct starpu_sched_component * child = component->children[0];
  326. struct starpu_task * task;
  327. while (1)
  328. {
  329. task = starpu_sched_component_pull_task(component,component);
  330. if (!task)
  331. break;
  332. ret = starpu_sched_component_push_task(component,child,task);
  333. if (ret)
  334. break;
  335. if(success)
  336. * success = 1;
  337. }
  338. if(task && ret)
  339. return task;
  340. return NULL;
  341. }
  342. void starpu_sched_tree_add_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers)
  343. {
  344. STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
  345. STARPU_ASSERT(workerids);
  346. struct starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  347. STARPU_COMPONENT_MUTEX_LOCK(&t->lock);
  348. _starpu_sched_component_lock_all_workers();
  349. unsigned i;
  350. for(i = 0; i < nworkers; i++)
  351. starpu_bitmap_set(t->workers, workerids[i]);
  352. starpu_sched_tree_update_workers_in_ctx(t);
  353. _starpu_sched_component_unlock_all_workers();
  354. STARPU_COMPONENT_MUTEX_UNLOCK(&t->lock);
  355. }
  356. void starpu_sched_tree_remove_workers(unsigned sched_ctx_id, int *workerids, unsigned nworkers)
  357. {
  358. STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
  359. STARPU_ASSERT(workerids);
  360. struct starpu_sched_tree * t = starpu_sched_ctx_get_policy_data(sched_ctx_id);
  361. STARPU_COMPONENT_MUTEX_LOCK(&t->lock);
  362. _starpu_sched_component_lock_all_workers();
  363. unsigned i;
  364. for(i = 0; i < nworkers; i++)
  365. starpu_bitmap_unset(t->workers, workerids[i]);
  366. starpu_sched_tree_update_workers_in_ctx(t);
  367. _starpu_sched_component_unlock_all_workers();
  368. STARPU_COMPONENT_MUTEX_UNLOCK(&t->lock);
  369. }
  370. static struct starpu_sched_tree *trees[STARPU_NMAX_SCHED_CTXS];
  371. struct starpu_sched_tree * starpu_sched_tree_create(unsigned sched_ctx_id)
  372. {
  373. STARPU_ASSERT(sched_ctx_id < STARPU_NMAX_SCHED_CTXS);
  374. STARPU_ASSERT(!trees[sched_ctx_id]);
  375. struct starpu_sched_tree *t;
  376. _STARPU_CALLOC(t, 1, sizeof(*t));
  377. t->sched_ctx_id = sched_ctx_id;
  378. t->workers = starpu_bitmap_create();
  379. STARPU_PTHREAD_MUTEX_INIT(&t->lock,NULL);
  380. trees[sched_ctx_id] = t;
  381. return t;
  382. }
  383. void starpu_sched_tree_destroy(struct starpu_sched_tree * tree)
  384. {
  385. STARPU_ASSERT(tree);
  386. STARPU_ASSERT(trees[tree->sched_ctx_id] == tree);
  387. trees[tree->sched_ctx_id] = NULL;
  388. if(tree->root)
  389. starpu_sched_component_destroy_rec(tree->root);
  390. starpu_bitmap_destroy(tree->workers);
  391. STARPU_PTHREAD_MUTEX_DESTROY(&tree->lock);
  392. free(tree);
  393. }
  394. struct starpu_sched_tree * starpu_sched_tree_get(unsigned sched_ctx_id)
  395. {
  396. return trees[sched_ctx_id];
  397. }
  398. /******************************************************************************
  399. * Interface Functions for Generic Scheduling Components *
  400. ******************************************************************************/
  401. void starpu_sched_component_add_child(struct starpu_sched_component* component, struct starpu_sched_component * child)
  402. {
  403. STARPU_ASSERT(component && child);
  404. STARPU_ASSERT(!starpu_sched_component_is_worker(component));
  405. unsigned i;
  406. for(i = 0; i < component->nchildren; i++)
  407. {
  408. STARPU_ASSERT(component->children[i] != component);
  409. STARPU_ASSERT(component->children[i] != NULL);
  410. }
  411. _STARPU_REALLOC(component->children, sizeof(struct starpu_sched_component *) * (component->nchildren + 1));
  412. component->children[component->nchildren] = child;
  413. component->nchildren++;
  414. }
  415. static void starpu_sched_component_remove_child(struct starpu_sched_component * component, struct starpu_sched_component * child)
  416. {
  417. STARPU_ASSERT(component && child);
  418. STARPU_ASSERT(!starpu_sched_component_is_worker(component));
  419. unsigned pos;
  420. for(pos = 0; pos < component->nchildren; pos++)
  421. if(component->children[pos] == child)
  422. break;
  423. STARPU_ASSERT(pos != component->nchildren);
  424. component->children[pos] = component->children[--component->nchildren];
  425. }
  426. static void starpu_sched_component_add_parent(struct starpu_sched_component* component, struct starpu_sched_component * parent)
  427. {
  428. STARPU_ASSERT(component && parent);
  429. unsigned i;
  430. for(i = 0; i < component->nparents; i++)
  431. {
  432. STARPU_ASSERT(component->parents[i] != component);
  433. STARPU_ASSERT(component->parents[i] != NULL);
  434. }
  435. _STARPU_REALLOC(component->parents, sizeof(struct starpu_sched_component *) * (component->nparents + 1));
  436. component->parents[component->nparents] = parent;
  437. component->nparents++;
  438. }
  439. static void starpu_sched_component_remove_parent(struct starpu_sched_component * component, struct starpu_sched_component * parent)
  440. {
  441. STARPU_ASSERT(component && parent);
  442. unsigned pos;
  443. for(pos = 0; pos < component->nparents; pos++)
  444. if(component->parents[pos] == parent)
  445. break;
  446. STARPU_ASSERT(pos != component->nparents);
  447. component->parents[pos] = component->parents[--component->nparents];
  448. }
  449. /* default implementation for component->pull_task()
  450. * just perform a recursive call on parent
  451. */
  452. static struct starpu_task * starpu_sched_component_parents_pull_task(struct starpu_sched_component * component)
  453. {
  454. STARPU_ASSERT(component);
  455. struct starpu_task * task = NULL;
  456. unsigned i;
  457. for(i=0; i < component->nparents; i++)
  458. {
  459. if(component->parents[i] == NULL)
  460. continue;
  461. else
  462. {
  463. task = starpu_sched_component_pull_task(component->parents[i], component);
  464. if(task)
  465. break;
  466. }
  467. }
  468. return task;
  469. }
  470. /* The default implementation of the can_push function is a recursive call to its parents.
  471. * A personally-made can_push in a component (like in prio components) is necessary to catch
  472. * this recursive call somewhere, if the user wants to exploit it.
  473. */
  474. static int starpu_sched_component_can_push(struct starpu_sched_component * component)
  475. {
  476. STARPU_ASSERT(component);
  477. int ret = 0;
  478. if(component->nparents > 0)
  479. {
  480. unsigned i;
  481. for(i=0; i < component->nparents; i++)
  482. {
  483. struct starpu_sched_component * parent = component->parents[i];
  484. if(parent != NULL)
  485. ret = parent->can_push(parent);
  486. if(ret)
  487. break;
  488. }
  489. }
  490. return ret;
  491. }
  492. /* A can_pull call will try to wake up one worker associated to the childs of the
  493. * component. It is currenly called by components which holds a queue (like fifo and prio
  494. * components) to signify its childs that a task has been pushed on its local queue.
  495. */
  496. static int starpu_sched_component_can_pull(struct starpu_sched_component * component)
  497. {
  498. STARPU_ASSERT(component);
  499. STARPU_ASSERT(!starpu_sched_component_is_worker(component));
  500. unsigned i;
  501. for(i = 0; i < component->nchildren; i++) {
  502. if (component->children[i]->can_pull(component->children[i]))
  503. return 1;
  504. }
  505. return 0;
  506. }
  507. /* Alternative can_pull which says that this component does not want
  508. to pull but prefers that you push. It can be used by decision
  509. components, in which decisions are usually taken in their push()
  510. functions */
  511. int starpu_sched_component_send_can_push_to_parents(struct starpu_sched_component * component)
  512. {
  513. STARPU_ASSERT(component);
  514. STARPU_ASSERT(!starpu_sched_component_is_worker(component));
  515. unsigned i;
  516. int ret = 0;
  517. for(i=0; i < component->nparents; i++)
  518. {
  519. if(component->parents[i] == NULL)
  520. continue;
  521. else
  522. {
  523. ret = component->parents[i]->can_push(component->parents[i]);
  524. if(ret)
  525. break;
  526. }
  527. }
  528. return ret != 0;
  529. }
  530. double starpu_sched_component_estimated_load(struct starpu_sched_component * component)
  531. {
  532. double sum = 0.0;
  533. unsigned i;
  534. for( i = 0; i < component->nchildren; i++)
  535. {
  536. struct starpu_sched_component * c = component->children[i];
  537. sum += c->estimated_load(c);
  538. }
  539. return sum;
  540. }
  541. double starpu_sched_component_estimated_end_min(struct starpu_sched_component * component)
  542. {
  543. STARPU_ASSERT(component);
  544. double min = DBL_MAX;
  545. unsigned i;
  546. for(i = 0; i < component->nchildren; i++)
  547. {
  548. double tmp = component->children[i]->estimated_end(component->children[i]);
  549. if(tmp < min)
  550. min = tmp;
  551. }
  552. return min;
  553. }
  554. double starpu_sched_component_estimated_end_average(struct starpu_sched_component * component)
  555. {
  556. STARPU_ASSERT(component);
  557. double sum = 0.0;
  558. unsigned i;
  559. for(i = 0; i < component->nchildren; i++)
  560. sum += component->children[i]->estimated_end(component->children[i]);
  561. return sum / component->nchildren;
  562. }
  563. static void take_component_and_does_nothing(struct starpu_sched_component * component STARPU_ATTRIBUTE_UNUSED)
  564. {
  565. }
  566. struct starpu_sched_component * starpu_sched_component_create(struct starpu_sched_tree *tree, const char *name)
  567. {
  568. struct starpu_sched_component *component;
  569. _STARPU_CALLOC(component, 1, sizeof(*component));
  570. component->tree = tree;
  571. component->workers = starpu_bitmap_create();
  572. component->workers_in_ctx = starpu_bitmap_create();
  573. component->add_child = starpu_sched_component_add_child;
  574. component->remove_child = starpu_sched_component_remove_child;
  575. component->add_parent = starpu_sched_component_add_parent;
  576. component->remove_parent = starpu_sched_component_remove_parent;
  577. component->pull_task = starpu_sched_component_parents_pull_task;
  578. component->can_push = starpu_sched_component_can_push;
  579. component->can_pull = starpu_sched_component_can_pull;
  580. component->estimated_load = starpu_sched_component_estimated_load;
  581. component->estimated_end = starpu_sched_component_estimated_end_min;
  582. component->deinit_data = take_component_and_does_nothing;
  583. component->notify_change_workers = take_component_and_does_nothing;
  584. component->name = strdup(name);
  585. _STARPU_TRACE_SCHED_COMPONENT_NEW(component);
  586. return component;
  587. }