@c -*-texinfo-*-

@c This file is part of the StarPU Handbook.
@c Copyright (C) 2011--2013 Institut National de Recherche en Informatique et Automatique
@c See the file starpu.texi for copying conditions.

@cindex Scheduling Context Hypervisor

@menu
* What is the Hypervisor::
* Start the Hypervisor::
* Interrogate the runtime::
* Trigger the Hypervisor::
* Resizing strategies::
@end menu

@node What is the Hypervisor 
@section What is the Hypervisor
StarPU proposes a platform for constructing Scheduling Contexts, for deleting and modifying them dynamically.
A parallel kernel, can thus be isolated into a scheduling context and interferences between several parallel kernels are avoided.
If the user knows exactly how many workers each scheduling context needs, he can assign them to the contexts at their creation time or modify them during the execution of the program.

The Scheduling Context Hypervisor Plugin is available for the users who do not dispose of a regular parallelism, who cannot know in advance the exact size of the context and need to resize the contexts according to the behavior of the parallel kernels.
The Hypervisor receives information from StarPU concerning the execution of the tasks, the efficiency of the resources, etc. and it decides accordingly when and how the contexts can be resized.
Basic strategies of resizing scheduling contexts already exist but a platform for implementing additional custom ones is available.

@node Start the Hypervisor
@section Start the Hypervisor
The Hypervisor must be initialised once at the beging of the application. At this point a resizing policy should be indicated. This strategy depends on the information the application is able to provide to the hypervisor as well
as on the accuracy needed for the resizing procedure. For exemple, the application may be able to provide an estimation of the workload of the contexts. In this situation the hypervisor may decide what resources the contexts need.
However, if no information is provided the hypervisor evaluates the behavior of the resources and of the application and makes a guess about the future.
The hypervisor resizes only the registered contexts.

@node Interrogate the runtime
@section Interrrogate the runtime
The runtime provides the hypervisor with information concerning the behavior of the resources and the application. This is done by using the performance_counters, some callbacks indicating when the resources are idle or not efficient, when the application submits tasks or when it becames to slow. 

@node Trigger the Hypervisor
@section Trigger the Hypervisor
The resizing is triggered either when the application requires it or when the initials distribution of resources alters the performance of the application( the application is to slow or the resource are idle for too long time, threashold indicated by the user). When this happens different resizing strategy are applied that target minimising the total execution of the application, the instant speed or the idle time of the resources.

@node Resizing strategies
@section Resizing strategies

The plugin proposes several strategies for resizing the scheduling context.

The @b{Application driven} strategy uses the user's input concerning the moment when he wants to resize the contexts.
Thus, the users tags the task that should trigger the resizing process. We can set directly the corresponding field in the @code{starpu_task} data structure is @code{hypervisor_tag} or
use the macro @code{STARPU_HYPERVISOR_TAG} in @code{starpu_insert_task} function.

@cartouche
@smallexample
task.hypervisor_tag = 2;
@end smallexample
@end cartouche

or

@cartouche
@smallexample
starpu_insert_task(&codelet,
		    ...,
		    STARPU_HYPERVISOR_TAG, 2,
                    0);
@end smallexample
@end cartouche

Then the user has to indicate that when a task with the specified tag is executed the contexts should resize.

@cartouche
@smallexample
sc_hypervisor_resize(sched_ctx, 2);
@end smallexample
@end cartouche

The user can use the same tag to change the resizing configuration of the contexts if he considers it necessary.
@cartouche
@smallexample
sc_hypervisor_ioctl(sched_ctx,
                    HYPERVISOR_MIN_WORKERS, 6,
                    HYPERVISOR_MAX_WORKERS, 12,
                    HYPERVISOR_TIME_TO_APPLY, 2,
                    NULL);
@end smallexample
@end cartouche


The @b{Idleness} based strategy resizes the scheduling contexts every time one of their workers stays idle
for a period longer than the one imposed by the user (see @pxref{The user's input in the resizing process})

@cartouche
@smallexample
int workerids[3] = @{1, 3, 10@};
int workerids2[9] = @{0, 2, 4, 5, 6, 7, 8, 9, 11@};
sc_hypervisor_ioctl(sched_ctx_id,
            HYPERVISOR_MAX_IDLE, workerids, 3, 10000.0,
            HYPERVISOR_MAX_IDLE, workerids2, 9, 50000.0,
            NULL);
@end smallexample
@end cartouche

The @b{Gflops rate} based strategy resizes the scheduling contexts such that they all finish at the same time.
The velocity of each of them is considered and once one of them is significantly slower the resizing process is triggered.
In order to do these computations the user has to input the total number of instructions needed to be executed by the
parallel kernels and the number of instruction to be executed by each task.
The number of flops to be executed by a context are passed as parameter when they are registered to the hypervisor,
 (@code{sc_hypervisor_register_ctx(sched_ctx_id, flops)}) and the one to be executed by each task are passed when the task is submitted.
The corresponding field in the @code{starpu_task} data structure is @code{flops} and
the corresponding macro in @code{starpu_insert_task} function is
@code{STARPU_FLOPS} (but take care of passing a double, not an integer, otherwise
parameter passing will be bogus). When the task is executed
the resizing process is triggered.
@cartouche
@smallexample
task.flops = 100;
@end smallexample
@end cartouche

or

@cartouche
@smallexample
starpu_insert_task(&codelet,
                    ...,
                    STARPU_FLOPS, (double) 100,
                    0);
@end smallexample
@end cartouche


