fxt-tool.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699
  1. /*
  2. * StarPU
  3. * Copyright (C) INRIA 2008-2009 (see AUTHORS file)
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU Lesser General Public License as published by
  7. * the Free Software Foundation; either version 2.1 of the License, or (at
  8. * your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but
  11. * WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. *
  14. * See the GNU Lesser General Public License in COPYING.LGPL for more details.
  15. */
  16. #include "fxt-tool.h"
  17. event_list_t events[MAXWORKERS];
  18. workq_list_t taskq;
  19. char *worker_name[MAXWORKERS];
  20. static char *cuda_worker_colors[MAXWORKERS] = {"/greens9/7", "/greens9/6", "/greens9/5", "/greens9/4"};
  21. static char *cpus_worker_colors[MAXWORKERS] = {"/ylorrd9/9", "/ylorrd9/6", "/ylorrd9/3", "/ylorrd9/1"};
  22. static char *other_worker_colors[MAXWORKERS] = {"/greys9/9", "/greys9/8", "/greys9/7", "/greys9/6"};
  23. static char *worker_colors[MAXWORKERS];
  24. static fxt_t fut;
  25. struct fxt_ev_64 ev;
  26. unsigned first_event = 1;
  27. uint64_t start_time = 0;
  28. uint64_t end_time = 0;
  29. unsigned nworkers = 0;
  30. /*
  31. * Paje trace file tools
  32. */
  33. static char *out_paje_path = "paje.trace";
  34. static FILE *out_paje_file;
  35. void paje_output_file_init(void)
  36. {
  37. /* create a new file */
  38. out_paje_file = fopen(out_paje_path, "w+");
  39. write_paje_header(out_paje_file);
  40. fprintf(out_paje_file, " \n \
  41. 1 P 0 \"Program\" \n \
  42. 1 Mn P \"Memory Node\" \n \
  43. 1 T Mn \"Worker\" \n \
  44. 1 Sc P \"Scheduler State\" \n \
  45. 3 S T \"Thread State\" \n \
  46. 3 MS Mn \"Memory Node State\" \n \
  47. 4 ntask Sc \"Number of tasks\" \n \
  48. 6 Fi S FetchingInput \"1.0 .1 1.0\" \n \
  49. 6 Po S PushingOutput \"0.1 1.0 1.0\" \n \
  50. 6 E S Executing \".0 .6 .4\" \n \
  51. 6 C S Callback \".0 .3 .8\" \n \
  52. 6 B S Blocked \".9 .1 .0\" \n \
  53. 6 A MS Allocating \".4 .1 .0\" \n \
  54. 6 Ar MS AllocatingReuse \".1 .1 .8\" \n \
  55. 6 R MS Reclaiming \".0 .1 .4\" \n \
  56. 6 Co MS DriverCopy \".3 .5 .1\" \n \
  57. 6 No MS Nothing \".0 .0 .0\" \n \
  58. 5 L P Mn Mn L\n");
  59. }
  60. void paje_output_file_terminate(void)
  61. {
  62. /* close the file */
  63. fclose(out_paje_file);
  64. }
  65. /*
  66. * Generic tools
  67. */
  68. void handle_new_mem_node(void)
  69. {
  70. char *memnodestr = malloc(16*sizeof(char));
  71. sprintf(memnodestr, "%ld", ev.param[0]);
  72. fprintf(out_paje_file, "7 %f %s Mn p MEMNODE%s\n", (float)((ev.time-start_time)/1000000.0), memnodestr, memnodestr);
  73. }
  74. static unsigned cuda_index = 0;
  75. static unsigned cpus_index = 0;
  76. static unsigned other_index = 0;
  77. void handle_new_worker(void)
  78. {
  79. /*
  80. arg0 : type of worker (cuda, core ..)
  81. arg1 : memory node
  82. arg2 : thread id
  83. */
  84. char *str = malloc(20*sizeof(char));
  85. char *color = NULL;
  86. strcpy(str, "unknown");
  87. switch (ev.param[0]) {
  88. case FUT_APPS_KEY:
  89. str = "apps";
  90. color = other_worker_colors[other_index++];
  91. break;
  92. case FUT_CORE_KEY:
  93. str = "core";
  94. color = cpus_worker_colors[cpus_index++];
  95. break;
  96. case FUT_CUDA_KEY:
  97. str = "cuda";
  98. color = cuda_worker_colors[cuda_index++];
  99. break;
  100. }
  101. // fprintf(stderr, "new %s worker (tid = %d)\n", str, ev.param[1]);
  102. char *memnodestr = malloc(16*sizeof(char));
  103. sprintf(memnodestr, "%ld", ev.param[1]);
  104. char *tidstr = malloc(16*sizeof(char));
  105. sprintf(tidstr, "%ld", ev.param[2]);
  106. fprintf(out_paje_file, "7 %f %s T MEMNODE%s %s \n", (float)((ev.time-start_time)/1000000.0), tidstr, memnodestr, tidstr);
  107. /* create a new key in the htable */
  108. uint64_t workerid = nworkers++;
  109. ENTRY item;
  110. item.key = tidstr;
  111. item.data = (void *)workerid;
  112. worker_colors[workerid] = color;
  113. ENTRY *res;
  114. res = hsearch(item, FIND);
  115. worker_name[workerid] = str;
  116. /* only register a thread once */
  117. STARPU_ASSERT(res == NULL);
  118. res = hsearch(item, ENTER);
  119. STARPU_ASSERT(res);
  120. events[workerid] = event_list_new();
  121. }
  122. void handle_worker_terminated(void)
  123. {
  124. char *tidstr = malloc(16*sizeof(char));
  125. sprintf(tidstr, "%ld", ev.param[1]);
  126. fprintf(out_paje_file, "8 %f %s T\n", (float)((ev.time-start_time)/1000000.0), tidstr);
  127. }
  128. int find_workder_id(unsigned long tid)
  129. {
  130. char tidstr[16];
  131. sprintf(tidstr, "%ld", tid);
  132. ENTRY item;
  133. item.key = tidstr;
  134. item.data = NULL;
  135. ENTRY *res;
  136. res = hsearch(item, FIND);
  137. //STARPU_ASSERT(res);
  138. if (!res)
  139. return -1;
  140. int id = (uintptr_t)(res->data);
  141. return id;
  142. }
  143. void handle_start_codelet_body(void)
  144. {
  145. //fprintf(stderr, "start codelet %p on tid %d\n", (void *)ev.param[0], ev.param[1]);
  146. int worker;
  147. worker = find_workder_id(ev.param[1]);
  148. if (worker < 0) return;
  149. // printf("-> worker %d\n", worker);
  150. fprintf(out_paje_file, "10 %f S %ld E\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  151. event_t e = event_new();
  152. e->time = ev.time;
  153. e->mode = WORKING;
  154. event_list_push_back(events[worker], e);
  155. end_time = STARPU_MAX(end_time, ev.time);
  156. }
  157. void handle_end_codelet_body(void)
  158. {
  159. //fprintf(stderr, "end codelet %p on tid %d\n", (void *)ev.param[0], ev.param[1]);
  160. int worker;
  161. worker = find_workder_id(ev.param[1]);
  162. if (worker < 0) return;
  163. // printf("<- worker %d\n", worker);
  164. fprintf(out_paje_file, "10 %f S %ld B\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  165. event_t e = event_new();
  166. e->time = ev.time;
  167. e->mode = IDLE;
  168. event_list_push_back(events[worker], e);
  169. end_time = STARPU_MAX(end_time, ev.time);
  170. }
  171. void handle_start_callback(void)
  172. {
  173. int worker;
  174. worker = find_workder_id(ev.param[1]);
  175. if (worker < 0) return;
  176. fprintf(out_paje_file, "10 %f S %ld C\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  177. }
  178. void handle_end_callback(void)
  179. {
  180. int worker;
  181. worker = find_workder_id(ev.param[1]);
  182. if (worker < 0) return;
  183. fprintf(out_paje_file, "10 %f S %ld B\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  184. }
  185. void handle_start_fetch_input(void)
  186. {
  187. int worker;
  188. worker = find_workder_id(ev.param[1]);
  189. if (worker < 0) return;
  190. fprintf(out_paje_file, "10 %f S %ld Fi\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  191. event_t e = event_new();
  192. e->time = ev.time;
  193. e->mode = FETCHING;
  194. event_list_push_back(events[worker], e);
  195. end_time = STARPU_MAX(end_time, ev.time);
  196. }
  197. void handle_end_fetch_input(void)
  198. {
  199. int worker;
  200. worker = find_workder_id(ev.param[1]);
  201. if (worker < 0) return;
  202. fprintf(out_paje_file, "10 %f S %ld B\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  203. event_t e = event_new();
  204. e->time = ev.time;
  205. e->mode = IDLE;
  206. event_list_push_back(events[worker], e);
  207. end_time = STARPU_MAX(end_time, ev.time);
  208. }
  209. void handle_start_push_output(void)
  210. {
  211. int worker;
  212. worker = find_workder_id(ev.param[1]);
  213. if (worker < 0) return;
  214. fprintf(out_paje_file, "10 %f S %ld Po\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  215. event_t e = event_new();
  216. e->time = ev.time;
  217. e->mode = PUSHING;
  218. event_list_push_back(events[worker], e);
  219. end_time = STARPU_MAX(end_time, ev.time);
  220. }
  221. void handle_end_push_output(void)
  222. {
  223. int worker;
  224. worker = find_workder_id(ev.param[1]);
  225. if (worker < 0) return;
  226. fprintf(out_paje_file, "10 %f S %ld B\n", (float)((ev.time-start_time)/1000000.0), ev.param[1] );
  227. event_t e = event_new();
  228. e->time = ev.time;
  229. e->mode = IDLE;
  230. event_list_push_back(events[worker], e);
  231. end_time = STARPU_MAX(end_time, ev.time);
  232. }
  233. void handle_data_copy(void)
  234. {
  235. }
  236. void handle_start_driver_copy(void)
  237. {
  238. unsigned src = ev.param[0];
  239. unsigned dst = ev.param[1];
  240. unsigned size = ev.param[2];
  241. unsigned comid = ev.param[3];
  242. fprintf(out_paje_file, "10 %f MS MEMNODE%d Co\n", (float)((ev.time-start_time)/1000000.0), dst);
  243. fprintf(out_paje_file, "18 %f L p %d MEMNODE%d com_%d\n", (float)((ev.time-start_time)/1000000.0), size, src, comid);
  244. }
  245. void handle_end_driver_copy(void)
  246. {
  247. unsigned dst = ev.param[1];
  248. unsigned size = ev.param[2];
  249. unsigned comid = ev.param[3];
  250. fprintf(out_paje_file, "10 %f MS MEMNODE%d No\n", (float)((ev.time-start_time)/1000000.0), dst);
  251. fprintf(out_paje_file, "19 %f L p %d MEMNODE%d com_%d\n", (float)((ev.time-start_time)/1000000.0), size, dst, comid);
  252. }
  253. void handle_start_alloc(void)
  254. {
  255. unsigned memnode = ev.param[0];
  256. fprintf(out_paje_file, "10 %f MS MEMNODE%d A\n", (float)((ev.time-start_time)/1000000.0), memnode);
  257. }
  258. void handle_end_alloc(void)
  259. {
  260. unsigned memnode = ev.param[0];
  261. fprintf(out_paje_file, "10 %f MS MEMNODE%d No\n", (float)((ev.time-start_time)/1000000.0), memnode);
  262. }
  263. void handle_start_alloc_reuse(void)
  264. {
  265. unsigned memnode = ev.param[0];
  266. fprintf(out_paje_file, "10 %f MS MEMNODE%d Ar\n", (float)((ev.time-start_time)/1000000.0), memnode);
  267. }
  268. void handle_end_alloc_reuse(void)
  269. {
  270. unsigned memnode = ev.param[0];
  271. fprintf(out_paje_file, "10 %f MS MEMNODE%d No\n", (float)((ev.time-start_time)/1000000.0), memnode);
  272. }
  273. void handle_start_memreclaim(void)
  274. {
  275. unsigned memnode = ev.param[0];
  276. fprintf(out_paje_file, "10 %f MS MEMNODE%d R\n", (float)((ev.time-start_time)/1000000.0), memnode);
  277. }
  278. void handle_end_memreclaim(void)
  279. {
  280. unsigned memnode = ev.param[0];
  281. fprintf(out_paje_file, "10 %f MS MEMNODE%d No\n", (float)((ev.time-start_time)/1000000.0), memnode);
  282. }
  283. int maxq_size = 0;
  284. int curq_size = 0;
  285. void handle_job_push(void)
  286. {
  287. curq_size++;
  288. maxq_size = STARPU_MAX(maxq_size, curq_size);
  289. workq_t e = workq_new();
  290. e->time = ev.time;
  291. e->diff = +1;
  292. e->current_size = curq_size;
  293. fprintf(out_paje_file, "13 %f ntask sched %f\n", (float)((ev.time-start_time)/1000000.0), (float)curq_size);
  294. workq_list_push_back(taskq, e);
  295. }
  296. void handle_job_pop(void)
  297. {
  298. curq_size--;
  299. workq_t e = workq_new();
  300. e->time = ev.time;
  301. e->diff = -1;
  302. e->current_size = curq_size;
  303. fprintf(out_paje_file, "13 %f ntask sched %f\n", (float)((ev.time-start_time)/1000000.0), (float)curq_size);
  304. workq_list_push_back(taskq, e);
  305. }
  306. void handle_codelet_tag_deps(void)
  307. {
  308. uint64_t child;
  309. uint64_t father;
  310. child = ev.param[0];
  311. father = ev.param[1];
  312. add_deps(child, father);
  313. }
  314. void handle_task_done(void)
  315. {
  316. uint64_t tag_id;
  317. tag_id = ev.param[0];
  318. int worker;
  319. worker = find_workder_id(ev.param[1]);
  320. dot_set_tag_done(tag_id, worker_colors[worker]);
  321. }
  322. #ifdef FLASH_RENDER
  323. void generate_flash_output(void)
  324. {
  325. flash_engine_init();
  326. flash_engine_generate_output(events, taskq, worker_name, nworkers, maxq_size, start_time, end_time, "toto.swf");
  327. }
  328. #endif
  329. void generate_svg_output(void)
  330. {
  331. svg_engine_generate_output(events, taskq, worker_name, nworkers, maxq_size, start_time, end_time, "toto.svg");
  332. }
  333. void generate_gnuplot_output(void)
  334. {
  335. FILE *output;
  336. output = fopen("data", "w+");
  337. STARPU_ASSERT(output);
  338. unsigned linesize;
  339. unsigned maxline = 0;
  340. unsigned worker;
  341. for (worker = 0; worker < nworkers; worker++)
  342. {
  343. linesize = 0;
  344. event_itor_t i;
  345. for (i = event_list_begin(events[worker]);
  346. i != event_list_end(events[worker]);
  347. i = event_list_next(i))
  348. {
  349. linesize++;
  350. }
  351. maxline = STARPU_MAX(maxline, linesize);
  352. }
  353. unsigned i;
  354. for (i = 0; i < maxline + 1; i++)
  355. {
  356. fprintf(output, "bla\t");
  357. }
  358. fprintf(output,"\n");
  359. for (worker = 0; worker < nworkers; worker++)
  360. {
  361. unsigned long prev = start_time;
  362. fprintf(output, "%d\t", 0);
  363. event_itor_t i;
  364. for (i = event_list_begin(events[worker]);
  365. i != event_list_end(events[worker]);
  366. i = event_list_next(i))
  367. {
  368. fprintf(output, "%lu\t", (i->time - prev)/FACTOR);
  369. prev = i->time;
  370. }
  371. fprintf(output, "\n");
  372. }
  373. fclose(output);
  374. }
  375. #ifdef USE_GTK
  376. void gtk_viewer(int argc, char **argv)
  377. {
  378. gtk_viewer_apps(argc, argv, events, taskq, worker_name, nworkers, maxq_size, start_time, end_time);
  379. }
  380. #endif
  381. /*
  382. * This program should be used to parse the log generated by FxT
  383. */
  384. int main(int argc, char **argv)
  385. {
  386. char *filename, *filenameout = NULL;
  387. int ret;
  388. int fd_in, fd_out;
  389. int use_stdout = 1;
  390. init_dag_dot();
  391. if (argc < 2) {
  392. fprintf(stderr, "Usage : %s input_filename [-o output_filename]\n", argv[0]);
  393. exit(-1);
  394. }
  395. filename = argv[1];
  396. fd_in = open(filename, O_RDONLY);
  397. if (fd_in < 0) {
  398. perror("open failed :");
  399. exit(-1);
  400. }
  401. if (argc > 2) {
  402. filenameout = argv[2];
  403. use_stdout = 0;
  404. fd_out = open(filenameout, O_RDWR);
  405. if (fd_out < 0) {
  406. perror("open (out) failed :");
  407. exit(-1);
  408. }
  409. }
  410. fut = fxt_fdopen(fd_in);
  411. if (!fut) {
  412. perror("fxt_fdopen :");
  413. exit(-1);
  414. }
  415. fxt_blockev_t block;
  416. block = fxt_blockev_enter(fut);
  417. /* create a htable to identify each worker(tid) */
  418. hcreate(MAXWORKERS);
  419. paje_output_file_init();
  420. taskq = workq_list_new();
  421. while(1) {
  422. ret = fxt_next_ev(block, FXT_EV_TYPE_64, (struct fxt_ev *)&ev);
  423. if (ret != FXT_EV_OK) {
  424. fprintf(stderr, "no more block ...\n");
  425. break;
  426. }
  427. __attribute__ ((unused)) int nbparam = ev.nb_params;
  428. if (first_event)
  429. {
  430. first_event = 0;
  431. start_time = ev.time;
  432. /* create the "program" container */
  433. fprintf(out_paje_file, "7 %f p P 0 program \n", (float)(start_time-start_time));
  434. /* create a variable with the number of tasks */
  435. fprintf(out_paje_file, "7 %f sched Sc p scheduler \n", (float)(start_time-start_time));
  436. fprintf(out_paje_file, "13 %f ntask sched 0.0\n", (float)(start_time-start_time));
  437. }
  438. switch (ev.code) {
  439. case FUT_NEW_WORKER_KEY:
  440. handle_new_worker();
  441. break;
  442. case FUT_NEW_MEM_NODE:
  443. handle_new_mem_node();
  444. break;
  445. /* detect when the workers were idling or not */
  446. case FUT_START_CODELET_BODY:
  447. handle_start_codelet_body();
  448. break;
  449. case FUT_END_CODELET_BODY:
  450. handle_end_codelet_body();
  451. break;
  452. case FUT_START_CALLBACK:
  453. handle_start_callback();
  454. break;
  455. case FUT_END_CALLBACK:
  456. handle_end_callback();
  457. break;
  458. /* monitor stack size */
  459. case FUT_JOB_PUSH:
  460. handle_job_push();
  461. break;
  462. case FUT_JOB_POP:
  463. handle_job_pop();
  464. break;
  465. /* check the memory transfer overhead */
  466. case FUT_START_FETCH_INPUT:
  467. handle_start_fetch_input();
  468. break;
  469. case FUT_END_FETCH_INPUT:
  470. handle_end_fetch_input();
  471. break;
  472. case FUT_START_PUSH_OUTPUT:
  473. handle_start_push_output();
  474. break;
  475. case FUT_END_PUSH_OUTPUT:
  476. handle_end_push_output();
  477. break;
  478. case FUT_CODELET_TAG:
  479. //handle_codelet_tag();
  480. break;
  481. case FUT_CODELET_TAG_DEPS:
  482. handle_codelet_tag_deps();
  483. break;
  484. case FUT_TASK_DONE:
  485. handle_task_done();
  486. break;
  487. case FUT_DATA_COPY:
  488. handle_data_copy();
  489. break;
  490. case FUT_START_DRIVER_COPY:
  491. handle_start_driver_copy();
  492. break;
  493. case FUT_END_DRIVER_COPY:
  494. handle_end_driver_copy();
  495. break;
  496. case FUT_WORK_STEALING:
  497. /* XXX */
  498. break;
  499. case FUT_WORKER_TERMINATED:
  500. handle_worker_terminated();
  501. break;
  502. case FUT_START_ALLOC:
  503. handle_start_alloc();
  504. break;
  505. case FUT_END_ALLOC:
  506. handle_end_alloc();
  507. break;
  508. case FUT_START_ALLOC_REUSE:
  509. handle_start_alloc_reuse();
  510. break;
  511. case FUT_END_ALLOC_REUSE:
  512. handle_end_alloc_reuse();
  513. break;
  514. case FUT_START_MEMRECLAIM:
  515. handle_start_memreclaim();
  516. break;
  517. case FUT_END_MEMRECLAIM:
  518. handle_end_memreclaim();
  519. break;
  520. default:
  521. fprintf(stderr, "unknown event.. %x at time %llx\n", (unsigned)ev.code, (long long unsigned)ev.time);
  522. break;
  523. }
  524. }
  525. generate_gnuplot_output();
  526. //generate_flash_output();
  527. generate_svg_output();
  528. paje_output_file_terminate();
  529. terminate_dat_dot();
  530. #ifdef USE_GTK
  531. gtk_viewer(argc, argv);
  532. #endif
  533. return 0;
  534. }