4 /* Copyright (c) 2004 Arnaud Legrand. All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
9 #include "surf_private.h"
10 #include "trace_mgr_private.h"
11 #include "cpu_ti_private.h"
15 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(surf_cpu_ti, surf,
16 "Logging specific to the SURF CPU TRACE INTEGRATION module");
19 static xbt_swag_t running_action_set_that_does_not_need_being_checked = NULL;
20 static xbt_swag_t modified_cpu = NULL;
21 static xbt_heap_t action_heap;
23 /* prototypes of new trace functions */
24 static double surf_cpu_integrate_trace(surf_cpu_ti_tgmr_t trace, double a,
26 static double surf_cpu_integrate_trace_simple(surf_cpu_ti_tgmr_t trace,
30 static double surf_cpu_solve_trace(surf_cpu_ti_tgmr_t trace, double a,
32 static double surf_cpu_solve_trace_somewhat_simple(surf_cpu_ti_tgmr_t trace,
33 double a, double amount);
34 static double surf_cpu_solve_trace_simple(surf_cpu_ti_tgmr_t trace, double a,
37 static void surf_cpu_free_trace(surf_cpu_ti_tgmr_t trace);
38 static void surf_cpu_free_time_series(surf_cpu_ti_timeSeries_t timeSeries);
41 static void surf_cpu_free_time_series(surf_cpu_ti_timeSeries_t timeSeries)
43 xbt_free(timeSeries->values);
47 static void surf_cpu_free_trace(surf_cpu_ti_tgmr_t trace)
51 for (i = 0; i < trace->nb_levels; i++)
52 surf_cpu_free_time_series(trace->levels[i]);
54 xbt_free(trace->levels);
58 static surf_cpu_ti_timeSeries_t surf_cpu_ti_time_series_new(tmgr_trace_t
62 surf_cpu_ti_timeSeries_t series;
64 double previous_time = 0.0;
67 series = xbt_new0(s_surf_cpu_ti_timeSeries_t, 1);
68 series->spacing = spacing;
71 xbt_dynar_foreach(power_trace->event_list, cpt, val) {
72 /* delta = the next trace event
73 * value = state until next event */
77 /* ignore events if time is less than spacing */
78 if (time < (series->nb_points) * spacing) {
82 while (previous_time < time) {
83 series->values = xbt_realloc(series->values,
84 (series->nb_points + 1) * sizeof(double));
85 series->values[(series->nb_points)++] = value;
86 previous_time += spacing;
94 * \brief Create new levels of points.
96 * This function assumes that the input series is
97 * evenly spaces, starting at time 0. That is the sort
98 * of series produced by surf_cpu_ti_time_series_new()
100 * \param original Original timeSeries structure
101 * \param factor New factor to spacing
102 * \return New timeSeries structure with spacing*factor
104 static surf_cpu_ti_timeSeries_t
105 surf_cpu_ti_time_series_coarsen(surf_cpu_ti_timeSeries_t original, int factor)
107 surf_cpu_ti_timeSeries_t series;
109 double dfactor = (double) (factor);
112 if (original->nb_points <= factor) {
113 DEBUG0("Warning: Not enough data points to coarsen time series");
117 series = xbt_new0(s_surf_cpu_ti_timeSeries_t, 1);
118 series->spacing = (original->spacing) * dfactor;
120 while (i + factor <= original->nb_points) {
123 for (j = i; j < i + factor; j++) {
124 ave += original->values[j];
128 series->values = xbt_realloc(series->values,
129 (series->nb_points + 1) * sizeof(double));
130 series->values[(series->nb_points)++] = ave;
138 * \brief Create a new integration trace from a tmgr_trace_t
140 * \param power_trace CPU availability trace
141 * \param value Percentage of CPU power disponible (usefull to fixed tracing)
142 * \param spacing Initial spacing
143 * \return Integration trace structure
145 static surf_cpu_ti_tgmr_t cpu_ti_parse_trace(tmgr_trace_t power_trace,
148 surf_cpu_ti_tgmr_t trace;
149 surf_cpu_ti_timeSeries_t series;
151 trace = xbt_new0(s_surf_cpu_ti_tgmr_t, 1);
153 /* no availability file, fixed trace */
155 trace->type = TRACE_FIXED;
156 trace->value = value;
157 DEBUG1("No availabily trace. Constant value = %lf", value);
161 DEBUG2("Value %lf, Spacing %lf", value, power_trace->timestep);
162 series = surf_cpu_ti_time_series_new(power_trace, power_trace->timestep);
166 trace->type = TRACE_DYNAMIC;
168 trace->levels = xbt_new0(surf_cpu_ti_timeSeries_t, 1);
169 trace->levels[(trace->nb_levels)++] = series;
171 /* Do the coarsening with some arbitrary factors */
172 for (i = 1; i < TRACE_NB_LEVELS; i++) {
173 series = surf_cpu_ti_time_series_coarsen(trace->levels[i - 1], 4 * i);
175 if (series) { /* If coarsening was possible, add it */
176 trace->levels = xbt_realloc(trace->levels,
178 1) * sizeof(s_surf_cpu_ti_timeSeries_t));
179 trace->levels[(trace->nb_levels)++] = series;
180 } else { /* otherwise stop */
185 /* calcul of initial integrate */
187 power_trace->timestep * ((double) (trace->levels[0]->nb_points));
188 trace->total = surf_cpu_integrate_trace(trace, 0.0, trace->last_time);
194 static cpu_ti_t cpu_new(char *name, double power_peak,
196 tmgr_trace_t power_trace,
197 e_surf_resource_state_t state_initial,
198 tmgr_trace_t state_trace, xbt_dict_t cpu_properties)
200 cpu_ti_t cpu = xbt_new0(s_cpu_ti_t, 1);
201 s_surf_action_cpu_ti_t ti_action;
202 xbt_assert1(!surf_model_resource_by_name(surf_cpu_model, name),
203 "Host '%s' declared several times in the platform file", name);
204 cpu->action_set = xbt_swag_new(xbt_swag_offset(ti_action, cpu_list_hookup));
205 cpu->generic_resource.model = surf_cpu_model;
206 cpu->generic_resource.name = name;
207 cpu->generic_resource.properties = cpu_properties;
208 cpu->power_peak = power_peak;
209 xbt_assert0(cpu->power_peak > 0, "Power has to be >0");
210 DEBUG1("power scale %lf", power_scale);
211 cpu->power_scale = power_scale;
212 cpu->avail_trace = cpu_ti_parse_trace(power_trace, power_scale);
213 cpu->state_current = state_initial;
216 tmgr_history_add_trace(history, state_trace, 0.0, 0, cpu);
218 xbt_dict_set(surf_model_resource_set(surf_cpu_model), name, cpu,
225 static void parse_cpu_init(void)
227 double power_peak = 0.0;
228 double power_scale = 0.0;
229 tmgr_trace_t power_trace = NULL;
230 e_surf_resource_state_t state_initial = SURF_RESOURCE_OFF;
231 tmgr_trace_t state_trace = NULL;
233 power_peak = get_cpu_power(A_surfxml_host_power);
234 surf_parse_get_double(&power_scale, A_surfxml_host_availability);
235 power_trace = tmgr_trace_new(A_surfxml_host_availability_file);
237 xbt_assert0((A_surfxml_host_state == A_surfxml_host_state_ON) ||
238 (A_surfxml_host_state == A_surfxml_host_state_OFF),
240 if (A_surfxml_host_state == A_surfxml_host_state_ON)
241 state_initial = SURF_RESOURCE_ON;
242 if (A_surfxml_host_state == A_surfxml_host_state_OFF)
243 state_initial = SURF_RESOURCE_OFF;
244 state_trace = tmgr_trace_new(A_surfxml_host_state_file);
246 current_property_set = xbt_dict_new();
247 cpu_new(xbt_strdup(A_surfxml_host_id), power_peak, power_scale,
248 power_trace, state_initial, state_trace, current_property_set);
252 static void add_traces_cpu(void)
254 xbt_dict_cursor_t cursor = NULL;
255 char *trace_name, *elm;
257 static int called = 0;
263 /* connect all traces relative to hosts */
264 xbt_dict_foreach(trace_connect_list_host_avail, cursor, trace_name, elm) {
265 tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
266 cpu_ti_t cpu = surf_model_resource_by_name(surf_cpu_model, elm);
268 xbt_assert1(cpu, "Host %s undefined", elm);
269 xbt_assert1(trace, "Trace %s undefined", trace_name);
271 if (cpu->state_event) {
272 DEBUG1("Trace already configured for this CPU(%s), ignoring it", elm);
275 DEBUG2("Add state trace: %s to CPU(%s)", trace_name, elm);
276 cpu->state_event = tmgr_history_add_trace(history, trace, 0.0, 0, cpu);
279 xbt_dict_foreach(trace_connect_list_power, cursor, trace_name, elm) {
280 tmgr_trace_t trace = xbt_dict_get_or_null(traces_set_list, trace_name);
281 cpu_ti_t cpu = surf_model_resource_by_name(surf_cpu_model, elm);
283 xbt_assert1(cpu, "Host %s undefined", elm);
284 xbt_assert1(trace, "Trace %s undefined", trace_name);
286 DEBUG2("Add power trace: %s to CPU(%s)", trace_name, elm);
287 if (cpu->avail_trace)
288 surf_cpu_free_trace(cpu->avail_trace);
290 cpu->avail_trace = cpu_ti_parse_trace(trace, cpu->power_scale);
294 static void define_callbacks(const char *file)
296 surf_parse_reset_parser();
297 surfxml_add_callback(STag_surfxml_host_cb_list, parse_cpu_init);
298 surfxml_add_callback(ETag_surfxml_platform_cb_list, &add_traces_cpu);
301 static int resource_used(void *resource_id)
303 cpu_ti_t cpu = resource_id;
304 return xbt_swag_size(cpu->action_set);
307 static int action_unref(surf_action_t action)
310 if (!action->refcount) {
311 xbt_swag_remove(action, action->state_set);
312 /* remove from action_set */
313 xbt_swag_remove(action, ACTION_GET_CPU(action)->action_set);
314 /* remove from heap */
315 xbt_heap_remove(action_heap, ((surf_action_cpu_ti_t) action)->index_heap);
316 xbt_swag_insert(ACTION_GET_CPU(action), modified_cpu);
323 static void action_cancel(surf_action_t action)
325 surf_action_state_set(action, SURF_ACTION_FAILED);
326 xbt_heap_remove(action_heap, ((surf_action_cpu_ti_t) action)->index_heap);
327 xbt_swag_insert(ACTION_GET_CPU(action), modified_cpu);
331 static void cpu_action_state_set(surf_action_t action,
332 e_surf_action_state_t state)
334 surf_action_state_set(action, state);
335 xbt_swag_insert(ACTION_GET_CPU(action), modified_cpu);
340 * \brief Update the remaning amount of actions
342 * \param cpu Cpu on which the actions are running
343 * \param now Current time
345 static void cpu_update_remaining_amount(cpu_ti_t cpu, double now)
347 #define GENERIC_ACTION(action) action->generic_action
349 surf_action_cpu_ti_t action;
351 /* alrealdy updated */
352 if (cpu->last_update == now)
355 /* calcule the surface */
357 surf_cpu_integrate_trace(cpu->avail_trace, cpu->last_update,
358 now) * cpu->power_peak;
359 DEBUG2("Flops total: %lf, Last update %lf", area_total, cpu->last_update);
361 xbt_swag_foreach(action, cpu->action_set) {
362 /* action not running, skip it */
363 if (GENERIC_ACTION(action).state_set !=
364 surf_cpu_model->states.running_action_set)
367 /* bogus priority, skip it */
368 if (GENERIC_ACTION(action).priority <= 0)
371 /* action suspended, skip it */
372 if (action->suspended != 0)
375 /* action don't need update */
376 if (GENERIC_ACTION(action).start >= now)
379 /* skip action that are finishing now */
380 if (GENERIC_ACTION(action).finish >= 0
381 && GENERIC_ACTION(action).finish <= now)
384 /* update remaining */
385 double_update(&(GENERIC_ACTION(action).remains),
386 area_total / (cpu->sum_priority *
387 GENERIC_ACTION(action).priority));
388 DEBUG2("Update remaining action(%p) remaining %lf", action,
389 GENERIC_ACTION(action).remains);
391 cpu->last_update = now;
392 #undef GENERIC_ACTION
396 * \brief Update the finish date of action if necessary
398 * \param cpu Cpu on which the actions are running
399 * \param now Current time
401 static void cpu_update_action_finish_date(cpu_ti_t cpu, double now)
403 #define GENERIC_ACTION(action) action->generic_action
404 surf_action_cpu_ti_t action;
405 double sum_priority = 0.0, total_area, min_finish = -1;
407 /* update remaning amount of actions */
408 cpu_update_remaining_amount(cpu, now);
410 xbt_swag_foreach(action, cpu->action_set) {
411 /* action not running, skip it */
412 if (GENERIC_ACTION(action).state_set !=
413 surf_cpu_model->states.running_action_set)
416 /* bogus priority, skip it */
417 if (GENERIC_ACTION(action).priority <= 0)
420 /* action suspended, skip it */
421 if (action->suspended != 0)
424 sum_priority += 1.0 / GENERIC_ACTION(action).priority;
426 cpu->sum_priority = sum_priority;
428 xbt_swag_foreach(action, cpu->action_set) {
429 /* action not running, skip it */
430 if (GENERIC_ACTION(action).state_set !=
431 surf_cpu_model->states.running_action_set)
434 /* verify if the action is really running on cpu */
435 if (action->suspended == 0 && GENERIC_ACTION(action).priority > 0) {
436 /* total area needed to finish the action. Used in trace integration */
438 (GENERIC_ACTION(action).remains) * sum_priority *
439 GENERIC_ACTION(action).priority;
441 total_area /= cpu->power_peak;
443 GENERIC_ACTION(action).finish =
444 surf_cpu_solve_trace(cpu->avail_trace, now, total_area);
445 /* verify which event will happen before (max_duration or finish time) */
446 if ((GENERIC_ACTION(action).max_duration != NO_MAX_DURATION) &&
447 (GENERIC_ACTION(action).start +
448 GENERIC_ACTION(action).max_duration <
449 GENERIC_ACTION(action).finish))
450 min_finish = GENERIC_ACTION(action).start +
451 GENERIC_ACTION(action).max_duration;
453 min_finish = GENERIC_ACTION(action).finish;
455 /* put the max duration time on heap */
456 if (GENERIC_ACTION(action).max_duration != NO_MAX_DURATION)
458 (GENERIC_ACTION(action).start +
459 GENERIC_ACTION(action).max_duration);
461 /* add in action heap */
462 DEBUG2("action(%p) index %d", action, action->index_heap);
463 if (action->index_heap >= 0) {
464 surf_action_cpu_ti_t heap_act =
465 xbt_heap_remove(action_heap, action->index_heap);
466 if (heap_act != action)
469 if (min_finish != NO_MAX_DURATION)
470 xbt_heap_push(action_heap, action, min_finish);
473 ("Update finish time: Action: %p, Start Time: %lf Finish Time: %lf Max duration %lf",
474 action, GENERIC_ACTION(action).start, GENERIC_ACTION(action).finish,
475 GENERIC_ACTION(action).max_duration);
477 /* remove from modified cpu */
478 xbt_swag_remove(cpu, modified_cpu);
479 #undef GENERIC_ACTION
482 static double share_resources(double now)
484 cpu_ti_t cpu, cpu_next;
485 double min_action_duration = -1;
487 /* iterates over modified cpus to update share resources */
488 xbt_swag_foreach_safe(cpu, cpu_next, modified_cpu) {
489 cpu_update_action_finish_date(cpu, now);
491 /* get the min next event if heap not empty */
492 if (xbt_heap_size(action_heap) > 0)
493 min_action_duration = xbt_heap_maxkey(action_heap) - now;
495 DEBUG1("Share resources, min next event date: %lf", min_action_duration);
497 return min_action_duration;
500 static void update_actions_state(double now, double delta)
502 #define GENERIC_ACTION(action) action->generic_action
503 surf_action_cpu_ti_t action;
504 while ((xbt_heap_size(action_heap) > 0)
505 && (xbt_heap_maxkey(action_heap) <= now)) {
506 DEBUG1("Action %p: finish", action);
507 action = xbt_heap_pop(action_heap);
508 GENERIC_ACTION(action).finish = surf_get_clock();
509 /* set the remains to 0 due to precision problems when updating the remaining amount */
510 GENERIC_ACTION(action).remains = 0;
511 cpu_action_state_set((surf_action_t) action, SURF_ACTION_DONE);
512 /* update remaining amout of all actions */
513 cpu_update_remaining_amount(action->cpu, surf_get_clock());
515 #undef GENERIC_ACTION
518 static void update_resource_state(void *id,
519 tmgr_trace_event_t event_type,
520 double value, double date)
523 surf_action_cpu_ti_t action;
524 if (event_type == cpu->state_event) {
526 cpu->state_current = SURF_RESOURCE_ON;
528 cpu->state_current = SURF_RESOURCE_OFF;
530 /* put all action running on cpu to failed */
531 xbt_swag_foreach(action, cpu->action_set) {
532 if (surf_action_state_get((surf_action_t) action) ==
534 || surf_action_state_get((surf_action_t) action) ==
536 || surf_action_state_get((surf_action_t) action) ==
537 SURF_ACTION_NOT_IN_THE_SYSTEM) {
538 action->generic_action.finish = date;
539 cpu_action_state_set((surf_action_t) action, SURF_ACTION_FAILED);
540 if (action->index_heap >= 0) {
541 surf_action_cpu_ti_t heap_act =
542 xbt_heap_remove(action_heap, action->index_heap);
543 if (heap_act != action)
549 if (tmgr_trace_event_free(event_type))
550 cpu->state_event = NULL;
552 CRITICAL0("Unknown event ! \n");
559 static surf_action_t execute(void *cpu, double size)
561 surf_action_cpu_ti_t action = NULL;
564 XBT_IN2("(%s,%g)", surf_resource_name(CPU), size);
566 surf_action_new(sizeof(s_surf_action_cpu_ti_t), size, surf_cpu_model,
567 CPU->state_current != SURF_RESOURCE_ON);
569 action->index_heap = -1;
571 xbt_swag_insert(CPU, modified_cpu);
573 xbt_swag_insert(action, CPU->action_set);
575 action->suspended = 0; /* Should be useless because of the
576 calloc but it seems to help valgrind... */
579 return (surf_action_t) action;
582 static void action_update_index_heap(void *action, int i)
584 ((surf_action_cpu_ti_t) action)->index_heap = i;
587 static surf_action_t action_sleep(void *cpu, double duration)
589 surf_action_cpu_ti_t action = NULL;
592 duration = MAX(duration, MAXMIN_PRECISION);
594 XBT_IN2("(%s,%g)", surf_resource_name(cpu), duration);
595 action = (surf_action_cpu_ti_t) execute(cpu, 1.0);
596 action->generic_action.max_duration = duration;
597 action->suspended = 2;
598 if (duration == NO_MAX_DURATION) {
599 /* Move to the *end* of the corresponding action set. This convention
600 is used to speed up update_resource_state */
601 xbt_swag_remove(action, ((surf_action_t) action)->state_set);
602 ((surf_action_t) action)->state_set =
603 running_action_set_that_does_not_need_being_checked;
604 xbt_swag_insert(action, ((surf_action_t) action)->state_set);
607 return (surf_action_t) action;
610 static void action_suspend(surf_action_t action)
612 XBT_IN1("(%p)", action);
613 if (((surf_action_cpu_ti_t) action)->suspended != 2) {
614 ((surf_action_cpu_ti_t) action)->suspended = 1;
615 xbt_swag_insert(ACTION_GET_CPU(action), modified_cpu);
620 static void action_resume(surf_action_t action)
622 XBT_IN1("(%p)", action);
623 if (((surf_action_cpu_ti_t) action)->suspended != 2) {
624 ((surf_action_cpu_ti_t) action)->suspended = 0;
625 xbt_swag_insert(ACTION_GET_CPU(action), modified_cpu);
630 static int action_is_suspended(surf_action_t action)
632 return (((surf_action_cpu_ti_t) action)->suspended == 1);
635 static void action_set_max_duration(surf_action_t action, double duration)
637 surf_action_cpu_ti_t ACT = (surf_action_cpu_ti_t) action;
640 XBT_IN2("(%p,%g)", action, duration);
642 action->max_duration = duration;
646 (action->start + action->max_duration) <
647 action->finish ? (action->start +
648 action->max_duration) : action->finish;
650 min_finish = action->finish;
652 /* add in action heap */
653 if (ACT->index_heap >= 0) {
654 surf_action_cpu_ti_t heap_act =
655 xbt_heap_remove(action_heap, ACT->index_heap);
659 xbt_heap_push(action_heap, ACT, min_finish);
664 static void action_set_priority(surf_action_t action, double priority)
666 XBT_IN2("(%p,%g)", action, priority);
667 action->priority = priority;
668 xbt_swag_insert(ACTION_GET_CPU(action), modified_cpu);
672 static double action_get_remains(surf_action_t action)
674 XBT_IN1("(%p)", action);
675 cpu_update_remaining_amount((cpu_ti_t) ((surf_action_cpu_ti_t) action)->cpu,
677 return action->remains;
681 static e_surf_resource_state_t get_state(void *cpu)
683 return ((cpu_ti_t) cpu)->state_current;
686 static double get_speed(void *cpu, double load)
688 return load * (((cpu_ti_t) cpu)->power_peak);
692 * \brief Auxiliar function to update the cpu power scale.
694 * This function uses the trace structure to return the power scale at the determined time a.
695 * \param trace Trace structure to search the updated power scale
697 * \return Cpu power scale
699 static double surf_cpu_get_power_scale(surf_cpu_ti_tgmr_t trace, double a)
704 reduced_a = a - floor(a / trace->last_time) * trace->last_time;
705 point = (int) (reduced_a / trace->levels[0]->spacing);
706 return trace->levels[0]->values[point];
709 static double get_available_speed(void *cpu)
713 surf_cpu_get_power_scale(CPU->avail_trace, surf_get_clock());
714 /* number between 0 and 1 */
715 return CPU->power_scale;
718 static void finalize(void)
721 xbt_dict_cursor_t cursor;
723 xbt_dict_foreach(surf_model_resource_set(surf_cpu_model), cursor, key, cpu) {
725 xbt_swag_free(CPU->action_set);
726 surf_cpu_free_trace(CPU->avail_trace);
729 surf_model_exit(surf_cpu_model);
730 surf_cpu_model = NULL;
732 xbt_swag_free(running_action_set_that_does_not_need_being_checked);
733 xbt_swag_free(modified_cpu);
734 running_action_set_that_does_not_need_being_checked = NULL;
735 xbt_heap_free(action_heap);
738 static void surf_cpu_model_init_internal(void)
740 s_surf_action_t action;
743 surf_cpu_model = surf_model_init();
745 running_action_set_that_does_not_need_being_checked =
746 xbt_swag_new(xbt_swag_offset(action, state_hookup));
748 modified_cpu = xbt_swag_new(xbt_swag_offset(cpu, modified_cpu_hookup));
750 surf_cpu_model->name = "CPU_TI";
752 surf_cpu_model->action_unref = action_unref;
753 surf_cpu_model->action_cancel = action_cancel;
754 surf_cpu_model->action_state_set = cpu_action_state_set;
756 surf_cpu_model->model_private->resource_used = resource_used;
757 surf_cpu_model->model_private->share_resources = share_resources;
758 surf_cpu_model->model_private->update_actions_state = update_actions_state;
759 surf_cpu_model->model_private->update_resource_state =
760 update_resource_state;
761 surf_cpu_model->model_private->finalize = finalize;
763 surf_cpu_model->suspend = action_suspend;
764 surf_cpu_model->resume = action_resume;
765 surf_cpu_model->is_suspended = action_is_suspended;
766 surf_cpu_model->set_max_duration = action_set_max_duration;
767 surf_cpu_model->set_priority = action_set_priority;
768 surf_cpu_model->get_remains = action_get_remains;
770 surf_cpu_model->extension.cpu.execute = execute;
771 surf_cpu_model->extension.cpu.sleep = action_sleep;
773 surf_cpu_model->extension.cpu.get_state = get_state;
774 surf_cpu_model->extension.cpu.get_speed = get_speed;
775 surf_cpu_model->extension.cpu.get_available_speed = get_available_speed;
777 action_heap = xbt_heap_new(8, NULL);
778 xbt_heap_set_update_callback(action_heap, action_update_index_heap);
782 void surf_cpu_model_init_ti(const char *filename)
786 surf_cpu_model_init_internal();
787 define_callbacks(filename);
788 xbt_dynar_push(model_list, &surf_cpu_model);
792 ///////////////// BEGIN INTEGRAL //////////////
795 * \brief Integrate trace
797 * Wrapper around surf_cpu_integrate_trace_simple() to get
800 * \param trace Trace structure.
801 * \param a Begin of interval
802 * \param b End of interval
803 * \return the integrate value. -1 if an error occurs.
805 static double surf_cpu_integrate_trace(surf_cpu_ti_tgmr_t trace, double a,
811 int a_index, b_index;
813 if ((a < 0.0) || (a > b)) {
815 ("Error, invalid integration interval [%.2f,%.2f]. You probably have a task executing with negative computation amount. Check your code.",
822 if (trace->type == TRACE_FIXED) {
823 return ((b - a) * trace->value);
826 if (ceil(a / trace->last_time) == a / trace->last_time)
827 a_index = 1 + (int) (ceil(a / trace->last_time));
829 a_index = (int) (ceil(a / trace->last_time));
831 b_index = (int) (floor(b / trace->last_time));
833 if (a_index > b_index) { /* Same chunk */
834 return surf_cpu_integrate_trace_simple(trace,
836 1) * trace->last_time,
837 b - (b_index) * trace->last_time);
840 first_chunk = surf_cpu_integrate_trace_simple(trace,
842 1) * trace->last_time,
844 middle_chunk = (b_index - a_index) * trace->total;
845 last_chunk = surf_cpu_integrate_trace_simple(trace,
848 (b_index) * trace->last_time);
850 DEBUG3("first_chunk=%.2f middle_chunk=%.2f last_chunk=%.2f\n",
851 first_chunk, middle_chunk, last_chunk);
853 return (first_chunk + middle_chunk + last_chunk);
857 * \brief Integrate the trace between a and b.
859 * integrates without taking cyclic-traces into account.
860 * [a,b] \subset [0,last_time]
862 * \param trace Trace structure.
863 * \param a Begin of interval
864 * \param b End of interval
865 * \return the integrate value. -1 if an error occurs.
867 static double surf_cpu_integrate_trace_simple(surf_cpu_ti_tgmr_t trace,
870 double integral = 0.0;
874 long l_bounds[TRACE_NB_LEVELS];
875 long u_bounds[TRACE_NB_LEVELS];
876 double a_divided_by_spacing;
877 double current_spacing;
878 DEBUG2("Computing simple integral on [%.2f , %.2f]\n", a, b);
881 if ((a < 0.0) || (b < a) || (a > trace->last_time)
882 || (b > trace->last_time)) {
884 ("Error, invalid integration interval [%.2f,%.2f]. You probably have a task executing with negative computation amount. Check your code.",
892 for (i = 0; i < trace->nb_levels; i++) {
893 a_divided_by_spacing = a / trace->levels[i]->spacing;
894 if (ceil(a_divided_by_spacing) == a_divided_by_spacing)
895 l_bounds[i] = 1 + (long) ceil(a_divided_by_spacing);
897 l_bounds[i] = (long) (ceil(a_divided_by_spacing));
898 if (b == trace->last_time) {
899 u_bounds[i] = (long) (floor(b / trace->levels[i]->spacing)) - 1;
901 u_bounds[i] = (long) (floor(b / trace->levels[i]->spacing));
903 DEBUG3("level %d: l%ld u%ld\n", i, l_bounds[i], u_bounds[i]);
905 if (l_bounds[i] <= u_bounds[i])
908 DEBUG1("top_level=%d\n", top_level);
910 /* Are a and b BOTH in the same chunk of level 0 ? */
911 if (l_bounds[0] > u_bounds[0]) {
912 return (b - a) * (trace->levels[0]->values[u_bounds[0]]);
915 /* first sub-level amount */
916 integral += ((l_bounds[0]) * (trace->levels[0]->spacing) - a) *
917 (trace->levels[0]->values[l_bounds[0] - 1]);
919 DEBUG1("Initial level 0 amount is %.2f\n", integral);
921 /* first n-1 levels */
922 for (i = 0; i < top_level; i++) {
924 if (l_bounds[i] >= u_bounds[i])
927 current_spacing = trace->levels[i]->spacing;
932 while (double_positive
933 (l_bounds[i + 1] * trace->levels[i + 1]->spacing -
934 index * current_spacing)) {
935 integral += current_spacing * trace->levels[i]->values[index];
936 DEBUG2("%.2f->%.2f|",
937 index * (trace->levels[i]->spacing),
938 (index + 1) * (trace->levels[i]->spacing));
945 DEBUG1("After going up: %.2f\n", integral);
948 current_spacing = trace->levels[top_level]->spacing;
949 index = l_bounds[top_level];
951 DEBUG1("L%d:", top_level);
953 while (index < u_bounds[top_level]) {
954 integral += current_spacing * trace->levels[top_level]->values[index];
956 DEBUG2("%.2f->%.2f|",
957 index * (trace->levels[top_level]->spacing),
958 (index + 1) * (trace->levels[top_level]->spacing));
964 DEBUG1("After steady : %.2f\n", integral);
966 /* And going back down */
967 for (i = top_level - 1; i >= 0; i--) {
968 if (l_bounds[i] > u_bounds[i])
971 current_spacing = trace->levels[i]->spacing;
972 index = u_bounds[i + 1] * (trace->levels[i + 1]->spacing /
975 while (double_positive
976 ((u_bounds[i]) * current_spacing - index * current_spacing)) {
977 integral += current_spacing * trace->levels[i]->values[index];
978 DEBUG2("%.2f->%.2f|",
979 index * (trace->levels[i]->spacing),
980 (index + 1) * (trace->levels[i]->spacing));
985 DEBUG1("After going down : %.2f", integral);
988 /* Little piece at the end */
989 integral += (b - u_bounds[0] * (trace->levels[0]->spacing)) *
990 (trace->levels[0]->values[u_bounds[0]]);
992 DEBUG1("After last bit : %.2f", integral);
999 * \brief Calcul the time needed to execute "amount" on cpu.
1001 * Here, amount can span multiple trace periods
1003 * \param trace CPU trace structure
1004 * \param a Initial time
1005 * \param amount Amount of calcul to be executed
1008 static double surf_cpu_solve_trace(surf_cpu_ti_tgmr_t trace, double a,
1013 double reduced_amount;
1017 /* Fix very small negative numbers */
1018 if ((a < 0.0) && (a > -EPSILON)) {
1021 if ((amount < 0.0) && (amount > -EPSILON)) {
1026 if ((a < 0.0) || (amount < 0.0)) {
1028 ("Error, invalid parameters [a = %.2f, amount = %.2f]. You probably have a task executing with negative computation amount. Check your code.",
1033 /* At this point, a and amount are positive */
1035 if (amount < EPSILON)
1038 /* Is the trace fixed ? */
1039 if (trace->type == TRACE_FIXED) {
1040 return (a + (amount / trace->value));
1043 /* Reduce the problem to one where amount <= trace_total */
1044 quotient = (int) (floor(amount / trace->total));
1045 reduced_amount = (trace->total) * ((amount / trace->total) -
1046 floor(amount / trace->total));
1047 reduced_a = a - (trace->last_time) * (int) (floor(a / trace->last_time));
1049 DEBUG3("Quotient: %d reduced_amount: %lf reduced_a: %lf", quotient,
1050 reduced_amount, reduced_a);
1052 /* Now solve for new_amount which is <= trace_total */
1054 fprintf(stderr,"reduced_a = %.2f\n",reduced_a);
1055 fprintf(stderr,"reduced_amount = %.2f\n",reduced_amount);
1058 surf_cpu_solve_trace_somewhat_simple(trace, reduced_a, reduced_amount);
1060 /* Re-map to the original b and amount */
1061 b = (trace->last_time) * (int) (floor(a / trace->last_time)) +
1062 (quotient * trace->last_time) + reduced_b;
1067 * \brief Auxiliar function to solve integral
1069 * Here, amount is <= trace->total
1070 * and a <=trace->last_time
1073 static double surf_cpu_solve_trace_somewhat_simple(surf_cpu_ti_tgmr_t trace,
1074 double a, double amount)
1076 double amount_till_end;
1079 DEBUG2("In solveTraceIntegralSomewhatSimple(): [%.2f, amount=%.2f]",
1082 amount_till_end = surf_cpu_integrate_trace(trace, a, trace->last_time);
1084 fprintf(stderr,"amount_till_end=%.2f\n",amount_till_end);
1087 if (amount_till_end > amount) {
1088 b = surf_cpu_solve_trace_simple(trace, a, amount);
1090 b = trace->last_time +
1091 surf_cpu_solve_trace_simple(trace, 0.0, amount - amount_till_end);
1098 * \brief Auxiliar function to solve integral
1099 * surf_cpu_solve_trace_simple()
1101 * solve for the upper bound without taking
1102 * cyclic-traces into account.
1104 * [a,y] \subset [0,last_time]
1107 static double surf_cpu_solve_trace_simple(surf_cpu_ti_tgmr_t trace, double a,
1117 long l_bounds[TRACE_NB_LEVELS]; /* May be too bgi for this trace */
1118 double a_divided_by_spacing;
1119 double current_spacing;
1121 DEBUG2("Solving simple integral [x=%.2f,amount=%.2f]", a, amount);
1124 if ((a < 0.0) || (amount < 0.0) || (a > trace->last_time)) {
1126 ("Error, invalid parameters [a = %.2f, amount = %.2f]. You probably have a task executing with negative computation amount. Check your code.",
1130 if (amount == 0.0) {
1131 /* fprintf(stderr,"Warning: trivial integral solve\n"); */
1135 for (i = 0; i < trace->nb_levels; i++) {
1136 a_divided_by_spacing = a / trace->levels[i]->spacing;
1137 if (ceil(a_divided_by_spacing) == a_divided_by_spacing)
1138 l_bounds[i] = 1 + (long) ceil(a_divided_by_spacing);
1140 l_bounds[i] = (long) (ceil(a_divided_by_spacing));
1142 if ((l_bounds[i] + 1) * trace->levels[i]->spacing > trace->last_time)
1145 DEBUG2("level %d: l%ld", i, l_bounds[i]);
1147 if (i == trace->nb_levels)
1148 top_level = trace->nb_levels - 1;
1154 /* first sub-level amount */
1155 next_chunk = ((l_bounds[0]) * (trace->levels[0]->spacing) - a) *
1156 (trace->levels[0]->values[l_bounds[0] - 1]);
1158 if (remains - next_chunk < 0.0) {
1159 b = a + (amount / trace->levels[0]->values[l_bounds[0] - 1]);
1161 DEBUG1("Returning sub-level[0] result %.2f", b);
1165 b = (l_bounds[0]) * (trace->levels[0]->spacing);
1166 remains -= next_chunk;
1168 DEBUG2("After sub-0 stuff: remains %.2f (b=%.2f)", remains, b);
1170 /* first n-1 levels */
1171 DEBUG0("Going up levels");
1174 for (i = 0; i < top_level; i++) {
1176 current_spacing = trace->levels[i]->spacing;
1177 index = l_bounds[i];
1181 while (double_positive
1182 (l_bounds[i + 1] * trace->levels[i + 1]->spacing -
1183 index * current_spacing)
1184 && ((index + 1) * (current_spacing) < trace->last_time)) {
1186 next_chunk = current_spacing * trace->levels[i]->values[index];
1188 DEBUG3("%.2f next_chunk= %.2f remains=%.2f",
1189 (index + 1) * (trace->levels[i]->spacing), next_chunk, remains);
1191 if (remains - next_chunk < 0.0) { /* Too far */
1194 } else { /* Keep going */
1195 DEBUG2("%.2f->%.2f|",
1196 index * (trace->levels[i]->spacing),
1197 (index + 1) * (trace->levels[i]->spacing));
1199 remains -= next_chunk;
1200 b = (index + 1) * (current_spacing);
1211 current_spacing = trace->levels[top_level]->spacing;
1212 index = l_bounds[top_level];
1214 DEBUG1("L%d:", top_level);
1216 while (index < trace->levels[top_level]->nb_points) {
1217 next_chunk = current_spacing * trace->levels[top_level]->values[index];
1218 if (remains - next_chunk <= 0.0) { /* Too far */
1221 DEBUG2("%.2f->%.2f|",
1222 index * (trace->levels[top_level]->spacing),
1223 (index + 1) * (trace->levels[top_level]->spacing));
1225 remains -= next_chunk;
1226 b = (index + 1) * (current_spacing);
1230 DEBUG2("remains = %.2f b=%.2f", remains, b);
1232 /* And going back down */
1233 DEBUG0("Going back down");
1234 for (i = top_level - 1; i >= 0; i--) {
1236 current_spacing = trace->levels[i]->spacing;
1237 index = b / (trace->levels[i]->spacing);
1241 while (index < trace->levels[i]->nb_points) {
1242 next_chunk = current_spacing * trace->levels[i]->values[index];
1243 if (remains - next_chunk <= 0.0) { /* Too far */
1246 DEBUG2("%.2f->%.2f|",
1247 index * (current_spacing), (index + 1) * (current_spacing));
1249 remains -= next_chunk;
1250 b += current_spacing;
1256 DEBUG2("remains = %.2f b=%.2f\n", remains, b);
1257 DEBUG1("Last bit index=%ld\n", index);
1259 /* Little piece at the end */
1260 b += (remains) / (trace->levels[0]->values[index]);
1265 //////////// END INTEGRAL /////////////////