|
@@ -19,44 +19,56 @@
|
|
|
#include <starpu.h>
|
|
|
#include <sched_ctx_hypervisor.h>
|
|
|
|
|
|
+#define NTASKS 1000
|
|
|
+#define NINCR 10
|
|
|
#define FPRINTF(ofile, fmt, args ...) do { if (!getenv("STARPU_SSILENT")) {fprintf(ofile, fmt, ##args); }} while(0)
|
|
|
|
|
|
-/* Every implementation of a codelet must have this prototype, the first * argument (buffers) describes the buffers/streams that are managed by the
|
|
|
- * DSM; the second arguments references read-only data that is passed as an
|
|
|
- * argument of the codelet (task->cl_arg). Here, "buffers" is unused as there
|
|
|
- * are no data input/output managed by the DSM (cl.nbuffers = 0) */
|
|
|
struct params
|
|
|
{
|
|
|
unsigned sched_ctx;
|
|
|
- int task_tag;
|
|
|
+ int task_tag;
|
|
|
};
|
|
|
|
|
|
+unsigned val[2];
|
|
|
+pthread_mutex_t mut[2];
|
|
|
+
|
|
|
+/* Every implementation of a codelet must have this prototype, the first * argument (buffers) describes the buffers/streams that are managed by the
|
|
|
+ * DSM; the second arguments references read-only data that is passed as an
|
|
|
+ * argument of the codelet (task->cl_arg). Here, "buffers" is unused as there
|
|
|
+ * are no data input/output managed by the DSM (cl.nbuffers = 0) */
|
|
|
+
|
|
|
void cpu_func(void *buffers[], void *cl_arg)
|
|
|
{
|
|
|
struct params *params = (struct params *) cl_arg;
|
|
|
|
|
|
int i;
|
|
|
- for(i = 0; i < 1000; i++);
|
|
|
- FPRINTF(stdout, "Hello world sched_ctx = %d task_tag = %d \n", params->sched_ctx, params->task_tag);
|
|
|
+ for(i = 0; i < NINCR; i++)
|
|
|
+ {
|
|
|
+ pthread_mutex_lock(&mut[params->sched_ctx - 1]);
|
|
|
+ val[params->sched_ctx - 1]++;
|
|
|
+ pthread_mutex_unlock(&mut[params->sched_ctx - 1]);
|
|
|
+ }
|
|
|
+ if(params->task_tag != 0)
|
|
|
+ FPRINTF(stdout, "Task with tag %d executed in ctx = %d %d counter_tests\n", params->task_tag, params->sched_ctx, val[params->sched_ctx - 1]);
|
|
|
}
|
|
|
|
|
|
-struct starpu_codelet cl = {};
|
|
|
+struct starpu_codelet cl = {0};
|
|
|
|
|
|
+/* the management of the tags is done by the user */
|
|
|
+/* who will take care that the tags will be unique */
|
|
|
int tag = 1;
|
|
|
-void* start_thread(void *arg)
|
|
|
+void* submit_tasks_thread(void *arg)
|
|
|
{
|
|
|
unsigned sched_ctx = *((unsigned*)arg);
|
|
|
starpu_sched_ctx_set_context(&sched_ctx);
|
|
|
|
|
|
- struct starpu_task *task[10];
|
|
|
- struct params params[10];
|
|
|
+ struct starpu_task *task[NTASKS];
|
|
|
+ struct params params[NTASKS];
|
|
|
int i;
|
|
|
- for(i = 0; i < 10; i++)
|
|
|
+ for(i = 0; i < NTASKS; i++)
|
|
|
{
|
|
|
- int j;
|
|
|
- for(j = 0; j < 1000; j++);
|
|
|
task[i] = starpu_task_create();
|
|
|
-
|
|
|
+// usleep(5000);
|
|
|
cl.cpu_funcs[0] = cpu_func;
|
|
|
cl.nbuffers = 0;
|
|
|
|
|
@@ -64,13 +76,18 @@ void* start_thread(void *arg)
|
|
|
|
|
|
if(sched_ctx == 1 && i == 5)
|
|
|
{
|
|
|
+ /* tag the tasks whose execution will start the resizing process */
|
|
|
task[i]->hypervisor_tag = tag;
|
|
|
+ /* indicate particular settings the context should have when the
|
|
|
+ resizing will be done */
|
|
|
sched_ctx_hypervisor_ioctl(sched_ctx,
|
|
|
HYPERVISOR_TIME_TO_APPLY, tag,
|
|
|
HYPERVISOR_MIN_WORKERS, 2,
|
|
|
HYPERVISOR_MAX_WORKERS, 12,
|
|
|
HYPERVISOR_NULL);
|
|
|
printf("require resize for sched_ctx %d at tag %d\n", sched_ctx, tag);
|
|
|
+ /* specify that the contexts should be resized when the task having this
|
|
|
+ particular tag will finish executing */
|
|
|
sched_ctx_hypervisor_resize(sched_ctx, tag);
|
|
|
}
|
|
|
|
|
@@ -84,6 +101,7 @@ void* start_thread(void *arg)
|
|
|
}
|
|
|
|
|
|
starpu_task_wait_for_all();
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
int main()
|
|
@@ -104,27 +122,49 @@ int main()
|
|
|
for(i = 0; i < nres2; i++)
|
|
|
ressources2[i] = nres1+i;
|
|
|
|
|
|
- unsigned sched_ctx1 = starpu_sched_ctx_create("heft", ressources1, nres1, "sched_ctx1");
|
|
|
- unsigned sched_ctx2 = starpu_sched_ctx_create("heft", ressources2, nres2, "sched_ctx2");
|
|
|
+ /* create contexts */
|
|
|
+ unsigned sched_ctx1 = starpu_sched_ctx_create("dmda", ressources1, nres1, "sched_ctx1");
|
|
|
+ unsigned sched_ctx2 = starpu_sched_ctx_create("dmda", ressources2, nres2, "sched_ctx2");
|
|
|
|
|
|
+ /* initialize the hypervisor */
|
|
|
struct sched_ctx_hypervisor_policy policy;
|
|
|
policy.custom = 0;
|
|
|
+ /* indicate which strategy to use
|
|
|
+ in this particular case we use app_driven which allows the user to resize
|
|
|
+ the ctxs dynamically at particular moments of the execution of the application */
|
|
|
policy.name = "app_driven";
|
|
|
void *perf_counters = sched_ctx_hypervisor_init(&policy);
|
|
|
|
|
|
+ /* let starpu know which performance counters should use
|
|
|
+ to inform the hypervisor how the application and the resources are executing */
|
|
|
starpu_sched_ctx_set_perf_counters(sched_ctx1, (struct starpu_sched_ctx_performance_counters*)perf_counters);
|
|
|
starpu_sched_ctx_set_perf_counters(sched_ctx2, (struct starpu_sched_ctx_performance_counters*)perf_counters);
|
|
|
+
|
|
|
+ /* register the contexts that should be managed by the hypervisor
|
|
|
+ and indicate an approximate amount of workload if known;
|
|
|
+ in this case we don't know it and we put 0 */
|
|
|
sched_ctx_hypervisor_register_ctx(sched_ctx1, 0.0);
|
|
|
sched_ctx_hypervisor_register_ctx(sched_ctx2, 0.0);
|
|
|
|
|
|
starpu_pthread_t tid[2];
|
|
|
|
|
|
- starpu_pthread_create(&tid[0], NULL, start_thread, (void*)&sched_ctx1);
|
|
|
- starpu_pthread_create(&tid[1], NULL, start_thread, (void*)&sched_ctx2);
|
|
|
+ val[0] = 0;
|
|
|
+ val[1] = 0;
|
|
|
+ pthread_mutex_init(&mut[0], NULL);
|
|
|
+ pthread_mutex_init(&mut[1], NULL);
|
|
|
+
|
|
|
+ /* we create two threads to simulate simultaneous submission of tasks */
|
|
|
+ starpu_pthread_create(&tid[0], NULL, submit_tasks_thread, (void*)&sched_ctx1);
|
|
|
+ starpu_pthread_create(&tid[1], NULL, submit_tasks_thread, (void*)&sched_ctx2);
|
|
|
|
|
|
starpu_pthread_join(tid[0], NULL);
|
|
|
starpu_pthread_join(tid[1], NULL);
|
|
|
|
|
|
+ /* free starpu and hypervisor data */
|
|
|
starpu_shutdown();
|
|
|
sched_ctx_hypervisor_shutdown();
|
|
|
+
|
|
|
+ FPRINTF(stdout, "ctx = %d executed %d counter_tests out of %d \n", sched_ctx1, val[0], NTASKS*NINCR);
|
|
|
+ FPRINTF(stdout, "ctx = %d executed %d counter_tests out of %d \n", sched_ctx2, val[1], NTASKS*NINCR);
|
|
|
+ return 0;
|
|
|
}
|