Bläddra i källkod

add glpk support

Samuel Thibault 14 år sedan
förälder
incheckning
0c7a6a6630
3 ändrade filer med 139 tillägg och 7 borttagningar
  1. 2 2
      configure.ac
  2. 5 1
      examples/lu/lu_example.c
  3. 132 4
      src/profiling/bound.c

+ 2 - 2
configure.ac

@@ -594,8 +594,8 @@ if test x$enable_stats = xyes; then
         AC_DEFINE(STARPU_DATA_STATS, [1], [enable statistics])
 fi
 
-#AC_CHECK_HEADERS([glpk.h])
-#AC_HAVE_LIBRARY([glpk])
+AC_CHECK_HEADERS([glpk.h])
+AC_HAVE_LIBRARY([glpk])
 
 ###############################################################################
 #                                                                             #

+ 5 - 1
examples/lu/lu_example.c

@@ -319,7 +319,11 @@ int main(int argc, char **argv)
 
 	if (bound) {
 		starpu_bound_stop();
-		starpu_bound_print_mps(stderr);
+#ifdef HAVE_GLPK_H
+		starpu_bound_print(stderr);
+#else
+		starpu_bound_print_lp(stderr);
+#endif
 	}
 
 	if (check)

+ 132 - 4
src/profiling/bound.c

@@ -20,9 +20,14 @@
  */
 
 #include <starpu.h>
+#include <starpu_config.h>
 #include <profiling/bound.h>
 #include <core/jobs.h>
 
+#ifdef HAVE_GLPK_H
+#include <glpk.h>
+#endif /* HAVE_GLPK_H */
+
 /* TODO: output duration between starpu_bound_start and starpu_bound_stop */
 
 struct task_pool {
@@ -127,6 +132,9 @@ static void _starpu_get_tasks_times(int nw, int nt, double times[nw][nt]) {
 	}
 }
 
+/*
+ * lp_solve format
+ */
 void starpu_bound_print_lp(FILE *output)
 {
 	struct task_pool *tp;
@@ -163,7 +171,7 @@ void starpu_bound_print_lp(FILE *output)
 
 		fprintf(output, "/* And we have to have computed exactly all tasks */\n");
 		for (t = 0, tp = task_pools; tp; t++, tp = tp->next) {
-			fprintf(output, "/* task %s key %lx */\n", tp->cl->model->symbol, (unsigned long) tp->footprint);
+			fprintf(output, "/* task %s key %x */\n", tp->cl->model->symbol, (unsigned) tp->footprint);
 			for (w = 0; w < nw; w++)
 				fprintf(output, "\t+w%dt%dn", w, t);
 			fprintf(output, " = %ld;\n", tp->n);
@@ -191,6 +199,9 @@ void starpu_bound_print_lp(FILE *output)
 	PTHREAD_MUTEX_UNLOCK(&mutex);
 }
 
+/*
+ * MPS output format
+ */
 void starpu_bound_print_mps(FILE *output)
 {
 	struct task_pool * tp;
@@ -227,7 +238,7 @@ void starpu_bound_print_mps(FILE *output)
 
 		fprintf(output, "\n* And we have to have computed exactly all tasks\n");
 		for (t = 0, tp = task_pools; tp; t++, tp = tp->next) {
-			fprintf(output, "* task %s key %lx\n", tp->cl->model->symbol, (unsigned long) tp->footprint);
+			fprintf(output, "* task %s key %x\n", tp->cl->model->symbol, (unsigned) tp->footprint);
 			fprintf(output, " E  T%d\n", t);
 		}
 
@@ -237,7 +248,7 @@ void starpu_bound_print_mps(FILE *output)
 		for (w = 0; w < nw; w++)
 			for (t = 0, tp = task_pools; tp; t++, tp = tp->next) {
 				char name[9];
-				snprintf(name, sizeof(name)-1, "W%dT%d", w, t);
+				snprintf(name, sizeof(name), "W%dT%d", w, t);
 				fprintf(stderr,"    %-8s  W%-7d  %12f\n", name, w, times[w][t]);
 				fprintf(stderr,"    %-8s  T%-7d  %12u\n", name, t, 1);
 			}
@@ -259,7 +270,124 @@ void starpu_bound_print_mps(FILE *output)
 	PTHREAD_MUTEX_UNLOCK(&mutex);
 }
 
+/*
+ * GNU Linear Programming Kit backend
+ */
 void starpu_bound_print(FILE *output)
 {
-	fprintf(output, "TODO: use glpk");
+#ifdef HAVE_GLPK_H
+	struct task_pool * tp;
+	int nt; /* Number of different kinds of tasks */
+	int nw; /* Number of different workers */
+	int t, w;
+	glp_prob *lp;
+	double tmax;
+	int ret;
+
+	PTHREAD_MUTEX_LOCK(&mutex);
+
+	nw = starpu_worker_get_count();
+	nt = 0;
+	for (tp = task_pools; tp; tp = tp->next)
+		nt++;
+
+	lp = glp_create_prob();
+	glp_set_prob_name(lp, "StarPU theoretical bound");
+	glp_set_obj_dir(lp, GLP_MIN);
+	glp_set_obj_name(lp, "total execution time");
+
+	{
+		double times[nw][nt];
+		int ne =
+			nw * (nt+1)	/* worker execution time */
+			+ nt * nw
+			+ 1; /* glpk dumbness */
+		int n = 1;
+		int ia[ne], ja[ne];
+		double ar[ne];
+
+		_starpu_get_tasks_times(nw, nt, times);
+
+		/* Variables: number of tasks i assigned to worker j, and tmax */
+		glp_add_cols(lp, nw*nt+1);
+#define colnum(w, t) ((w)*nt+(t)+1)
+		glp_set_obj_coef(lp, nw*nt+1, 1.);
+
+		for (w = 0; w < nw; w++)
+			for (t = 0, tp = task_pools; tp; t++, tp = tp->next) {
+				char name[32];
+				snprintf(name, sizeof(name), "w%dt%dn", w, t);
+				glp_set_col_name(lp, colnum(w, t), name);
+				glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0., 0.);
+			}
+		glp_set_col_bnds(lp, nw*nt+1, GLP_LO, 0., 0.);
+
+		/* Total worker execution time */
+		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), "worker %s", name);
+			glp_set_row_name(lp, w+1, title);
+			for (t = 0, tp = task_pools; tp; t++, tp = tp->next) {
+				ia[n] = w+1;
+				ja[n] = colnum(w, t);
+				ar[n] = times[w][t];
+				n++;
+			}
+			/* tmax */
+			ia[n] = w+1;
+			ja[n] = nw*nt+1;
+			ar[n] = -1;
+			n++;
+			glp_set_row_bnds(lp, w+1, GLP_UP, 0, 0);
+		}
+
+		/* Total task completion */
+		glp_add_rows(lp, nt);
+		for (t = 0, tp = 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->model->symbol, (unsigned) tp->footprint);
+			glp_set_row_name(lp, nw+t+1, title);
+			for (w = 0; w < nw; w++) {
+				ia[n] = nw+t+1;
+				ja[n] = colnum(w, t);
+				ar[n] = 1;
+				n++;
+			}
+			glp_set_row_bnds(lp, nw+t+1, GLP_FX, tp->n, tp->n);
+		}
+
+		STARPU_ASSERT(n == ne);
+
+		glp_load_matrix(lp, ne-1, ia, ja, ar);
+	}
+
+	glp_adv_basis(lp, 0);
+	glp_smcp parm;
+	glp_init_smcp(&parm);
+	parm.msg_lev = GLP_MSG_OFF;
+	ret = glp_simplex(lp, &parm);
+	if (ret) {
+		fprintf(output, "simplex failed: %d\n", ret);
+	} else {
+		tmax = glp_get_obj_val(lp);
+
+		fprintf(output, "Theoretical minimum execution time: %f ms\n", tmax);
+
+		for (t = 0, tp = task_pools; tp; t++, tp = tp->next) {
+			fprintf(output, "%s key %x\n", tp->cl->model->symbol, (unsigned) tp->footprint);
+			for (w = 0; w < nw; w++)
+				fprintf(output, "\tw%dt%d %f", w, t, glp_get_col_prim(lp, colnum(w, t)));
+			fprintf(output, "\n");
+		}
+	}
+
+	glp_delete_prob(lp);
+
+	PTHREAD_MUTEX_UNLOCK(&mutex);
+#else /* HAVE_GLPK_H */
+	fprintf(output, "Please rebuild StarPU with glpk enabled.\n");
+#endif /* HAVE_GLPK_H */
 }