perfmodel.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  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 <common/utils.h>
  17. #include <unistd.h>
  18. #include <sys/stat.h>
  19. #include <core/perfmodel/perfmodel.h>
  20. #include <core/jobs.h>
  21. #include <core/workers.h>
  22. #include <datawizard/datawizard.h>
  23. /*
  24. * PER ARCH model
  25. */
  26. static double per_arch_task_expected_length(struct starpu_perfmodel_t *model, enum starpu_perf_archtype arch, struct starpu_task *task)
  27. {
  28. double exp = -1.0;
  29. double (*per_arch_cost_model)(struct starpu_buffer_descr_t *);
  30. if (!model->is_loaded)
  31. {
  32. if (starpu_get_env_number("CALIBRATE") != -1)
  33. {
  34. fprintf(stderr, "CALIBRATE model %s\n", model->symbol);
  35. model->benchmarking = 1;
  36. }
  37. else {
  38. model->benchmarking = 0;
  39. }
  40. register_model(model);
  41. model->is_loaded = 1;
  42. }
  43. per_arch_cost_model = model->per_arch[arch].cost_model;
  44. if (per_arch_cost_model)
  45. exp = per_arch_cost_model(task->buffers);
  46. return exp;
  47. }
  48. /*
  49. * Common model
  50. */
  51. static double common_task_expected_length(struct starpu_perfmodel_t *model, uint32_t who, struct starpu_task *task)
  52. {
  53. double exp;
  54. if (model->cost_model) {
  55. float alpha;
  56. exp = model->cost_model(task->buffers);
  57. switch (who) {
  58. case STARPU_CORE:
  59. alpha = STARPU_CORE_ALPHA;
  60. break;
  61. case STARPU_CUDA:
  62. alpha = STARPU_CUDA_ALPHA;
  63. break;
  64. default:
  65. /* perhaps there are various worker types on that queue */
  66. alpha = 1.0; // this value is not significant ...
  67. break;
  68. }
  69. STARPU_ASSERT(alpha != 0.0f);
  70. return (exp/alpha);
  71. }
  72. return -1.0;
  73. }
  74. double job_expected_length(uint32_t who, struct job_s *j, enum starpu_perf_archtype arch)
  75. {
  76. struct starpu_task *task = j->task;
  77. struct starpu_perfmodel_t *model = task->cl->model;
  78. if (model) {
  79. switch (model->type) {
  80. case STARPU_PER_ARCH:
  81. return per_arch_task_expected_length(model, arch, task);
  82. case STARPU_COMMON:
  83. return common_task_expected_length(model, who, task);
  84. case STARPU_HISTORY_BASED:
  85. return history_based_job_expected_length(model, arch, j);
  86. case STARPU_REGRESSION_BASED:
  87. return regression_based_job_expected_length(model, arch, j);
  88. default:
  89. STARPU_ABORT();
  90. };
  91. }
  92. /* no model was found */
  93. return 0.0;
  94. }
  95. /* Data transfer performance modeling */
  96. double data_expected_penalty(struct jobq_s *q, struct starpu_task *task)
  97. {
  98. uint32_t memory_node = q->memory_node;
  99. unsigned nbuffers = task->cl->nbuffers;
  100. unsigned buffer;
  101. double penalty = 0.0;
  102. for (buffer = 0; buffer < nbuffers; buffer++)
  103. {
  104. starpu_data_handle handle = task->buffers[buffer].handle;
  105. if (task->buffers[buffer].mode == STARPU_W)
  106. continue;
  107. if (!is_data_present_or_requested(handle, memory_node))
  108. {
  109. size_t size = handle->ops->get_size(handle);
  110. uint32_t src_node = select_src_node(handle);
  111. penalty += predict_transfer_time(src_node, memory_node, size);
  112. }
  113. }
  114. return penalty;
  115. }
  116. static int directory_existence_was_tested = 0;
  117. void _starpu_get_perf_model_dir(char *path, size_t maxlen)
  118. {
  119. #ifdef PERF_MODEL_DIR
  120. /* use the directory specified at configure time */
  121. snprintf(path, maxlen, "%s", PERF_MODEL_DIR);
  122. #else
  123. /* by default, we use $HOME/.starpu/sampling */
  124. const char *home_path = getenv("HOME");
  125. snprintf(path, maxlen, "%s/.starpu/sampling/", home_path);
  126. #endif
  127. }
  128. void _starpu_get_perf_model_dir_codelets(char *path, size_t maxlen)
  129. {
  130. _starpu_get_perf_model_dir(path, maxlen);
  131. strncat(path, "codelets/", maxlen);
  132. }
  133. void _starpu_get_perf_model_dir_bus(char *path, size_t maxlen)
  134. {
  135. _starpu_get_perf_model_dir(path, maxlen);
  136. strncat(path, "bus/", maxlen);
  137. }
  138. void _starpu_get_perf_model_dir_debug(char *path, size_t maxlen)
  139. {
  140. _starpu_get_perf_model_dir(path, maxlen);
  141. strncat(path, "debug/", maxlen);
  142. }
  143. void create_sampling_directory_if_needed(void)
  144. {
  145. if (!directory_existence_was_tested)
  146. {
  147. char perf_model_dir[256];
  148. _starpu_get_perf_model_dir(perf_model_dir, 256);
  149. /* The performance of the codelets are stored in
  150. * $PERF_MODEL_DIR/codelets/ while those of the bus are stored in
  151. * $PERF_MODEL_DIR/bus/ so that we don't have name collisions */
  152. /* Testing if a directory exists and creating it otherwise
  153. may not be safe: it is possible that the permission are
  154. changed in between. Instead, we create it and check if
  155. it already existed before */
  156. int ret;
  157. ret = starpu_mkpath(perf_model_dir, S_IRWXU);
  158. if (ret == -1)
  159. {
  160. STARPU_ASSERT(errno == EEXIST);
  161. /* make sure that it is actually a directory */
  162. struct stat sb;
  163. stat(perf_model_dir, &sb);
  164. STARPU_ASSERT(S_ISDIR(sb.st_mode));
  165. }
  166. /* Per-task performance models */
  167. char perf_model_dir_codelets[256];
  168. _starpu_get_perf_model_dir_codelets(perf_model_dir_codelets, 256);
  169. ret = starpu_mkpath(perf_model_dir_codelets, S_IRWXU);
  170. if (ret == -1)
  171. {
  172. STARPU_ASSERT(errno == EEXIST);
  173. /* make sure that it is actually a directory */
  174. struct stat sb;
  175. stat(perf_model_dir_codelets, &sb);
  176. STARPU_ASSERT(S_ISDIR(sb.st_mode));
  177. }
  178. /* Performance of the memory subsystem */
  179. char perf_model_dir_bus[256];
  180. _starpu_get_perf_model_dir_bus(perf_model_dir_bus, 256);
  181. ret = starpu_mkpath(perf_model_dir_bus, S_IRWXU);
  182. if (ret == -1)
  183. {
  184. STARPU_ASSERT(errno == EEXIST);
  185. /* make sure that it is actually a directory */
  186. struct stat sb;
  187. stat(perf_model_dir_bus, &sb);
  188. STARPU_ASSERT(S_ISDIR(sb.st_mode));
  189. }
  190. /* Performance debug measurements */
  191. char perf_model_dir_debug[256];
  192. _starpu_get_perf_model_dir_debug(perf_model_dir_debug, 256);
  193. ret = starpu_mkpath(perf_model_dir_debug, S_IRWXU);
  194. if (ret == -1)
  195. {
  196. STARPU_ASSERT(errno == EEXIST);
  197. /* make sure that it is actually a directory */
  198. struct stat sb;
  199. stat(perf_model_dir_debug, &sb);
  200. STARPU_ASSERT(S_ISDIR(sb.st_mode));
  201. }
  202. directory_existence_was_tested = 1;
  203. }
  204. }