5 #include "mixtesim_prototypes.h"
6 #include "list_scheduling.h"
8 #include "simdag/simdag.h"
11 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(mixtesim_heft, mixtesim,
12 "Logging specific to Mixtesim (heft)");
14 /* static function prototypes */
16 static Node *computeNodeList(DAG dag);
17 static int rankUCompareNode(const void *n1, const void *n2);
18 static int scheduleList(DAG dag, Node *L);
19 static void scheduleNode(Node node);
21 static double computeAverageLinkSpeed();
22 static double computeAverageLinkLatency();
23 static double computeAverageExecutionTime(Node node);
25 static void assignMeanCost(Node node);
26 static double computeAndAssignRankU(Node node);
29 static double computeEarliestStartTime(Node node, SD_workstation_t host);
30 static double computeEarliestFinishTime(Node node, SD_workstation_t host);
31 static void scheduleNodeOnHost(Node node, SD_workstation_t host);
35 * HEFT(): Implementation of HEFT
41 /* Compute mean cost for each node */
42 assignMeanCost(dag->root);
44 /* Compute Rank_u for each node */
45 computeAndAssignRankU(dag->root);
47 /* Compute the list for the schedule */
48 if ((L = computeNodeList(dag)) == NULL)
52 if (scheduleList(dag,L) == -1)
56 /* if (analyzeSchedule (grid,dag,L) == -1) */
59 /* Implement the Simgrid schedule */
60 implementSimgridSchedule(dag,L);
68 static Node *computeNodeList(DAG dag)
74 for (i=0;i<dag->nb_nodes;i++) {
75 if (dag->nodes[i]->type != NODE_COMPUTATION)
77 L = (Node *)realloc(L,(nb_comp_nodes+1)*sizeof(Node));
78 L[nb_comp_nodes] = dag->nodes[i];
82 /* sort L by rank_u */
83 qsort(L,nb_comp_nodes,sizeof(Node),rankUCompareNode);
85 /* NULL-terminate the list */
86 L = (Node *)realloc(L,(nb_comp_nodes+1)*sizeof(Node));
87 L[nb_comp_nodes]=NULL;
95 static int rankUCompareNode(const void *n1, const void *n2)
97 double rank_u1, rank_u2;
99 rank_u1 = NODE_ATTR((*((Node *)n1)))->rank_u;
100 rank_u2 = NODE_ATTR((*((Node *)n2)))->rank_u;
102 if (rank_u1 > rank_u2)
104 else if (rank_u1 == rank_u2)
113 static int scheduleList(DAG dag, Node *L)
118 /* Schedules the nodes in the order of list L */
119 while ((node=L[i++])) {
129 static void scheduleNode(Node node)
132 SD_workstation_t host;
133 SD_workstation_t best_host;
136 int nb_hosts = SD_workstation_get_number();
137 const SD_workstation_t *hosts = SD_workstation_get_list();
139 /* pick the best host */
140 for (i=0;i<nb_hosts;i++) {
142 /* compute the start_time on that host */
143 EFT = computeEarliestFinishTime(node, host);
144 /* fprintf(stderr,"EFT %s on %s = %f\n",node->sg_task->name, */
145 /* host->sg_host->name, EFT); */
147 /* is it the best one ? */
148 if ((min_EFT == -1.0)||
155 scheduleNodeOnHost(node, best_host);
161 * computeAverageLinkSpeed()
163 static double computeAverageLinkSpeed()
166 double bandwidth, ave;
167 int nb_links = SD_link_get_number();
168 const SD_link_t *links = SD_link_get_list();
171 for (i=0;i<nb_links;i++) {
172 bandwidth = SD_link_get_current_bandwidth(links[i]);
175 return (ave / nb_links);
179 * computeAverageLinkLatency()
181 static double computeAverageLinkLatency()
185 int nb_links = SD_link_get_number();
186 const SD_link_t *links = SD_link_get_list();
189 for (i=0;i<nb_links;i++) {
190 latency = SD_link_get_current_latency(links[i]);
193 return (ave / nb_links);
197 *computeAverageExecutionTime()
199 static double computeAverageExecutionTime(Node node)
202 double exec_time, ave;
203 int nb_hosts = SD_workstation_get_number();
204 const SD_workstation_t *hosts = SD_workstation_get_list();
205 double communication_amount = 0.0;
208 for (i=0;i<nb_hosts;i++) {
210 SD_task_get_execution_time(node->sd_task, 1, &hosts[i],
211 &node->cost, &communication_amount, -1.0);
216 return (ave / nb_hosts);
220 * computeAverageCommunicationTime()
222 static double computeAverageCommunicationTime(Node node)
224 return (computeAverageLinkLatency() +
225 (node->cost / computeAverageLinkSpeed()));
229 * computeEarliestFinishTime()
231 static double computeEarliestFinishTime(Node node, SD_workstation_t host)
233 double executionTime, EST;
234 double communication_amount = 0.0;
236 EST = computeEarliestStartTime(node, host);
238 SD_task_get_execution_time(node->sd_task, 1, &host, &node->cost,
239 &communication_amount, -1.0);
241 return executionTime + EST;
245 * computeEarliestStartTime()
247 static double computeEarliestStartTime(Node node, SD_workstation_t host)
249 double earliest_start_time=0.0;
251 double host_available = HOST_ATTR(host)->first_available;
252 double data_available;
253 double transfer_time;
254 double last_data_available;
255 Node parent,grand_parent;
256 SD_workstation_t grand_parent_host;
257 /* SD_link_t link; */
259 if (node->nb_parents != 0) {
260 /* compute last_data_available */
261 last_data_available=-1.0;
262 for (i=0;i<node->nb_parents;i++) {
263 parent = node->parents[i];
265 /* No transfers to schedule */
266 if (parent->type == NODE_ROOT) {
271 if (parent->type == NODE_TRANSFER) {
272 if (parent->nb_parents > 1) {
273 fprintf(stderr,"Warning: transfer has 2 parents\n");
275 grand_parent = parent->parents[0];
276 grand_parent_host = NODE_ATTR(grand_parent)->host;
278 SD_route_get_communication_time(grand_parent_host, host, parent->cost);
280 /* link = SD_workstation_route_get_list(grand_parent_host, host)[0]; */
282 /* if (link->global_index == -1) { */
283 /* /\* it is the local link so transfer_time = 0 *\/ */
284 /* transfer_time = 0.0; */
286 /* transfer_time = SG_getLinkLatency(link->sg_link, */
287 /* NODE_ATTR(grand_parent)->finish) + */
288 /* parent->cost/SG_getLinkBandwidth(link->sg_link, */
289 /* NODE_ATTR(grand_parent)->finish); */
291 data_available = NODE_ATTR(grand_parent)->finish + transfer_time;
295 if (parent->type == NODE_COMPUTATION) {
296 data_available = NODE_ATTR(parent)->finish;
299 if (last_data_available < data_available)
300 last_data_available = data_available;
303 /* return the MAX "*/
304 earliest_start_time = MAX(host_available,last_data_available);
307 return earliest_start_time;
312 * computeAndAssignRankU()
314 static double computeAndAssignRankU(Node node)
317 double my_rank_u = 0.0, max_rank_u, current_child_rank_u;
318 Node child,grand_child;
320 my_rank_u = NODE_ATTR(node)->mean_cost;
323 for (i=0;i<node->nb_children;i++) {
324 child = node->children[i];
326 if (node->type == NODE_ROOT)
328 my_rank_u = computeAndAssignRankU(child);
331 if (child->type == NODE_TRANSFER) { /* normal case */
332 if (child->nb_children > 1) {
333 fprintf(stderr,"Warning: transfer has 2 children\n");
335 grand_child = child->children[0];
336 current_child_rank_u = NODE_ATTR(child)->mean_cost +
337 computeAndAssignRankU(grand_child);
338 if (max_rank_u < current_child_rank_u)
339 max_rank_u = current_child_rank_u;
341 else /* child is the end node */
346 my_rank_u += max_rank_u;
348 NODE_ATTR(node)->rank_u = my_rank_u;
355 static void assignMeanCost(Node node)
359 for (i=0;i<node->nb_children;i++) {
360 if (node->children[i]->type == NODE_COMPUTATION)
361 NODE_ATTR(node->children[i])->mean_cost =
362 computeAverageExecutionTime(node->children[i]);
364 NODE_ATTR(node->children[i])->mean_cost =
365 computeAverageCommunicationTime(node->children[i]);
366 assignMeanCost(node->children[i]);
373 * scheduleNodeOnHost()
375 static void scheduleNodeOnHost(Node node, SD_workstation_t host)
378 double data_available, transfer_time, last_data_available;
379 /* SD_link_t link; */
380 Node parent, grand_parent;
381 SD_workstation_t grand_parent_host;
382 double communication_amount = 0.0;
384 INFO2("Affecting node '%s' to host '%s'", SD_task_get_name(node->sd_task),
385 SD_workstation_get_name(host));
387 last_data_available=-1.0;
388 for (i=0;i<node->nb_parents;i++) {
389 parent = node->parents[i];
391 if (parent->type == NODE_ROOT) {/* No transfers to schedule */
396 if (parent->type == NODE_TRANSFER) { /* normal case */
397 if (parent->nb_parents > 1) {
398 fprintf(stderr,"Warning: transfer has 2 parents\n");
400 grand_parent = parent->parents[0];
401 grand_parent_host = NODE_ATTR(grand_parent)->host;
403 SD_route_get_communication_time(grand_parent_host, host, parent->cost);
405 /* link = SD_workstation_route_get_list(grand_parent_host, host)[0]; */
407 /* if (link->global_index == -1) { */
408 /* /\* it is the local link so transfer_time = 0 *\/ */
409 /* transfer_time = 0.0; */
411 /* transfer_time = SG_getLinkLatency(link->sg_link, */
412 /* NODE_ATTR(grand_parent)->finish) + */
413 /* parent->cost/SG_getLinkBandwidth(link->sg_link, */
414 /* NODE_ATTR(grand_parent)->finish); */
417 data_available = NODE_ATTR(grand_parent)->finish + transfer_time;
421 if (parent->type == NODE_COMPUTATION) {
422 data_available = NODE_ATTR(parent)->finish;
425 if (last_data_available < data_available)
426 last_data_available = data_available;
429 /* node attributes */
430 NODE_ATTR(node)->start=MAX(last_data_available,
431 HOST_ATTR(host)->first_available);
432 NODE_ATTR(node)->finish=NODE_ATTR(node)->start +
433 SD_task_get_execution_time(node->sd_task, 1, &host, &node->cost,
434 &communication_amount, -1.0);
435 /* SG_getPrediction(SG_PERFECT, 0.0, NULL,host->sg_host, */
436 /* NODE_ATTR(node)->start,node->cost); */
438 NODE_ATTR(node)->host = host;
439 NODE_ATTR(node)->state = LIST_SCHEDULING_SCHEDULED;
441 /* host attributes */
442 HOST_ATTR(host)->first_available = NODE_ATTR(node)->finish;