Prechádzať zdrojové kódy

move linear program in a file

Andra Hugo 12 rokov pred
rodič
commit
c978226b8d

+ 10 - 0
sc_hypervisor/include/sc_hypervisor_lp.h

@@ -32,6 +32,8 @@ extern "C"
 #include <glpk.h>
 #include <glpk.h>
 #endif //STARPU_HAVE_GLPK_H
 #endif //STARPU_HAVE_GLPK_H
 
 
+struct sc_hypervisor_policy_task_pool; 
+
 /* returns 1/tmax, and computes in table res the nr of workers needed by each context st the system ends up in the smallest tmax*/
 /* returns 1/tmax, and computes in table res the nr of workers needed by each context st the system ends up in the smallest tmax*/
 double sc_hypervisor_lp_compute_nworkers_per_ctx(int nsched_ctxs, int ntypes_of_workers, double velocity[nsched_ctxs][ntypes_of_workers], double flops[nsched_ctxs], 
 double sc_hypervisor_lp_compute_nworkers_per_ctx(int nsched_ctxs, int ntypes_of_workers, double velocity[nsched_ctxs][ntypes_of_workers], double flops[nsched_ctxs], 
 				    double res[nsched_ctxs][ntypes_of_workers], int total_nw[ntypes_of_workers]);
 				    double res[nsched_ctxs][ntypes_of_workers], int total_nw[ntypes_of_workers]);
@@ -63,6 +65,14 @@ unsigned sc_hypervisor_lp_execute_dichotomy(int ns, int nw, double w_in_s[ns][nw
 					    double (*lp_estimated_distrib_func)(int ns, int nw, double draft_w_in_s[ns][nw], 
 					    double (*lp_estimated_distrib_func)(int ns, int nw, double draft_w_in_s[ns][nw], 
 									     unsigned is_integer, double tmax, void *specifc_data));
 									     unsigned is_integer, double tmax, void *specifc_data));
 
 
+#ifdef STARPU_HAVE_GLPK_H
+/* linear program that simulates a distribution of tasks that minimises the execution time of the tasks in the pool */
+double sc_hypervisor_lp_simulate_distrib_tasks(int ns, int nw, int nt, double w_in_s[ns][nw], double tasks[nw][nt],
+					       double times[nw][nt], unsigned is_integer, double tmax, int *in_sched_ctxs,
+					       struct sc_hypervisor_policy_task_pool *tmp_task_pools);
+
+#endif // STARPU_HAVE_GLPK_H
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 4 - 0
sc_hypervisor/include/sc_hypervisor_policy.h

@@ -52,6 +52,9 @@ void sc_hypervisor_policy_remove_task_from_pool(struct starpu_task *task, uint32
 /* clone a task wrapper linked list */
 /* clone a task wrapper linked list */
 struct sc_hypervisor_policy_task_pool* sc_hypervisor_policy_clone_task_pool(struct sc_hypervisor_policy_task_pool *tp);
 struct sc_hypervisor_policy_task_pool* sc_hypervisor_policy_clone_task_pool(struct sc_hypervisor_policy_task_pool *tp);
 
 
+/* get the execution time of the submitted tasks out of starpu's calibration files */
+void sc_hypervisor_get_tasks_times(int nw, int nt, double times[nw][nt], int *workers, unsigned size_ctxs, struct sc_hypervisor_policy_task_pool *task_pools);
+
 /* find the context with the lowest priority in order to move some workers */
 /* find the context with the lowest priority in order to move some workers */
 unsigned sc_hypervisor_find_lowest_prio_sched_ctx(unsigned req_sched_ctx, int nworkers_to_move);
 unsigned sc_hypervisor_find_lowest_prio_sched_ctx(unsigned req_sched_ctx, int nworkers_to_move);
 
 
@@ -97,6 +100,7 @@ int sc_hypervisor_has_velocity_gap_btw_ctxs(void);
 /* get the list of workers grouped by type */
 /* get the list of workers grouped by type */
 void sc_hypervisor_group_workers_by_type(int *workers, int nworkers, int ntypes_of_workers, int total_nw[ntypes_of_workers]);
 void sc_hypervisor_group_workers_by_type(int *workers, int nworkers, int ntypes_of_workers, int total_nw[ntypes_of_workers]);
 
 
+
 #ifdef __cplusplus
 #ifdef __cplusplus
 }
 }
 #endif
 #endif

+ 1 - 0
sc_hypervisor/src/Makefile.am

@@ -27,6 +27,7 @@ libsc_hypervisor_la_SOURCES = 				\
 	policies_utils/policy_tools.c			\
 	policies_utils/policy_tools.c			\
 	policies_utils/task_pool.c			\
 	policies_utils/task_pool.c			\
 	policies_utils/lp_tools.c			\
 	policies_utils/lp_tools.c			\
+	policies_utils/lp_programs.c			\
 	policies_utils/dichotomy.c			\
 	policies_utils/dichotomy.c			\
 	hypervisor_policies/idle_policy.c		\
 	hypervisor_policies/idle_policy.c		\
 	hypervisor_policies/app_driven_policy.c		\
 	hypervisor_policies/app_driven_policy.c		\

+ 21 - 273
sc_hypervisor/src/hypervisor_policies/teft_lp_policy.c

@@ -34,52 +34,6 @@ struct teft_lp_data
 	unsigned size_ctxs;
 	unsigned size_ctxs;
 };
 };
 
 
-static void _get_tasks_times(int nw, int nt, double times[nw][nt], int *workers, unsigned size_ctxs)
-{
-        struct sc_hypervisor_policy_task_pool *tp;
-        int w, t;
-        for (w = 0; w < nw; w++)
-        {
-                for (t = 0, tp = task_pools; tp; t++, tp = tp->next)
-                {
-			int worker = workers == NULL ? w : workers[w];
-                        enum starpu_perf_archtype arch = starpu_worker_get_perf_archtype(worker);
-                        double length = starpu_history_based_expected_perf(tp->cl->model, arch, tp->footprint);
-
-                        if (isnan(length))
-                                times[w][t] = NAN;
-			else
-			{
-                                times[w][t] = length / 1000.;
-
-				double transfer_time = 0.0;
-				enum starpu_archtype arch = starpu_worker_get_type(worker);
-				if(arch == STARPU_CUDA_WORKER)
-				{
-					unsigned worker_in_ctx = starpu_sched_ctx_contains_worker(worker, tp->sched_ctx_id);
-					if(!worker_in_ctx && !size_ctxs)
-					{
-						double transfer_velocity = starpu_get_bandwidth_RAM_CUDA(worker);
-						transfer_time +=  (tp->footprint / transfer_velocity) / 1000. ;
-					}
-					double latency = starpu_get_latency_RAM_CUDA(worker);
-					transfer_time += latency/1000.;
-
-				}
-//				printf("%d/%d %s x %d time = %lf transfer_time = %lf\n", w, tp->sched_ctx_id, tp->cl->model->symbol, tp->n, times[w][t], transfer_time);
-				times[w][t] += transfer_time;
-			}
-                }
-        }
-}
-
-
-
-/*
- * GNU Linear Programming Kit backend
- */
-#ifdef STARPU_HAVE_GLPK_H
-#include <glpk.h>
 static double _glp_resolve(int ns, int nw, double final_w_in_s[ns][nw], 
 static double _glp_resolve(int ns, int nw, double final_w_in_s[ns][nw], 
 			   unsigned is_integer, double tmax, void *specific_data)
 			   unsigned is_integer, double tmax, void *specific_data)
 {
 {
@@ -91,237 +45,23 @@ static double _glp_resolve(int ns, int nw, double final_w_in_s[ns][nw],
 	int *workers = sd->workers;
 	int *workers = sd->workers;
 	struct sc_hypervisor_policy_task_pool *tmp_task_pools = sd->tmp_task_pools;
 	struct sc_hypervisor_policy_task_pool *tmp_task_pools = sd->tmp_task_pools;
 	unsigned size_ctxs = sd->size_ctxs;
 	unsigned size_ctxs = sd->size_ctxs;
-	
-	double w_in_s[ns][nw];
-	double tasks[nw][nt];
-	
+		
 	if(tmp_task_pools == NULL)
 	if(tmp_task_pools == NULL)
 		return 0.0;
 		return 0.0;
-	struct sc_hypervisor_policy_task_pool * tp;
-	int t, w, s;
-	glp_prob *lp;
-
-	lp = glp_create_prob();
-	glp_set_prob_name(lp, "StarPU theoretical bound");
-	glp_set_obj_dir(lp, GLP_MAX);
-	glp_set_obj_name(lp, "total execution time");
-
-	{
-		double times[nw][nt];
-		int ne = nt * nw /* worker execution time */
-			+ nw * ns
-			+ nw * (nt + ns)
-			+ 1; /* glp dumbness */
-		int n = 1;
-		int ia[ne], ja[ne];
-		double ar[ne];
-
-		_get_tasks_times(nw, nt, times, workers, size_ctxs);
-
-		/* Variables: number of tasks i assigned to worker j, and tmax */
-		glp_add_cols(lp, nw*nt+ns*nw);
-#define colnum(w, t) ((t)*nw+(w)+1)
-		for(s = 0; s < ns; s++)
-			for(w = 0; w < nw; w++)
-				glp_set_obj_coef(lp, nw*nt+s*nw+w+1, 1.);
-
-		for (w = 0; w < nw; w++)
-			for (t = 0; t < nt; t++)
-			{
-				char name[32];
-				snprintf(name, sizeof(name), "w%dt%dn", w, t);
-				glp_set_col_name(lp, colnum(w, t), name);
-/* 				if (integer) */
-/*                                 { */
-/*                                         glp_set_col_kind(lp, colnum(w, t), GLP_IV); */
-/* 					glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0, 0); */
-/*                                 } */
-/* 				else */
-					glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0.0, 0.0);
-			}
-		for(s = 0; s < ns; s++)
-			for(w = 0; w < nw; w++)
-			{
-				char name[32];
-				snprintf(name, sizeof(name), "w%ds%dn", w, s);
-				glp_set_col_name(lp, nw*nt+s*nw+w+1, name);
-				if (is_integer)
-                                {
-                                        glp_set_col_kind(lp, nw*nt+s*nw+w+1, GLP_IV);
-                                        glp_set_col_bnds(lp, nw*nt+s*nw+w+1, GLP_DB, 0, 1);
-                                }
-                                else
-					glp_set_col_bnds(lp, nw*nt+s*nw+w+1, GLP_DB, 0.0, 1.0);
-			}
-
-		int *sched_ctxs = in_sched_ctxs == NULL ? sc_hypervisor_get_sched_ctxs() : in_sched_ctxs;
-
-		int curr_row_idx = 0;
-		/* Total worker execution time */
-		glp_add_rows(lp, nw*ns);
-		for (t = 0; t < nt; t++)
-		{
-			int someone = 0;
-			for (w = 0; w < nw; w++)
-				if (!isnan(times[w][t]))
-					someone = 1;
-			if (!someone)
-			{
-				/* This task does not have any performance model at all, abort */
-				printf("NO PERF MODELS\n");
-				glp_delete_prob(lp);
-				return 0.0;
-			}
-		}
-		/*sum(t[t][w]*n[t][w]) < x[s][w]*tmax */
-		for(s = 0; s < ns; s++)
-		{
-			for (w = 0; w < nw; w++)
-			{
-				char name[32], title[64];
-				starpu_worker_get_name(w, name, sizeof(name));
-				snprintf(title, sizeof(title), "worker %s", name);
-				glp_set_row_name(lp, curr_row_idx+s*nw+w+1, title);
-				for (t = 0, tp = tmp_task_pools; tp; t++, tp = tp->next)
-				{
-					if((int)tp->sched_ctx_id == sched_ctxs[s])
-					{
-						ia[n] = curr_row_idx+s*nw+w+1;
-						ja[n] = colnum(w, t);
-						if (isnan(times[w][t]))
-							ar[n] = 1000000000.;
-						else
-							ar[n] = times[w][t];
-						n++;
-					}
-				}
-				/* x[s][w] = 1 | 0 */
-				ia[n] = curr_row_idx+s*nw+w+1;
-				ja[n] = nw*nt+s*nw+w+1;
-				ar[n] = (-1) * tmax;
-				n++;
-				glp_set_row_bnds(lp, curr_row_idx+s*nw+w+1, GLP_UP, 0.0, 0.0);
-			}
-		}
-
-		curr_row_idx += nw*ns;
-
-		/* Total task completion */
-		glp_add_rows(lp, nt);
-		for (t = 0, tp = tmp_task_pools; tp; t++, tp = tp->next)
-		{
-			char name[32], title[64];
-			starpu_worker_get_name(w, name, sizeof(name));
-			snprintf(title, sizeof(title), "task %s key %x", tp->cl->name, (unsigned) tp->footprint);
-			glp_set_row_name(lp, curr_row_idx+t+1, title);
-			for (w = 0; w < nw; w++)
-			{
-				ia[n] = curr_row_idx+t+1;
-				ja[n] = colnum(w, t);
-				ar[n] = 1;
-				n++;
-			}
-			glp_set_row_bnds(lp, curr_row_idx+t+1, GLP_FX, tp->n, tp->n);
-		}
-
-		curr_row_idx += nt;
-
-		/* sum(x[s][i]) = 1 */
-		glp_add_rows(lp, nw);
-		for (w = 0; w < nw; w++)
-		{
-			char name[32], title[64];
-			starpu_worker_get_name(w, name, sizeof(name));
-			snprintf(title, sizeof(title), "w%x", w);
-			glp_set_row_name(lp, curr_row_idx+w+1, title);
-			for(s = 0; s < ns; s++)
-			{
-				ia[n] = curr_row_idx+w+1;
-				ja[n] = nw*nt+s*nw+w+1;
-				ar[n] = 1;
-				n++;
-			}
-			if(is_integer)
-                                glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1, 1);
-			else
-				glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1.0, 1.0);
-		}
-		if(n != ne)
-			printf("ns= %d nw = %d nt = %d n = %d ne = %d\n", ns, nw, nt, n, ne);
-		STARPU_ASSERT(n == ne);
-
-		glp_load_matrix(lp, ne-1, ia, ja, ar);
-	}
-
-	glp_smcp parm;
-	glp_init_smcp(&parm);
-	parm.msg_lev = GLP_MSG_OFF;
-	int ret = glp_simplex(lp, &parm);
-
-/* 	char str[50]; */
-/* 	sprintf(str, "outpu_lp_%g", tmax); */
-
-/* 	glp_print_sol(lp, str); */
-
-	if (ret)
-	{
-		printf("error in simplex\n");
-		glp_delete_prob(lp);
-		lp = NULL;
-		return 0.0;
-	}
 
 
-	int stat = glp_get_prim_stat(lp);
-	/* if we don't have a solution return */
-	if(stat == GLP_NOFEAS)
-	{
-		glp_delete_prob(lp);
-//		printf("no_sol in tmax = %lf\n", tmax);
-		lp = NULL;
-		return 0.0;
-	}
-
-
-	if (is_integer)
-        {
-                glp_iocp iocp;
-                glp_init_iocp(&iocp);
-                iocp.msg_lev = GLP_MSG_OFF;
-		glp_intopt(lp, &iocp);
-		int stat = glp_mip_status(lp);
-		/* if we don't have a solution return */
-		if(stat == GLP_NOFEAS)
-		{
-//			printf("no int sol in tmax = %lf\n", tmax);
-			glp_delete_prob(lp);
-			lp = NULL;
-			return 0.0;
-		}
-	}
-
-	double res = glp_get_obj_val(lp);
-	for (w = 0; w < nw; w++)
-		for (t = 0; t < nt; t++)
-/* 			if (integer) */
-/* 				tasks[w][t] = (double)glp_mip_col_val(lp, colnum(w, t)); */
-/*                         else */
-				tasks[w][t] = glp_get_col_prim(lp, colnum(w, t));
+	double w_in_s[ns][nw];
+	double tasks[nw][nt];
+	double times[nw][nt];
 	
 	
-//	printf("for tmax %lf\n", tmax);
-	for(s = 0; s < ns; s++)
-		for(w = 0; w < nw; w++)
-		{
-			if (is_integer)
-				w_in_s[s][w] = (double)glp_mip_col_val(lp, nw*nt+s*nw+w+1);
-                        else
-				w_in_s[s][w] = glp_get_col_prim(lp, nw*nt+s*nw+w+1);
-//			printf("w_in_s[%d][%d]=%lf\n", s, w, w_in_s[s][w]);
-		}
-//	printf("\n");
+	sc_hypervisor_get_tasks_times(nw, nt, times, workers, size_ctxs, task_pools);
 
 
-	glp_delete_prob(lp);
+	double res = 0.0;
+#ifdef STARPU_HAVE_GLPK_H
+	res = sc_hypervisor_lp_simulate_distrib_tasks(ns, nw, nt, w_in_s, tasks, times, is_integer, tmax, in_sched_ctxs, tmp_task_pools);
+#endif //STARPU_HAVE_GLPK_H
 	if(res != 0.0)
 	if(res != 0.0)
 	{
 	{
+		int s, w, t;
 		for(s = 0; s < ns; s++)
 		for(s = 0; s < ns; s++)
 			for(w = 0; w < nw; w++)
 			for(w = 0; w < nw; w++)
 				final_w_in_s[s][w] = w_in_s[s][w];
 				final_w_in_s[s][w] = w_in_s[s][w];
@@ -344,7 +84,12 @@ static void _size_ctxs(int *sched_ctxs, int nsched_ctxs , int *workers, int nwor
 		nt++;
 		nt++;
 
 
 	double w_in_s[ns][nw];
 	double w_in_s[ns][nw];
-	double tasks[nw][nt];
+//	double tasks[nw][nt];
+	double **tasks=(double**)malloc(nw*sizeof(double*));
+	int i;
+	for(i = 0; i < nw; i++)
+		tasks[i] = (double*)malloc(nt*sizeof(double));
+
 
 
 	struct teft_lp_data specific_data;
 	struct teft_lp_data specific_data;
 	specific_data.nt = nt;
 	specific_data.nt = nt;
@@ -368,6 +113,11 @@ static void _size_ctxs(int *sched_ctxs, int nsched_ctxs , int *workers, int nwor
 	/* if we did find at least one solution redistribute the resources */
 	/* if we did find at least one solution redistribute the resources */
 	if(found_sol)
 	if(found_sol)
 		sc_hypervisor_lp_place_resources_in_ctx(ns, nw, w_in_s, sched_ctxs, workers, 1);
 		sc_hypervisor_lp_place_resources_in_ctx(ns, nw, w_in_s, sched_ctxs, workers, 1);
+	
+	for(i = 0; i < nw; i++)
+		free(tasks[i]);
+	free(tasks);
+
 }
 }
 
 
 static void size_if_required()
 static void size_if_required()
@@ -507,5 +257,3 @@ struct sc_hypervisor_policy teft_lp_policy = {
 	.custom = 0,
 	.custom = 0,
 	.name = "teft_lp"
 	.name = "teft_lp"
 };
 };
-
-#endif /* STARPU_HAVE_GLPK_H */

+ 252 - 0
sc_hypervisor/src/policies_utils/lp_programs.c

@@ -0,0 +1,252 @@
+/* StarPU --- Runtime system for heterogeneous multicore architectures.
+ *
+ * Copyright (C) 2011 - 2013  INRIA
+ *
+ * StarPU is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or (at
+ * your option) any later version.
+ *
+ * StarPU is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * See the GNU Lesser General Public License in COPYING.LGPL for more details.
+ */
+/*
+ * GNU Linear Programming Kit backend
+ */
+
+#include "sc_hypervisor_policy.h"
+#include "sc_hypervisor_lp.h"
+
+#ifdef STARPU_HAVE_GLPK_H
+
+double sc_hypervisor_lp_simulate_distrib_tasks(int ns, int nw, int nt, double w_in_s[ns][nw], double tasks[nw][nt],
+					       double times[nw][nt], unsigned is_integer, double tmax, int *in_sched_ctxs,
+					       struct sc_hypervisor_policy_task_pool *tmp_task_pools)
+{
+	struct sc_hypervisor_policy_task_pool * tp;
+	int t, w, s;
+	glp_prob *lp;
+
+	lp = glp_create_prob();
+	glp_set_prob_name(lp, "StarPU theoretical bound");
+	glp_set_obj_dir(lp, GLP_MAX);
+	glp_set_obj_name(lp, "total execution time");
+
+	{
+		int ne = nt * nw /* worker execution time */
+			+ nw * ns
+			+ nw * (nt + ns)
+			+ 1; /* glp dumbness */
+		int n = 1;
+		int ia[ne], ja[ne];
+		double ar[ne];
+
+		/* Variables: number of tasks i assigned to worker j, and tmax */
+		glp_add_cols(lp, nw*nt+ns*nw);
+#define colnum(w, t) ((t)*nw+(w)+1)
+		for(s = 0; s < ns; s++)
+			for(w = 0; w < nw; w++)
+				glp_set_obj_coef(lp, nw*nt+s*nw+w+1, 1.);
+
+		for (w = 0; w < nw; w++)
+			for (t = 0; t < nt; t++)
+			{
+				char name[32];
+				snprintf(name, sizeof(name), "w%dt%dn", w, t);
+				glp_set_col_name(lp, colnum(w, t), name);
+/* 				if (integer) */
+/*                                 { */
+/*                                         glp_set_col_kind(lp, colnum(w, t), GLP_IV); */
+/* 					glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0, 0); */
+/*                                 } */
+/* 				else */
+					glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0.0, 0.0);
+			}
+		for(s = 0; s < ns; s++)
+			for(w = 0; w < nw; w++)
+			{
+				char name[32];
+				snprintf(name, sizeof(name), "w%ds%dn", w, s);
+				glp_set_col_name(lp, nw*nt+s*nw+w+1, name);
+				if (is_integer)
+                                {
+                                        glp_set_col_kind(lp, nw*nt+s*nw+w+1, GLP_IV);
+                                        glp_set_col_bnds(lp, nw*nt+s*nw+w+1, GLP_DB, 0, 1);
+                                }
+                                else
+					glp_set_col_bnds(lp, nw*nt+s*nw+w+1, GLP_DB, 0.0, 1.0);
+			}
+
+		int *sched_ctxs = in_sched_ctxs == NULL ? sc_hypervisor_get_sched_ctxs() : in_sched_ctxs;
+
+		int curr_row_idx = 0;
+		/* Total worker execution time */
+		glp_add_rows(lp, nw*ns);
+		for (t = 0; t < nt; t++)
+		{
+			int someone = 0;
+			for (w = 0; w < nw; w++)
+				if (!isnan(times[w][t]))
+					someone = 1;
+			if (!someone)
+			{
+				/* This task does not have any performance model at all, abort */
+				printf("NO PERF MODELS\n");
+				glp_delete_prob(lp);
+				return 0.0;
+			}
+		}
+		/*sum(t[t][w]*n[t][w]) < x[s][w]*tmax */
+		for(s = 0; s < ns; s++)
+		{
+			for (w = 0; w < nw; w++)
+			{
+				char name[32], title[64];
+				starpu_worker_get_name(w, name, sizeof(name));
+				snprintf(title, sizeof(title), "worker %s", name);
+				glp_set_row_name(lp, curr_row_idx+s*nw+w+1, title);
+				for (t = 0, tp = tmp_task_pools; tp; t++, tp = tp->next)
+				{
+					if((int)tp->sched_ctx_id == sched_ctxs[s])
+					{
+						ia[n] = curr_row_idx+s*nw+w+1;
+						ja[n] = colnum(w, t);
+						if (isnan(times[w][t]))
+							ar[n] = 1000000000.;
+						else
+							ar[n] = times[w][t];
+						n++;
+					}
+				}
+				/* x[s][w] = 1 | 0 */
+				ia[n] = curr_row_idx+s*nw+w+1;
+				ja[n] = nw*nt+s*nw+w+1;
+				ar[n] = (-1) * tmax;
+				n++;
+				glp_set_row_bnds(lp, curr_row_idx+s*nw+w+1, GLP_UP, 0.0, 0.0);
+			}
+		}
+
+		curr_row_idx += nw*ns;
+
+		/* Total task completion */
+		glp_add_rows(lp, nt);
+		for (t = 0, tp = tmp_task_pools; tp; t++, tp = tp->next)
+		{
+			char name[32], title[64];
+			starpu_worker_get_name(w, name, sizeof(name));
+			snprintf(title, sizeof(title), "task %s key %x", tp->cl->name, (unsigned) tp->footprint);
+			glp_set_row_name(lp, curr_row_idx+t+1, title);
+			for (w = 0; w < nw; w++)
+			{
+				ia[n] = curr_row_idx+t+1;
+				ja[n] = colnum(w, t);
+				ar[n] = 1;
+				n++;
+			}
+			glp_set_row_bnds(lp, curr_row_idx+t+1, GLP_FX, tp->n, tp->n);
+		}
+
+		curr_row_idx += nt;
+
+		/* sum(x[s][i]) = 1 */
+		glp_add_rows(lp, nw);
+		for (w = 0; w < nw; w++)
+		{
+			char name[32], title[64];
+			starpu_worker_get_name(w, name, sizeof(name));
+			snprintf(title, sizeof(title), "w%x", w);
+			glp_set_row_name(lp, curr_row_idx+w+1, title);
+			for(s = 0; s < ns; s++)
+			{
+				ia[n] = curr_row_idx+w+1;
+				ja[n] = nw*nt+s*nw+w+1;
+				ar[n] = 1;
+				n++;
+			}
+			if(is_integer)
+                                glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1, 1);
+			else
+				glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1.0, 1.0);
+		}
+		if(n != ne)
+			printf("ns= %d nw = %d nt = %d n = %d ne = %d\n", ns, nw, nt, n, ne);
+		STARPU_ASSERT(n == ne);
+
+		glp_load_matrix(lp, ne-1, ia, ja, ar);
+	}
+
+	glp_smcp parm;
+	glp_init_smcp(&parm);
+	parm.msg_lev = GLP_MSG_OFF;
+	int ret = glp_simplex(lp, &parm);
+
+/* 	char str[50]; */
+/* 	sprintf(str, "outpu_lp_%g", tmax); */
+
+/* 	glp_print_sol(lp, str); */
+
+	if (ret)
+	{
+		printf("error in simplex\n");
+		glp_delete_prob(lp);
+		lp = NULL;
+		return 0.0;
+	}
+
+	int stat = glp_get_prim_stat(lp);
+	/* if we don't have a solution return */
+	if(stat == GLP_NOFEAS)
+	{
+		glp_delete_prob(lp);
+//		printf("no_sol in tmax = %lf\n", tmax);
+		lp = NULL;
+		return 0.0;
+	}
+
+
+	if (is_integer)
+        {
+                glp_iocp iocp;
+                glp_init_iocp(&iocp);
+                iocp.msg_lev = GLP_MSG_OFF;
+		glp_intopt(lp, &iocp);
+		int stat = glp_mip_status(lp);
+		/* if we don't have a solution return */
+		if(stat == GLP_NOFEAS)
+		{
+//			printf("no int sol in tmax = %lf\n", tmax);
+			glp_delete_prob(lp);
+			lp = NULL;
+			return 0.0;
+		}
+	}
+
+	double res = glp_get_obj_val(lp);
+	for (w = 0; w < nw; w++)
+		for (t = 0; t < nt; t++)
+/* 			if (integer) */
+/* 				tasks[w][t] = (double)glp_mip_col_val(lp, colnum(w, t)); */
+/*                         else */
+				tasks[w][t] = glp_get_col_prim(lp, colnum(w, t));
+	
+//	printf("for tmax %lf\n", tmax);
+	for(s = 0; s < ns; s++)
+		for(w = 0; w < nw; w++)
+		{
+			if (is_integer)
+				w_in_s[s][w] = (double)glp_mip_col_val(lp, nw*nt+s*nw+w+1);
+                        else
+				w_in_s[s][w] = glp_get_col_prim(lp, nw*nt+s*nw+w+1);
+//			printf("w_in_s[%d][%d]=%lf\n", s, w, w_in_s[s][w]);
+		}
+//	printf("\n");
+
+	glp_delete_prob(lp);
+	return res;
+}
+
+#endif // STARPU_HAVE_GLPK_H

+ 40 - 0
sc_hypervisor/src/policies_utils/policy_tools.c

@@ -588,3 +588,43 @@ void sc_hypervisor_group_workers_by_type(int *workers, int nworkers, int ntypes_
 			total_nw[0]++;
 			total_nw[0]++;
 	}
 	}
 }
 }
+
+void sc_hypervisor_get_tasks_times(int nw, int nt, double times[nw][nt], int *workers, unsigned size_ctxs, struct sc_hypervisor_policy_task_pool *task_pools)
+{
+        struct sc_hypervisor_policy_task_pool *tp;
+        int w, t;
+        for (w = 0; w < nw; w++)
+        {
+                for (t = 0, tp = task_pools; tp; t++, tp = tp->next)
+                {
+			int worker = workers == NULL ? w : workers[w];
+                        enum starpu_perf_archtype arch = starpu_worker_get_perf_archtype(worker);
+                        double length = starpu_history_based_expected_perf(tp->cl->model, arch, tp->footprint);
+
+                        if (isnan(length))
+                                times[w][t] = NAN;
+			else
+			{
+                                times[w][t] = length / 1000.;
+
+				double transfer_time = 0.0;
+				enum starpu_archtype arch = starpu_worker_get_type(worker);
+				if(arch == STARPU_CUDA_WORKER)
+				{
+					unsigned worker_in_ctx = starpu_sched_ctx_contains_worker(worker, tp->sched_ctx_id);
+					if(!worker_in_ctx && !size_ctxs)
+					{
+						double transfer_velocity = starpu_get_bandwidth_RAM_CUDA(worker);
+						transfer_time +=  (tp->footprint / transfer_velocity) / 1000. ;
+					}
+					double latency = starpu_get_latency_RAM_CUDA(worker);
+					transfer_time += latency/1000.;
+
+				}
+//				printf("%d/%d %s x %d time = %lf transfer_time = %lf\n", w, tp->sched_ctx_id, tp->cl->model->symbol, tp->n, times[w][t], transfer_time);
+				times[w][t] += transfer_time;
+			}
+                }
+        }
+}
+