simgrid.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2012 Université de Bordeaux 1
  4. *
  5. * StarPU 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. * StarPU 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 <starpu.h>
  17. #include <datawizard/memory_nodes.h>
  18. #include <unistd.h>
  19. #include <core/perfmodel/perfmodel.h>
  20. #include <core/workers.h>
  21. #ifdef STARPU_SIMGRID
  22. #include <msg/msg.h>
  23. #define MAX_TSD 16
  24. #pragma weak starpu_main
  25. extern int starpu_main(int argc, char *argv[]);
  26. struct main_args {
  27. int argc;
  28. char **argv;
  29. };
  30. int do_starpu_main(int argc STARPU_ATTRIBUTE_UNUSED, char *argv[] STARPU_ATTRIBUTE_UNUSED)
  31. {
  32. struct main_args *args = MSG_process_get_data(MSG_process_self());
  33. return starpu_main(args->argc, args->argv);
  34. }
  35. static void bus_name(struct starpu_conf *conf, char *s, size_t size, int num)
  36. {
  37. if (!num)
  38. snprintf(s, size, "RAM");
  39. else if (num < conf->ncuda + 1)
  40. snprintf(s, size, "CUDA%d", num - 1);
  41. else
  42. snprintf(s, size, "OpenCL%d", num - conf->ncuda - 1);
  43. }
  44. #ifdef STARPU_DEVEL
  45. #warning TODO: use another way to start main, when simgrid provides it, and then include the application-provided configuration for platform numbers
  46. #endif
  47. #undef main
  48. int main(int argc, char **argv)
  49. {
  50. xbt_dynar_t hosts;
  51. int i, j;
  52. char name[] = "/tmp/starpu-simgrid-platform.xml.XXXXXX";
  53. int fd;
  54. FILE *file;
  55. struct starpu_machine_topology *topology = &_starpu_get_machine_config()->topology;
  56. if (!starpu_main)
  57. {
  58. _STARPU_ERROR("The main file of this application needs to be compiled with starpu.h included, to properly define starpu_main\n");
  59. exit(EXIT_FAILURE);
  60. }
  61. MSG_init(&argc, argv);
  62. MSG_config("workstation/model", "ptask_L07");
  63. /* Create platform file */
  64. struct starpu_conf conf;
  65. starpu_conf_init(&conf);
  66. if ((!getenv("STARPU_NCPUS") && !getenv("STARPU_NCPU"))
  67. #ifdef STARPU_USE_CUDA
  68. || !getenv("STARPU_NCUDA")
  69. #endif
  70. #ifdef STARPU_USE_OPENCL
  71. || !getenv("STARPU_NOPENCL")
  72. #endif
  73. )
  74. {
  75. _STARPU_ERROR("Please specify the number of cpus and gpus by setting the environment variables STARPU_NCPU%s%s\n",
  76. #ifdef STARPU_USE_CUDA
  77. ", STARPU_NCUDA",
  78. #else
  79. "",
  80. #endif
  81. #ifdef STARPU_USE_OPENCL
  82. ", STARPU_NOPENCL"
  83. #else
  84. ""
  85. #endif
  86. );
  87. exit(EXIT_FAILURE);
  88. }
  89. _starpu_conf_check_environment(&conf);
  90. _starpu_load_bus_performance_files();
  91. topology->ncpus = conf.ncpus;
  92. topology->ncudagpus = conf.ncuda;
  93. topology->nopenclgpus = conf.nopencl;
  94. /* TODO: rather use simgrid/platf.h */
  95. /* TODO: but still permit the user to provide his own xml */
  96. fd = mkstemp(name);
  97. file = fdopen(fd, "w");
  98. fprintf(file,
  99. "<?xml version='1.0'?>\n"
  100. " <!DOCTYPE platform SYSTEM 'http://simgrid.gforge.inria.fr/simgrid.dtd'>\n"
  101. " <platform version='3'>\n"
  102. " <config id='General'>\n"
  103. " <prop id='network/TCP_gamma' value='1000000000'></prop>\n"
  104. " <prop id='network/latency_factor' value='1'></prop>\n"
  105. " <prop id='network/bandwidth_factor' value='1'></prop>\n"
  106. " </config>\n"
  107. " <AS id='AS0' routing='Full'>\n"
  108. " <host id='MAIN' power='1'/>\n"
  109. );
  110. for (i = 0; i < conf.ncpus; i++)
  111. fprintf(file, " <host id='CPU%d' power='2000000000'/>\n", i);
  112. for (i = 0; i < conf.ncuda; i++)
  113. fprintf(file, " <host id='CUDA%d' power='2000000000'/>\n", i);
  114. for (i = 0; i < conf.nopencl; i++)
  115. fprintf(file, " <host id='OpenCL%d' power='2000000000'/>\n", i);
  116. fprintf(file, "\n <host id='RAM' power='1'/>\n");
  117. /* Compute maximum bandwidth, taken as machine bandwidth */
  118. double max_bandwidth = 0;
  119. for (i = 1; i < conf.ncuda + conf.nopencl + 1; i++)
  120. {
  121. if (max_bandwidth < _starpu_transfer_bandwidth(0, i))
  122. max_bandwidth = _starpu_transfer_bandwidth(0, i);
  123. if (max_bandwidth < _starpu_transfer_bandwidth(i, 0))
  124. max_bandwidth = _starpu_transfer_bandwidth(i, 0);
  125. }
  126. fprintf(file, "\n <link id='Share' bandwidth='%f' latency='0.000000'/>\n\n", max_bandwidth*1000000);
  127. for (i = 0; i < conf.ncuda + conf.nopencl + 1; i++)
  128. {
  129. char i_name[16];
  130. bus_name(&conf, i_name, sizeof(i_name), i);
  131. for (j = 0; j < conf.ncuda + conf.nopencl + 1; j++)
  132. {
  133. char j_name[16];
  134. if (j == i)
  135. continue;
  136. bus_name(&conf, j_name, sizeof(j_name), j);
  137. fprintf(file, " <link id='%s-%s' bandwidth='%f' latency='%f'/>\n",
  138. i_name, j_name,
  139. _starpu_transfer_bandwidth(i, j) * 1000000,
  140. _starpu_transfer_latency(i, j) / 1000000);
  141. }
  142. }
  143. for (i = 0; i < conf.ncuda + conf.nopencl + 1; i++)
  144. {
  145. char i_name[16];
  146. bus_name(&conf, i_name, sizeof(i_name), i);
  147. for (j = 0; j < conf.ncuda + conf.nopencl + 1; j++)
  148. {
  149. char j_name[16];
  150. if (j == i)
  151. continue;
  152. bus_name(&conf, j_name, sizeof(j_name), j);
  153. fprintf(file,
  154. " <route src='%s' dst='%s' symmetrical='NO'><link_ctn id='%s-%s'/><link_ctn id='Share'/></route>\n",
  155. i_name, j_name, i_name, j_name);
  156. }
  157. }
  158. fprintf(file,
  159. " </AS>\n"
  160. " </platform>\n"
  161. );
  162. fclose(file);
  163. close(fd);
  164. /* and load it */
  165. MSG_create_environment(name);
  166. unlink(name);
  167. hosts = MSG_hosts_as_dynar();
  168. int nb = xbt_dynar_length(hosts);
  169. for (i = 0; i < nb; i++)
  170. MSG_host_set_data(xbt_dynar_get_as(hosts, i, msg_host_t), calloc(MAX_TSD, sizeof(void*)));
  171. struct main_args args = { .argc = argc, .argv = argv };
  172. MSG_process_create("main", &do_starpu_main, &args, xbt_dynar_get_as(hosts, 0, msg_host_t));
  173. xbt_dynar_free(&hosts);
  174. MSG_main();
  175. return 0;
  176. }
  177. void _starpu_simgrid_execute_job(struct _starpu_job *j, enum starpu_perf_archtype perf_arch, double length)
  178. {
  179. struct starpu_task *task = j->task;
  180. msg_task_t simgrid_task;
  181. if (j->exclude_from_dag)
  182. /* This is not useful to include in simulation (and probably
  183. * doesn't have a perfmodel anyway) */
  184. return;
  185. if (isnan(length))
  186. {
  187. length = starpu_task_expected_length(task, perf_arch, j->nimpl);
  188. STARPU_ASSERT_MSG(!_STARPU_IS_ZERO(length) && !isnan(length),
  189. "Codelet %s does not have a perfmodel, or is not calibrated enough",
  190. _starpu_job_get_model_name(j));
  191. }
  192. simgrid_task = MSG_task_create(_starpu_job_get_model_name(j),
  193. length/1000000.0*MSG_get_host_speed(MSG_host_self()),
  194. 0, NULL);
  195. MSG_task_execute(simgrid_task);
  196. }
  197. msg_task_t _starpu_simgrid_transfer_task_create(unsigned src_node, unsigned dst_node, size_t size)
  198. {
  199. msg_host_t *hosts = calloc(2, sizeof(*hosts));
  200. double *computation = calloc(2, sizeof(*computation));
  201. double *communication = calloc(4, sizeof(*communication));
  202. hosts[0] = _starpu_simgrid_memory_node_get_host(src_node);
  203. hosts[1] = _starpu_simgrid_memory_node_get_host(dst_node);
  204. STARPU_ASSERT(hosts[0] != hosts[1]);
  205. communication[1] = size;
  206. return MSG_parallel_task_create("copy", 2, hosts, computation, communication, NULL);
  207. }
  208. struct completion {
  209. msg_task_t task;
  210. unsigned *finished;
  211. _starpu_pthread_mutex_t *mutex;
  212. _starpu_pthread_cond_t *cond;
  213. };
  214. int transfer_execute(int argc STARPU_ATTRIBUTE_UNUSED, char *argv[] STARPU_ATTRIBUTE_UNUSED)
  215. {
  216. struct completion *completion = MSG_process_get_data(MSG_process_self());
  217. MSG_task_execute(completion->task);
  218. MSG_task_destroy(completion->task);
  219. _STARPU_PTHREAD_MUTEX_LOCK(completion->mutex);
  220. *completion->finished = 1;
  221. _STARPU_PTHREAD_COND_BROADCAST(completion->cond);
  222. _STARPU_PTHREAD_MUTEX_UNLOCK(completion->mutex);
  223. free(completion);
  224. return 0;
  225. }
  226. void _starpu_simgrid_post_task(msg_task_t task, unsigned *finished, _starpu_pthread_mutex_t *mutex, _starpu_pthread_cond_t *cond)
  227. {
  228. struct completion *completion = malloc(sizeof (*completion));
  229. completion->task = task;
  230. completion->finished = finished;
  231. completion->mutex = mutex;
  232. completion->cond = cond;
  233. xbt_dynar_t hosts = MSG_hosts_as_dynar();
  234. MSG_process_create("transfer task", transfer_execute, completion, xbt_dynar_get_as(hosts, 0, msg_host_t));
  235. xbt_dynar_free(&hosts);
  236. }
  237. static int last_key;
  238. int _starpu_pthread_key_create(_starpu_pthread_key_t *key)
  239. {
  240. /* Note: no synchronization here, we are actually monothreaded anyway. */
  241. STARPU_ASSERT(last_key < MAX_TSD);
  242. *key = last_key++;
  243. return 0;
  244. }
  245. int _starpu_pthread_key_delete(_starpu_pthread_key_t key STARPU_ATTRIBUTE_UNUSED)
  246. {
  247. #ifdef STARPU_DEVEL
  248. #warning TODO: implement pthread_key_delete so simgridified starpu can be restarted at will
  249. #endif
  250. return 0;
  251. }
  252. int _starpu_pthread_setspecific(_starpu_pthread_key_t key, void *ptr)
  253. {
  254. void **array = MSG_host_get_data(MSG_host_self());
  255. array[key] = ptr;
  256. return 0;
  257. }
  258. void* _starpu_pthread_getspecific(_starpu_pthread_key_t key)
  259. {
  260. void **array = MSG_host_get_data(MSG_host_self());
  261. return array[key];
  262. }
  263. int
  264. _starpu_simgrid_thread_start(int argc STARPU_ATTRIBUTE_UNUSED, char *argv[] STARPU_ATTRIBUTE_UNUSED)
  265. {
  266. struct _starpu_pthread_args *args = MSG_process_get_data(MSG_process_self());
  267. args->f(args->arg);
  268. free(args);
  269. return 0;
  270. }
  271. #endif