lp_programs.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2011,2013-2016 Inria
  4. * Copyright (C) 2016,2017 CNRS
  5. *
  6. * StarPU is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU Lesser General Public License as published by
  8. * the Free Software Foundation; either version 2.1 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * StarPU is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  14. *
  15. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  16. */
  17. /*
  18. * GNU Linear Programming Kit backend
  19. */
  20. #include "sc_hypervisor_policy.h"
  21. #include "sc_hypervisor_lp.h"
  22. #ifdef STARPU_HAVE_GLPK_H
  23. double sc_hypervisor_lp_simulate_distrib_tasks(int ns, int nw, int nt, double w_in_s[ns][nw], double tasks[nw][nt],
  24. double times[nw][nt], unsigned is_integer, double tmax, unsigned *in_sched_ctxs,
  25. struct sc_hypervisor_policy_task_pool *tmp_task_pools)
  26. {
  27. struct sc_hypervisor_policy_task_pool * tp;
  28. int t, w, s;
  29. glp_prob *lp;
  30. lp = glp_create_prob();
  31. glp_set_prob_name(lp, "StarPU theoretical bound");
  32. glp_set_obj_dir(lp, GLP_MAX);
  33. glp_set_obj_name(lp, "total execution time");
  34. {
  35. int ne = nt * nw /* worker execution time */
  36. + nw * ns
  37. + nw * (nt + ns)
  38. + 1; /* glp dumbness */
  39. int n = 1;
  40. int ia[ne], ja[ne];
  41. double ar[ne];
  42. /* Variables: number of tasks i assigned to worker j, and tmax */
  43. glp_add_cols(lp, nw*nt+ns*nw);
  44. #define colnum(w, t) ((t)*nw+(w)+1)
  45. for(s = 0; s < ns; s++)
  46. for(w = 0; w < nw; w++)
  47. glp_set_obj_coef(lp, nw*nt+s*nw+w+1, 1.);
  48. for (w = 0; w < nw; w++)
  49. for (t = 0; t < nt; t++)
  50. {
  51. char name[32];
  52. snprintf(name, sizeof(name), "w%dt%dn", w, t);
  53. glp_set_col_name(lp, colnum(w, t), name);
  54. if (is_integer)
  55. {
  56. glp_set_col_kind(lp, colnum(w, t), GLP_IV);
  57. glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0, 0);
  58. }
  59. else
  60. glp_set_col_bnds(lp, colnum(w, t), GLP_LO, 0.0, 0.0);
  61. }
  62. for(s = 0; s < ns; s++)
  63. for(w = 0; w < nw; w++)
  64. {
  65. char name[32];
  66. snprintf(name, sizeof(name), "w%ds%dn", w, s);
  67. glp_set_col_name(lp, nw*nt+s*nw+w+1, name);
  68. if (is_integer)
  69. {
  70. glp_set_col_kind(lp, nw*nt+s*nw+w+1, GLP_IV);
  71. glp_set_col_bnds(lp, nw*nt+s*nw+w+1, GLP_DB, 0, 1);
  72. }
  73. else
  74. glp_set_col_bnds(lp, nw*nt+s*nw+w+1, GLP_DB, 0.0, 1.0);
  75. }
  76. unsigned *sched_ctxs = in_sched_ctxs == NULL ? sc_hypervisor_get_sched_ctxs() : in_sched_ctxs;
  77. int curr_row_idx = 0;
  78. /* Total worker execution time */
  79. glp_add_rows(lp, nw*ns);
  80. for (t = 0; t < nt; t++)
  81. {
  82. int someone = 0;
  83. for (w = 0; w < nw; w++)
  84. if (!isnan(times[w][t]))
  85. someone = 1;
  86. if (!someone)
  87. {
  88. /* This task does not have any performance model at all, abort */
  89. printf("NO PERF MODELS\n");
  90. glp_delete_prob(lp);
  91. return 0.0;
  92. }
  93. }
  94. /*sum(t[t][w]*n[t][w]) < x[s][w]*tmax */
  95. for(s = 0; s < ns; s++)
  96. {
  97. for (w = 0; w < nw; w++)
  98. {
  99. char name[32], title[64];
  100. starpu_worker_get_name(w, name, sizeof(name));
  101. snprintf(title, sizeof(title), "worker %s", name);
  102. glp_set_row_name(lp, curr_row_idx+s*nw+w+1, title);
  103. for (t = 0, tp = tmp_task_pools; tp; t++, tp = tp->next)
  104. {
  105. if(tp->sched_ctx_id == sched_ctxs[s])
  106. {
  107. ia[n] = curr_row_idx+s*nw+w+1;
  108. ja[n] = colnum(w, t);
  109. if (isnan(times[w][t]))
  110. {
  111. printf("had to insert huge val \n");
  112. ar[n] = 1000000000.;
  113. }
  114. else
  115. ar[n] = times[w][t];
  116. n++;
  117. }
  118. }
  119. /* x[s][w] = 1 | 0 */
  120. ia[n] = curr_row_idx+s*nw+w+1;
  121. ja[n] = nw*nt+s*nw+w+1;
  122. ar[n] = (-1) * tmax;
  123. n++;
  124. if (is_integer)
  125. {
  126. glp_set_row_bnds(lp, curr_row_idx+s*nw+w+1, GLP_UP, 0, 0);
  127. }
  128. else
  129. glp_set_row_bnds(lp, curr_row_idx+s*nw+w+1, GLP_UP, 0.0, 0.0);
  130. }
  131. }
  132. curr_row_idx += nw*ns;
  133. /* Total task completion */
  134. glp_add_rows(lp, nt);
  135. for (t = 0, tp = tmp_task_pools; tp; t++, tp = tp->next)
  136. {
  137. char name[32], title[64];
  138. starpu_worker_get_name(w, name, sizeof(name));
  139. snprintf(title, sizeof(title), "task %s key %x", tp->cl->name, (unsigned) tp->footprint);
  140. glp_set_row_name(lp, curr_row_idx+t+1, title);
  141. for (w = 0; w < nw; w++)
  142. {
  143. ia[n] = curr_row_idx+t+1;
  144. ja[n] = colnum(w, t);
  145. ar[n] = 1;
  146. n++;
  147. }
  148. glp_set_row_bnds(lp, curr_row_idx+t+1, GLP_FX, tp->n, tp->n);
  149. }
  150. curr_row_idx += nt;
  151. /* sum(x[s][i]) = 1 */
  152. glp_add_rows(lp, nw);
  153. for (w = 0; w < nw; w++)
  154. {
  155. char name[32], title[64];
  156. starpu_worker_get_name(w, name, sizeof(name));
  157. snprintf(title, sizeof(title), "w%x", w);
  158. glp_set_row_name(lp, curr_row_idx+w+1, title);
  159. for(s = 0; s < ns; s++)
  160. {
  161. ia[n] = curr_row_idx+w+1;
  162. ja[n] = nw*nt+s*nw+w+1;
  163. ar[n] = 1;
  164. n++;
  165. }
  166. if(is_integer)
  167. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1, 1);
  168. else
  169. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1.0, 1.0);
  170. }
  171. if(n != ne)
  172. printf("ns= %d nw = %d nt = %d n = %d ne = %d\n", ns, nw, nt, n, ne);
  173. STARPU_ASSERT(n == ne);
  174. glp_load_matrix(lp, ne-1, ia, ja, ar);
  175. }
  176. glp_smcp parm;
  177. glp_init_smcp(&parm);
  178. parm.msg_lev = GLP_MSG_OFF;
  179. int ret = glp_simplex(lp, &parm);
  180. /* char str[50]; */
  181. /* sprintf(str, "outpu_lp_%g", tmax); */
  182. /* glp_print_sol(lp, str); */
  183. if (ret)
  184. {
  185. printf("error in simplex\n");
  186. glp_delete_prob(lp);
  187. lp = NULL;
  188. return 0.0;
  189. }
  190. int stat = glp_get_prim_stat(lp);
  191. /* if we don't have a solution return */
  192. if(stat == GLP_NOFEAS)
  193. {
  194. glp_delete_prob(lp);
  195. // printf("no_sol in tmax = %lf\n", tmax);
  196. lp = NULL;
  197. return 0.0;
  198. }
  199. if (is_integer)
  200. {
  201. glp_iocp iocp;
  202. glp_init_iocp(&iocp);
  203. iocp.msg_lev = GLP_MSG_OFF;
  204. // iocp.tm_lim = 1000;
  205. glp_intopt(lp, &iocp);
  206. int stat = glp_mip_status(lp);
  207. /* if we don't have a solution return */
  208. if(stat == GLP_NOFEAS || stat == GLP_ETMLIM || stat == GLP_UNDEF)
  209. {
  210. // printf("no int sol in tmax = %lf\n", tmax);
  211. if(stat == GLP_ETMLIM || stat == GLP_UNDEF)
  212. printf("timeout \n");
  213. glp_delete_prob(lp);
  214. lp = NULL;
  215. return 0.0;
  216. }
  217. }
  218. double res = glp_get_obj_val(lp);
  219. for (w = 0; w < nw; w++)
  220. for (t = 0; t < nt; t++)
  221. if (is_integer)
  222. tasks[w][t] = (double)glp_mip_col_val(lp, colnum(w, t));
  223. else
  224. tasks[w][t] = glp_get_col_prim(lp, colnum(w, t));
  225. /* printf("**********************************************\n"); */
  226. /* printf("for tmax %lf\n", tmax); */
  227. for(s = 0; s < ns; s++)
  228. for(w = 0; w < nw; w++)
  229. {
  230. if (is_integer)
  231. w_in_s[s][w] = (double)glp_mip_col_val(lp, nw*nt+s*nw+w+1);
  232. else
  233. w_in_s[s][w] = glp_get_col_prim(lp, nw*nt+s*nw+w+1);
  234. // printf("w %d in ctx %d = %lf\n", w, s, w_in_s[s][w]);
  235. }
  236. /* printf("\n"); */
  237. /* printf("**********************************************\n"); */
  238. glp_delete_prob(lp);
  239. return res;
  240. }
  241. double sc_hypervisor_lp_simulate_distrib_flops(int ns, int nw, double v[ns][nw], double flops[ns], double res[ns][nw],
  242. int total_nw[nw], unsigned sched_ctxs[ns], double last_vmax)
  243. {
  244. int integer = 1;
  245. int s, w;
  246. glp_prob *lp;
  247. int ne = (ns*nw+1)*(ns+nw)
  248. + 1; /* glp dumbness */
  249. int n = 1;
  250. int ia[ne], ja[ne];
  251. double ar[ne];
  252. lp = glp_create_prob();
  253. glp_set_prob_name(lp, "sample");
  254. glp_set_obj_dir(lp, GLP_MAX);
  255. glp_set_obj_name(lp, "max speed");
  256. /* we add nw*ns columns one for each type of worker in each context
  257. and another column corresponding to the 1/tmax bound (bc 1/tmax is a variable too)*/
  258. glp_add_cols(lp, nw*ns+1);
  259. /* struct sc_hypervisor_wrapper *sc_w = NULL; */
  260. for(s = 0; s < ns; s++)
  261. {
  262. /* sc_w = sc_hypervisor_get_wrapper(sched_ctxs[s]); */
  263. struct sc_hypervisor_policy_config *config = sc_hypervisor_get_config(sched_ctxs[s]);
  264. for(w = 0; w < nw; w++)
  265. {
  266. char name[32];
  267. snprintf(name, sizeof(name), "worker%dctx%d", w, s);
  268. glp_set_col_name(lp, n, name);
  269. if (integer)
  270. {
  271. glp_set_col_kind(lp, n, GLP_IV);
  272. /* if(sc_w->consider_max) */
  273. /* { */
  274. /* if(config->max_nworkers == 0) */
  275. /* glp_set_col_bnds(lp, n, GLP_FX, config->min_nworkers, config->max_nworkers); */
  276. /* else */
  277. /* glp_set_col_bnds(lp, n, GLP_DB, config->min_nworkers, config->max_nworkers); */
  278. /* } */
  279. /* else */
  280. {
  281. if(total_nw[w] == 0)
  282. glp_set_col_bnds(lp, n, GLP_FX, config->min_nworkers, total_nw[w]);
  283. else
  284. glp_set_col_bnds(lp, n, GLP_DB, config->min_nworkers, total_nw[w]);
  285. }
  286. }
  287. else
  288. {
  289. /* if(sc_w->consider_max) */
  290. /* { */
  291. /* if(config->max_nworkers == 0) */
  292. /* glp_set_col_bnds(lp, n, GLP_FX, config->min_nworkers*1.0, config->max_nworkers*1.0); */
  293. /* else */
  294. /* glp_set_col_bnds(lp, n, GLP_DB, config->min_nworkers*1.0, config->max_nworkers*1.0); */
  295. /* #ifdef STARPU_SC_HYPERVISOR_DEBUG */
  296. /* printf("%d****************consider max %lf in lp\n", sched_ctxs[s], config->max_nworkers*1.0); */
  297. /* #endif */
  298. /* } */
  299. /* else */
  300. {
  301. if(total_nw[w] == 0)
  302. glp_set_col_bnds(lp, n, GLP_FX, config->min_nworkers*1.0, total_nw[w]*1.0);
  303. else
  304. glp_set_col_bnds(lp, n, GLP_DB, config->min_nworkers*1.0, total_nw[w]*1.0);
  305. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  306. printf("%u****************don't consider max %d but total %d in lp\n", sched_ctxs[s], config->max_nworkers, total_nw[w]);
  307. #endif
  308. }
  309. }
  310. n++;
  311. }
  312. }
  313. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  314. printf("ns = %d nw = %d\n", ns, nw);
  315. #endif
  316. /*1/tmax should belong to the interval [0.0;1.0]*/
  317. glp_set_col_name(lp, n, "vmax");
  318. // glp_set_col_bnds(lp, n, GLP_DB, 0.0, 1.0);
  319. if(last_vmax != -1.0)
  320. glp_set_col_bnds(lp, n, GLP_LO, last_vmax, last_vmax);
  321. else
  322. glp_set_col_bnds(lp, n, GLP_LO, 0.0, 0.0);
  323. /* Z = 1/tmax -> 1/tmax structural variable, nCPUs & nGPUs in ctx are auxiliar variables */
  324. glp_set_obj_coef(lp, n, 1.0);
  325. n = 1;
  326. /* one row corresponds to one ctx*/
  327. glp_add_rows(lp, ns);
  328. for(s = 0; s < ns; s++)
  329. {
  330. char name[32];
  331. snprintf(name, sizeof(name), "ctx%d", s);
  332. glp_set_row_name(lp, s+1, name);
  333. glp_set_row_bnds(lp, s+1, GLP_LO, 0., 0.);
  334. for(w = 0; w < nw; w++)
  335. {
  336. int s2;
  337. for(s2 = 0; s2 < ns; s2++)
  338. {
  339. if(s2 == s)
  340. {
  341. ia[n] = s+1;
  342. ja[n] = w + nw*s2 + 1;
  343. ar[n] = v[s][w];
  344. // printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
  345. }
  346. else
  347. {
  348. ia[n] = s+1;
  349. ja[n] = w + nw*s2 + 1;
  350. ar[n] = 0.0;
  351. // printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
  352. }
  353. n++;
  354. }
  355. }
  356. /* 1/tmax */
  357. ia[n] = s+1;
  358. ja[n] = ns*nw+1;
  359. ar[n] = (-1) * flops[s];
  360. // printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
  361. n++;
  362. }
  363. /*we add another linear constraint : sum(all cpus) = 9 and sum(all gpus) = 3 */
  364. glp_add_rows(lp, nw);
  365. for(w = 0; w < nw; w++)
  366. {
  367. char name[32];
  368. snprintf(name, sizeof(name), "w%d", w);
  369. glp_set_row_name(lp, ns+w+1, name);
  370. for(s = 0; s < ns; s++)
  371. {
  372. int w2;
  373. for(w2 = 0; w2 < nw; w2++)
  374. {
  375. if(w2 == w)
  376. {
  377. ia[n] = ns+w+1;
  378. ja[n] = w2+s*nw + 1;
  379. ar[n] = 1.0;
  380. // printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
  381. }
  382. else
  383. {
  384. ia[n] = ns+w+1;
  385. ja[n] = w2+s*nw + 1;
  386. ar[n] = 0.0;
  387. // printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
  388. }
  389. n++;
  390. }
  391. }
  392. /* 1/tmax */
  393. ia[n] = ns+w+1;
  394. ja[n] = ns*nw+1;
  395. ar[n] = 0.0;
  396. // printf("ia[%d]=%d ja[%d]=%d ar[%d]=%lf\n", n, ia[n], n, ja[n], n, ar[n]);
  397. n++;
  398. /*sum(all gpus) = 3*/
  399. if(w == 0)
  400. glp_set_row_bnds(lp, ns+w+1, GLP_FX, total_nw[0], total_nw[0]);
  401. /*sum(all cpus) = 9*/
  402. if(w == 1)
  403. glp_set_row_bnds(lp, ns+w+1, GLP_FX, total_nw[1], total_nw[1]);
  404. }
  405. STARPU_ASSERT(n == ne);
  406. glp_load_matrix(lp, ne-1, ia, ja, ar);
  407. glp_smcp parm;
  408. glp_init_smcp(&parm);
  409. parm.msg_lev = GLP_MSG_OFF;
  410. int ret = glp_simplex(lp, &parm);
  411. if (ret)
  412. {
  413. printf("error in simplex\n");
  414. glp_delete_prob(lp);
  415. lp = NULL;
  416. return 0.0;
  417. }
  418. int stat = glp_get_prim_stat(lp);
  419. /* if we don't have a solution return */
  420. if(stat == GLP_NOFEAS)
  421. {
  422. glp_delete_prob(lp);
  423. printf("no_sol\n");
  424. lp = NULL;
  425. return 0.0;
  426. }
  427. if (integer)
  428. {
  429. glp_iocp iocp;
  430. glp_init_iocp(&iocp);
  431. iocp.msg_lev = GLP_MSG_OFF;
  432. glp_intopt(lp, &iocp);
  433. int stat = glp_mip_status(lp);
  434. /* if we don't have a solution return */
  435. if(stat == GLP_NOFEAS)
  436. {
  437. printf("no int sol\n");
  438. glp_delete_prob(lp);
  439. lp = NULL;
  440. return 0.0;
  441. }
  442. }
  443. double vmax = glp_get_obj_val(lp);
  444. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  445. printf("vmax = %lf \n", vmax);
  446. #endif
  447. n = 1;
  448. for(s = 0; s < ns; s++)
  449. {
  450. for(w = 0; w < nw; w++)
  451. {
  452. if (integer)
  453. res[s][w] = (double)glp_mip_col_val(lp, n);
  454. else
  455. res[s][w] = glp_get_col_prim(lp, n);
  456. #ifdef STARPU_SC_HYPERVISOR_DEBUG
  457. printf("%d/%d: res %lf flops = %lf v = %lf\n", w,s, res[s][w], flops[s], v[s][w]);
  458. #endif
  459. n++;
  460. }
  461. }
  462. glp_delete_prob(lp);
  463. return vmax;
  464. }
  465. double sc_hypervisor_lp_simulate_distrib_flops_on_sample(int ns, int nw, double final_w_in_s[ns][nw], unsigned is_integer, double tmax,
  466. double **speed, double flops[ns], double **final_flops_on_w)
  467. {
  468. double w_in_s[ns][nw];
  469. double flops_on_w[ns][nw];
  470. int w, s;
  471. glp_prob *lp;
  472. // printf("try with tmax %lf\n", tmax);
  473. lp = glp_create_prob();
  474. glp_set_prob_name(lp, "StarPU theoretical bound");
  475. glp_set_obj_dir(lp, GLP_MAX);
  476. glp_set_obj_name(lp, "total execution time");
  477. {
  478. int ne = 5 * ns * nw /* worker execution time */
  479. + 1; /* glp dumbness */
  480. int n = 1;
  481. int ia[ne], ja[ne];
  482. double ar[ne];
  483. /* Variables: number of flops assigned to worker w in context s, and
  484. the acknwoledgment that the worker w belongs to the context s */
  485. glp_add_cols(lp, 2*nw*ns);
  486. #define colnum_sample(w, s) ((s)*nw+(w)+1)
  487. for(s = 0; s < ns; s++)
  488. for(w = 0; w < nw; w++)
  489. glp_set_obj_coef(lp, nw*ns+colnum_sample(w,s), 1.);
  490. for(s = 0; s < ns; s++)
  491. for(w = 0; w < nw; w++)
  492. {
  493. char name[32];
  494. snprintf(name, sizeof(name), "flopsw%ds%dn", w, s);
  495. glp_set_col_name(lp, colnum_sample(w,s), name);
  496. glp_set_col_bnds(lp, colnum_sample(w,s), GLP_LO, 0., 0.);
  497. snprintf(name, sizeof(name), "w%ds%dn", w, s);
  498. glp_set_col_name(lp, nw*ns+colnum_sample(w,s), name);
  499. if (is_integer)
  500. {
  501. glp_set_col_kind(lp, nw*ns+colnum_sample(w, s), GLP_IV);
  502. glp_set_col_bnds(lp, nw*ns+colnum_sample(w,s), GLP_DB, 0, 1);
  503. }
  504. else
  505. glp_set_col_bnds(lp, nw*ns+colnum_sample(w,s), GLP_DB, 0.0, 1.0);
  506. }
  507. int curr_row_idx = 0;
  508. /* Total worker execution time */
  509. glp_add_rows(lp, nw*ns);
  510. /*nflops[s][w]/v[s][w] < x[s][w]*tmax */
  511. for(s = 0; s < ns; s++)
  512. {
  513. for (w = 0; w < nw; w++)
  514. {
  515. char name[32], title[64];
  516. starpu_worker_get_name(w, name, sizeof(name));
  517. snprintf(title, sizeof(title), "worker %s", name);
  518. glp_set_row_name(lp, curr_row_idx+s*nw+w+1, title);
  519. /* nflosp[s][w] */
  520. ia[n] = curr_row_idx+s*nw+w+1;
  521. ja[n] = colnum_sample(w, s);
  522. ar[n] = 1 / speed[s][w];
  523. n++;
  524. /* x[s][w] = 1 | 0 */
  525. ia[n] = curr_row_idx+s*nw+w+1;
  526. ja[n] = nw*ns+colnum_sample(w,s);
  527. ar[n] = (-1) * tmax;
  528. n++;
  529. glp_set_row_bnds(lp, curr_row_idx+s*nw+w+1, GLP_UP, 0.0, 0.0);
  530. }
  531. }
  532. curr_row_idx += nw*ns;
  533. /* sum(flops[s][w]) = flops[s] */
  534. glp_add_rows(lp, ns);
  535. for (s = 0; s < ns; s++)
  536. {
  537. char name[32], title[64];
  538. starpu_worker_get_name(w, name, sizeof(name));
  539. snprintf(title, sizeof(title), "flops %lf ctx%d", flops[s], s);
  540. glp_set_row_name(lp, curr_row_idx+s+1, title);
  541. for (w = 0; w < nw; w++)
  542. {
  543. ia[n] = curr_row_idx+s+1;
  544. ja[n] = colnum_sample(w, s);
  545. ar[n] = 1;
  546. n++;
  547. }
  548. glp_set_row_bnds(lp, curr_row_idx+s+1, GLP_FX, flops[s], flops[s]);
  549. }
  550. curr_row_idx += ns;
  551. /* sum(x[s][w]) = 1 */
  552. glp_add_rows(lp, nw);
  553. for (w = 0; w < nw; w++)
  554. {
  555. char name[32], title[64];
  556. starpu_worker_get_name(w, name, sizeof(name));
  557. snprintf(title, sizeof(title), "w%x", w);
  558. glp_set_row_name(lp, curr_row_idx+w+1, title);
  559. for(s = 0; s < ns; s++)
  560. {
  561. ia[n] = curr_row_idx+w+1;
  562. ja[n] = nw*ns+colnum_sample(w,s);
  563. ar[n] = 1;
  564. n++;
  565. }
  566. if(is_integer)
  567. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1, 1);
  568. else
  569. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_FX, 1.0, 1.0);
  570. }
  571. curr_row_idx += nw;
  572. /* sum(nflops[s][w]) > 0*/
  573. glp_add_rows(lp, nw);
  574. for (w = 0; w < nw; w++)
  575. {
  576. char name[32], title[64];
  577. starpu_worker_get_name(w, name, sizeof(name));
  578. snprintf(title, sizeof(title), "flopsw%x", w);
  579. glp_set_row_name(lp, curr_row_idx+w+1, title);
  580. for(s = 0; s < ns; s++)
  581. {
  582. ia[n] = curr_row_idx+w+1;
  583. ja[n] = colnum_sample(w,s);
  584. ar[n] = 1;
  585. n++;
  586. }
  587. glp_set_row_bnds(lp, curr_row_idx+w+1, GLP_LO, 0.1, 0.);
  588. }
  589. if(n != ne)
  590. printf("ns= %d nw = %d n = %d ne = %d\n", ns, nw, n, ne);
  591. STARPU_ASSERT(n == ne);
  592. glp_load_matrix(lp, ne-1, ia, ja, ar);
  593. }
  594. glp_smcp parm;
  595. glp_init_smcp(&parm);
  596. parm.msg_lev = GLP_MSG_OFF;
  597. int ret = glp_simplex(lp, &parm);
  598. if (ret)
  599. {
  600. glp_delete_prob(lp);
  601. lp = NULL;
  602. return 0.0;
  603. }
  604. if (is_integer)
  605. {
  606. glp_iocp iocp;
  607. glp_init_iocp(&iocp);
  608. iocp.msg_lev = GLP_MSG_OFF;
  609. glp_intopt(lp, &iocp);
  610. int stat = glp_mip_status(lp);
  611. /* if we don't have a solution return */
  612. if(stat == GLP_NOFEAS)
  613. {
  614. glp_delete_prob(lp);
  615. lp = NULL;
  616. return 0.0;
  617. }
  618. }
  619. int stat = glp_get_prim_stat(lp);
  620. /* if we don't have a solution return */
  621. if(stat == GLP_NOFEAS)
  622. {
  623. glp_delete_prob(lp);
  624. lp = NULL;
  625. return 0.0;
  626. }
  627. double res = glp_get_obj_val(lp);
  628. for(s = 0; s < ns; s++)
  629. for(w = 0; w < nw; w++)
  630. {
  631. flops_on_w[s][w] = glp_get_col_prim(lp, colnum_sample(w, s));
  632. if (is_integer)
  633. w_in_s[s][w] = (double)glp_mip_col_val(lp, nw*ns+colnum_sample(w, s));
  634. else
  635. w_in_s[s][w] = glp_get_col_prim(lp, nw*ns+colnum_sample(w,s));
  636. // printf("w_in_s[s%d][w%d] = %lf flops[s%d][w%d] = %lf \n", s, w, w_in_s[s][w], s, w, flops_on_w[s][w]);
  637. }
  638. glp_delete_prob(lp);
  639. for(s = 0; s < ns; s++)
  640. for(w = 0; w < nw; w++)
  641. {
  642. final_w_in_s[s][w] = w_in_s[s][w];
  643. final_flops_on_w[s][w] = flops_on_w[s][w];
  644. }
  645. return res;
  646. }
  647. #endif // STARPU_HAVE_GLPK_H