Parcourir la source

introduce min max as a constraint for the linear program

Andra Hugo il y a 11 ans
Parent
commit
9502f53f25

+ 2 - 0
sc_hypervisor/include/sc_hypervisor.h

@@ -128,6 +128,8 @@ void sc_hypervisor_update_diff_total_flops(unsigned sched_ctx, double diff_total
 /* change dynamically the number of the elapsed flops in a context, modify the past in order to better compute the speed */
 void sc_hypervisor_update_diff_elapsed_flops(unsigned sched_ctx, double diff_task_flops);
 
+/* updates the min and max workers needed by each context */
+	void sc_hypervisor_update_resize_interval(unsigned *sched_ctxs, int nsched_ctxs);
 #ifdef __cplusplus
 }
 #endif

+ 1 - 1
sc_hypervisor/include/sc_hypervisor_lp.h

@@ -65,7 +65,7 @@ unsigned sc_hypervisor_lp_execute_dichotomy(int ns, int nw, double w_in_s[ns][nw
 /* linear program that 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_simulate_distrib_flops(int nsched_ctxs, int ntypes_of_workers, double speed[nsched_ctxs][ntypes_of_workers], 
-					       double flops[nsched_ctxs], double res[nsched_ctxs][ntypes_of_workers], int total_nw[ntypes_of_workers]);
+					       double flops[nsched_ctxs], double res[nsched_ctxs][ntypes_of_workers], int total_nw[ntypes_of_workers], unsigned sched_ctxs[nsched_ctxs]);
 
 /* 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],

+ 1 - 0
sc_hypervisor/src/hypervisor_policies/feft_lp_policy.c

@@ -73,6 +73,7 @@ static void feft_lp_handle_poped_task(__attribute__((unused))unsigned sched_ctx,
 				_try_resizing(NULL, -1, NULL, -1);
 			}
 		}
+	
 		starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
 	}
 

+ 72 - 9
sc_hypervisor/src/policies_utils/lp_programs.c

@@ -249,14 +249,14 @@ double sc_hypervisor_lp_simulate_distrib_tasks(int ns, int nw, int nt, double w_
 	return res;
 }
 
-double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw], double flops[ns], double res[ns][nw], int  total_nw[nw])
+double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw], double flops[ns], double res[ns][nw], int  total_nw[nw], unsigned sched_ctxs[ns])
 {
 	int integer = 1;
 	int s, w;
 	glp_prob *lp;
 
-	int ne =
-		(ns*nw+1)*(ns+nw)
+	int ne = //ns * (nw*ns + 1) +
+		(ns*nw+1)*(2*ns+nw)
 		+ 1; /* glp dumbness */
 	int n = 1;
 	int ia[ne], ja[ne];
@@ -338,6 +338,69 @@ double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw],
 		n++;
 	}
 
+	/* one row corresponds to one ctx*/
+	glp_add_rows(lp, ns);
+
+	for(s = 0; s < ns; s++)
+	{
+		struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(sched_ctxs[s]);
+		char name[32];
+		snprintf(name, sizeof(name), "ctx%d", s);
+		glp_set_row_name(lp, ns+s+1, name);
+		glp_set_row_bnds(lp, ns+s+1, GLP_LO, 0., 0.);
+		
+
+		int s2;
+		for(s2 = 0; s2 < ns; s2++)
+		{
+			if(s2 == s)
+			{
+
+				for(w = 0; w < nw; w++)
+				{
+					/* only for CPUs for now */
+					if(w == 0)
+					{
+						ia[n] = ns+s+1;
+						ja[n] = w+s2*nw + 1;
+						ar[n] = 1.0;
+//					printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
+					}
+					else
+					{
+						ia[n] = ns+s+1;
+						ja[n] = w+s2*nw + 1;
+						ar[n] = 0.0;
+//					printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
+
+					}
+					n++;
+				}
+			}
+			else
+			{
+				for(w = 0; w < nw; w++)
+				{
+
+					ia[n] = ns+s+1;
+					ja[n] = w+s2*nw + 1;
+					ar[n] = 0.0;
+//					printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
+					n++;
+				}
+				
+			}
+				
+		}
+		ia[n] = ns+s+1;
+		ja[n] = ns*nw+1;
+		ar[n] = 0.0;
+		n++;
+		
+		glp_set_row_bnds(lp, ns+s+1, GLP_UP, config->min_nworkers, config->max_nworkers);
+
+	}
+
 	/*we add another linear constraint : sum(all cpus) = 9 and sum(all gpus) = 3 */
 	glp_add_rows(lp, nw);
 
@@ -345,7 +408,7 @@ double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw],
 	{
 		char name[32];
 		snprintf(name, sizeof(name), "w%d", w);
-		glp_set_row_name(lp, ns+w+1, name);
+		glp_set_row_name(lp, 2*ns+w+1, name);
 		for(s = 0; s < ns; s++)
 		{
 			int w2;
@@ -353,14 +416,14 @@ double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw],
 			{
 				if(w2 == w)
 				{
-					ia[n] = ns+w+1;
+					ia[n] = 2*ns+w+1;
 					ja[n] = w2+s*nw + 1;
 					ar[n] = 1.0;
 //					printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
 				}
 				else
 				{
-					ia[n] = ns+w+1;
+					ia[n] = 2*ns+w+1;
 					ja[n] = w2+s*nw + 1;
 					ar[n] = 0.0;
 //					printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
@@ -369,7 +432,7 @@ double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw],
 			}
 		}
 		/* 1/tmax */
-		ia[n] = ns+w+1;
+		ia[n] = 2*ns+w+1;
 		ja[n] = ns*nw+1;
 		ar[n] = 0.0;
 //		printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
@@ -377,11 +440,11 @@ double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw],
 
 		/*sum(all gpus) = 3*/
 		if(w == 0)
-			glp_set_row_bnds(lp, ns+w+1, GLP_FX, total_nw[0], total_nw[0]);
+			glp_set_row_bnds(lp, 2*ns+w+1, GLP_FX, total_nw[0], total_nw[0]);
 
 		/*sum(all cpus) = 9*/
 		if(w == 1)
-			glp_set_row_bnds(lp, ns+w+1, GLP_FX, total_nw[1], total_nw[1]);
+			glp_set_row_bnds(lp, 2*ns+w+1, GLP_FX, total_nw[1], total_nw[1]);
 	}
 
 	STARPU_ASSERT(n == ne);

+ 5 - 2
sc_hypervisor/src/policies_utils/lp_tools.c

@@ -28,6 +28,8 @@ double sc_hypervisor_lp_get_nworkers_per_ctx(int nsched_ctxs, int ntypes_of_work
 	double v[nsched_ctxs][ntypes_of_workers];
 	double flops[nsched_ctxs];
 
+	sc_hypervisor_update_resize_interval(sched_ctxs, nsched_ctxs);
+
 	int nw = tw->nw;
 	int i = 0;
 	struct sc_hypervisor_wrapper* sc_w;
@@ -59,8 +61,9 @@ double sc_hypervisor_lp_get_nworkers_per_ctx(int nsched_ctxs, int ntypes_of_work
 /* 		printf("%d: flops %lf remaining flops %lf ready flops %lf nready_tasks %d\n", */
 /* 		       sched_ctxs[i], flops[i], sc_w->remaining_flops/1000000000, sc_w->ready_flops/1000000000, sc_w->nready_tasks); */
 	}
-
-	double vmax = 1/sc_hypervisor_lp_simulate_distrib_flops(nsched_ctxs, ntypes_of_workers, v, flops, res, total_nw);
+		
+	
+	double vmax = 1/sc_hypervisor_lp_simulate_distrib_flops(nsched_ctxs, ntypes_of_workers, v, flops, res, total_nw, sched_ctxs);
 	double optimal_v = 0.0;
 	for(i = 0; i < nsched_ctxs; i++)
 	{

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

@@ -465,6 +465,7 @@ unsigned sc_hypervisor_check_idle(unsigned sched_ctx, int worker)
 	struct sc_hypervisor_policy_config *config = sc_w->config;
 	if(config != NULL)
 	{
+		printf("w%d/ctx%d: current idle %lf max_idle %lf\n", worker, sched_ctx, sc_w->current_idle_time[worker], config->max_idle[worker]);
 		if(sc_w->current_idle_time[worker] > config->max_idle[worker])
 		{
 			sc_w->current_idle_time[worker] = 0.0;

+ 19 - 0
sc_hypervisor/src/policies_utils/speed.c

@@ -188,6 +188,25 @@ double sc_hypervisor_get_speed(struct sc_hypervisor_wrapper *sc_w, enum starpu_w
 {
 	/* monitored speed in the last frame */
 	double speed = sc_hypervisor_get_speed_per_worker_type(sc_w, arch);
+/* 	if(speed != -1.0 && arch == STARPU_CPU_WORKER) */
+/* 	{ */
+/* 		struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(sc_w->sched_ctx); */
+/* 		double ratio = speed / SC_HYPERVISOR_DEFAULT_CPU_SPEED; */
+/* 		if(ratio < 0.3) */
+/* 		{ */
+/* 			if(config->max_nworkers > 0) */
+/* 				config->max_nworkers--; */
+/* 			printf("%d: ratio %lf max_nworkers descr %d \n", sc_w->sched_ctx, ratio, config->max_nworkers); */
+/* 		} */
+/* 		if(ratio > 0.9) */
+/* 		{ */
+/* 			int max_cpus = starpu_cpu_worker_get_count(); */
+/* 			if(config->max_nworkers < max_cpus) */
+/* 				config->max_nworkers++; */
+/* 			printf("%d: ratio %lf max_nworkers incr %d \n",  sc_w->sched_ctx, ratio, config->max_nworkers); */
+/* 		} */
+/* 	} */
+
 	if(speed == -1.0)
 	{
 		/* avg value of the monitored speed over the entier current execution */

+ 1 - 1
sc_hypervisor/src/sc_config.c

@@ -74,7 +74,7 @@ void _add_config(unsigned sched_ctx)
 {
 	struct sc_hypervisor_policy_config *config = _create_config();
 	config->min_nworkers = 0;
-	config->max_nworkers = STARPU_NMAXWORKERS;
+	config->max_nworkers = starpu_worker_get_count();
 	config->new_workers_max_idle = MAX_IDLE_TIME;
 
 	int i;

+ 135 - 2
sc_hypervisor/src/sc_hypervisor.c

@@ -763,6 +763,114 @@ void sc_hypervisor_resize_ctxs(unsigned *sched_ctxs, int nsched_ctxs , int *work
 		hypervisor.policy.resize_ctxs(sched_ctxs, nsched_ctxs, workers, nworkers);
 }
 
+void sc_hypervisor_update_resize_interval(unsigned *sched_ctxs, int nsched_ctxs)
+{
+	unsigned sched_ctx;
+	int total_max_nworkers = 0;
+	int max_cpus = starpu_cpu_worker_get_count();
+	double max_workers_idle_time[nsched_ctxs];
+	unsigned configured = 0;
+	int i;
+	for(i = 0; i < nsched_ctxs; i++)
+	{
+		sched_ctx = sched_ctxs[i];
+
+		if(hypervisor.sched_ctx_w[sched_ctx].to_be_sized) continue;
+
+		struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(sched_ctx);
+		struct starpu_worker_collection *workers = starpu_sched_ctx_get_worker_collection(sched_ctx);
+		int worker;
+		
+		struct starpu_sched_ctx_iterator it;
+		if(workers->init_iterator)
+			workers->init_iterator(workers, &it);
+		
+		max_workers_idle_time[i] = 0.0;
+		while(workers->has_next(workers, &it))
+		{
+			worker = workers->get_next(workers, &it);
+			if(hypervisor.sched_ctx_w[sched_ctx].idle_start_time[worker]==0.0)
+			{
+//				if(max_workers_idle_time[i] < hypervisor.sched_ctx_w[sched_ctx].idle_time[worker])
+					max_workers_idle_time[i] += hypervisor.sched_ctx_w[sched_ctx].idle_time[worker]; /* in seconds */
+			}
+			else
+			{
+				double end_time  = starpu_timing_now();
+				double idle = (end_time - hypervisor.sched_ctx_w[sched_ctx].idle_start_time[worker]) / 1000000.0; /* in seconds */ 
+				//if(max_workers_idle_time[i] < idle)
+					max_workers_idle_time[i] += idle;
+			}				
+		}			
+
+		if(hypervisor.sched_ctx_w[sched_ctx].nready_tasks < config->max_nworkers || hypervisor.sched_ctx_w[sched_ctx].nready_tasks == 0)
+		{
+			double curr_time = starpu_timing_now();
+			double elapsed_time = (curr_time - hypervisor.sched_ctx_w[sched_ctx].start_time) / 1000000.0; /* in seconds */
+			double norm_idle_time = max_workers_idle_time[i] / elapsed_time;
+
+			config->max_nworkers = 	workers->nworkers - lrint(norm_idle_time);
+			printf("%d: few tasks %d idle %lf norme_idle_time %lf nworkers %d decr %d \n", sched_ctx, hypervisor.sched_ctx_w[sched_ctx].nready_tasks, max_workers_idle_time[i], norm_idle_time, workers->nworkers, config->max_nworkers);
+		}
+		else
+		{			
+			if(max_workers_idle_time[i] > 0.000002)
+			{
+				if(config->max_nworkers > 0)
+					config->max_nworkers--;
+				printf("%d: idle for long time %lf max_nworkers decr %d \n", sched_ctx, max_workers_idle_time[i], config->max_nworkers);
+			}
+			else
+			{
+				config->max_nworkers = ((workers->nworkers + hypervisor.sched_ctx_w[sched_ctx].nready_tasks) > max_cpus) 
+					? max_cpus : (workers->nworkers + hypervisor.sched_ctx_w[sched_ctx].nready_tasks);
+				printf("%d: max_nworkers incr %d \n",  sched_ctx, config->max_nworkers);
+				
+			}
+		}
+
+		total_max_nworkers += config->max_nworkers;
+		configured = 1;
+	}
+	if(configured && total_max_nworkers < max_cpus)
+	{
+		int diff = max_cpus - total_max_nworkers;
+		double min_idle = max_workers_idle_time[0];
+		unsigned min_idle_sched_ctx = sched_ctxs[0];
+		
+		/* try to find one that has some ready tasks */
+		for(i = 1; i < nsched_ctxs; i++)
+		{
+			if(hypervisor.sched_ctx_w[sched_ctx].nready_tasks != 0)
+			{
+				if(max_workers_idle_time[i] < min_idle || 
+				   (min_idle_sched_ctx == sched_ctxs[0] && hypervisor.sched_ctx_w[sched_ctxs[0]].nready_tasks == 0))
+				{
+					min_idle = max_workers_idle_time[i];
+					min_idle_sched_ctx = sched_ctxs[i];
+				}
+			}
+		}
+
+		printf("*************min idle %lf ctx %d ready tasks %d\n", min_idle, min_idle_sched_ctx, hypervisor.sched_ctx_w[sched_ctxs[0]].nready_tasks);
+		/* if we didn't find an a context with ready tasks try another time with less constraints */
+		if(min_idle_sched_ctx == sched_ctxs[0] && hypervisor.sched_ctx_w[sched_ctxs[0]].nready_tasks == 0)
+		{
+			for(i = 1; i < nsched_ctxs; i++)
+			{
+				if(max_workers_idle_time[i] < min_idle)
+				{
+					min_idle = max_workers_idle_time[i];
+					min_idle_sched_ctx = sched_ctxs[i];
+				}
+			}
+		}
+			
+		struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(min_idle_sched_ctx);
+		config->max_nworkers += diff;
+		printf("%d: redib max_nworkers incr %d \n",  min_idle_sched_ctx, config->max_nworkers);
+	}
+}
 /* notifies the hypervisor that the worker is no longer idle and a new task was pushed on its queue */
 static void notify_idle_end(unsigned sched_ctx, int worker)
 {
@@ -777,7 +885,7 @@ static void notify_idle_end(unsigned sched_ctx, int worker)
 		sc_w->idle_time[worker] += (end_time - sc_w->idle_start_time[worker]) / 1000000.0; /* in seconds */ 
 		sc_w->idle_start_time[worker] = 0.0;
 	}
-
+			
 	if(hypervisor.policy.handle_idle_end)
 		hypervisor.policy.handle_idle_end(sched_ctx, worker);
 
@@ -793,7 +901,7 @@ static void notify_idle_cycle(unsigned sched_ctx, int worker, double idle_time)
 
 		if(sc_w->idle_start_time[worker] == 0.0)
 			sc_w->idle_start_time[worker] = starpu_timing_now();
-
+		
 		if(hypervisor.policy.handle_idle_cycle)
 		{
 			hypervisor.policy.handle_idle_cycle(sched_ctx, worker);
@@ -842,6 +950,31 @@ static void notify_poped_task(unsigned sched_ctx, int worker, struct starpu_task
 		hypervisor.sched_ctx_w[sched_ctx].ready_flops = 0.0;
 	starpu_pthread_mutex_unlock(&act_hypervisor_mutex);
 
+/* 	struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(sched_ctx); */
+	
+/* 	unsigned finished_sample = 0; */
+/* 	char *speed_sample_criteria = getenv("SC_HYPERVISOR_SAMPLE_CRITERIA"); */
+/* 	if(speed_sample_criteria && (strcmp(speed_sample_criteria, "time") == 0)) */
+/* 	{ */
+
+/* 		double curr_time = starpu_timing_now(); */
+/* 		double elapsed_time = (curr_time - hypervisor.sched_ctx_w[sched_ctx].start_time) / 1000000.0; /\* in seconds *\/ */
+
+/* 		finished_sample = elapsed_time > config->time_sample; */
+/* 	} */
+/* 	else */
+/* 	{ */
+/* 		double ctx_elapsed_flops = sc_hypervisor_get_elapsed_flops_per_sched_ctx(&hypervisor.sched_ctx_w[sched_ctx]); */
+/* 		double ctx_sample = config->ispeed_ctx_sample; */
+
+/* 		finished_sample = ctx_elapsed_flops > ctx_sample; */
+/* 	} */
+
+/* 	if(finished_sample) */
+/* 	{ */
+/* 		sc_hypervisor_update_resize_interval(sched_ctx); */
+/* 	} */
+	
 	if(hypervisor.resize[sched_ctx])
 	{	
 		if(hypervisor.policy.handle_poped_task)