node_random.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2013 INRIA
  4. * Copyright (C) 2013 Simon Archipoff
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. #include <starpu_sched_node.h>
  18. #include <core/workers.h>
  19. static double compute_relative_speedup(struct starpu_sched_node * node)
  20. {
  21. double sum = 0.0;
  22. int id;
  23. for(id = starpu_bitmap_first(node->workers_in_ctx);
  24. id != -1;
  25. id = starpu_bitmap_next(node->workers_in_ctx, id))
  26. {
  27. struct starpu_perfmodel_arch* perf_arch = starpu_worker_get_perf_archtype(id);
  28. sum += starpu_worker_get_relative_speedup(perf_arch);
  29. }
  30. STARPU_ASSERT(sum != 0.0);
  31. return sum;
  32. }
  33. static int random_push_task(struct starpu_sched_node * node, struct starpu_task * task)
  34. {
  35. STARPU_ASSERT(node->nchilds > 0);
  36. /* indexes_nodes and size are used to memoize node that can execute tasks
  37. * during the first phase of algorithm, it contain the size indexes of the nodes
  38. * that can execute task.
  39. */
  40. int indexes_nodes[node->nchilds];
  41. int size=0;
  42. /* speedup[i] is revelant only if i is in the size firsts elements of
  43. * indexes_nodes
  44. */
  45. double speedup[node->nchilds];
  46. double alpha_sum = 0.0;
  47. int i;
  48. for(i = 0; i < node->nchilds ; i++)
  49. {
  50. if(starpu_sched_node_can_execute_task(node->childs[i],task))
  51. {
  52. speedup[size] = compute_relative_speedup(node->childs[i]);
  53. alpha_sum += speedup[size];
  54. indexes_nodes[size] = i;
  55. size++;
  56. }
  57. }
  58. if(size == 0)
  59. return -ENODEV;
  60. /* not fully sure that this code is correct
  61. * because of bad properties of double arithmetic
  62. */
  63. double random = starpu_drand48()*alpha_sum;
  64. double alpha = 0.0;
  65. struct starpu_sched_node * select = NULL;
  66. for(i = 0; i < size ; i++)
  67. {
  68. int index = indexes_nodes[i];
  69. if(alpha + speedup[i] >= random)
  70. {
  71. select = node->childs[index];
  72. break;
  73. }
  74. alpha += speedup[i];
  75. }
  76. STARPU_ASSERT(select != NULL);
  77. if(starpu_sched_node_is_worker(select))
  78. {
  79. select->avail(select);
  80. return 1;
  81. }
  82. int ret_val = select->push_task(select,task);
  83. if(!ret_val)
  84. select->avail(select);
  85. return ret_val;
  86. }
  87. /* taking the min of estimated_end not seems to be a good value to return here
  88. * as random scheduler balance between childs very poorly
  89. */
  90. double random_estimated_end(struct starpu_sched_node * node)
  91. {
  92. double sum = 0.0;
  93. int i;
  94. for(i = 0; i < node->nchilds; i++)
  95. sum += node->childs[i]->estimated_end(node->childs[i]);
  96. return sum / node->nchilds;
  97. }
  98. struct starpu_sched_node * starpu_sched_node_random_create(void * arg STARPU_ATTRIBUTE_UNUSED)
  99. {
  100. struct starpu_sched_node * node = starpu_sched_node_create();
  101. node->estimated_end = random_estimated_end;
  102. node->push_task = random_push_task;
  103. return node;
  104. }
  105. int starpu_sched_node_is_random(struct starpu_sched_node *node)
  106. {
  107. return node->push_task == random_push_task;
  108. }