nested_sched_ctxs.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010-2021 Université de Bordeaux, CNRS (LaBRI UMR 5800), Inria
  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 <omp.h>
  18. #ifdef STARPU_QUICK_CHECK
  19. #define NTASKS 64
  20. #else
  21. #define NTASKS 100
  22. #endif
  23. int tasks_executed[2];
  24. int parallel_code(int sched_ctx)
  25. {
  26. int i;
  27. int t = 0;
  28. int *cpuids = NULL;
  29. int ncpuids = 0;
  30. starpu_sched_ctx_get_available_cpuids(sched_ctx, &cpuids, &ncpuids);
  31. // printf("execute task of %d threads \n", ncpuids);
  32. #pragma omp parallel num_threads(ncpuids)
  33. {
  34. starpu_sched_ctx_bind_current_thread_to_cpuid(cpuids[omp_get_thread_num()]);
  35. // printf("cpu = %d ctx%d nth = %d\n", sched_getcpu(), sched_ctx, omp_get_num_threads());
  36. #pragma omp for
  37. for(i = 0; i < NTASKS; i++)
  38. t++;
  39. }
  40. free(cpuids);
  41. return t;
  42. }
  43. static void sched_ctx_func(void *descr[], void *arg)
  44. {
  45. (void)descr;
  46. unsigned sched_ctx = (uintptr_t)arg;
  47. int t = parallel_code(sched_ctx);
  48. if (sched_ctx > 0 && sched_ctx < 3)
  49. {
  50. STARPU_ATOMIC_ADD(&tasks_executed[sched_ctx-1], t);
  51. }
  52. //printf("w %d executed %d it \n", w, n);
  53. }
  54. static struct starpu_codelet sched_ctx_codelet =
  55. {
  56. .cpu_funcs = {sched_ctx_func},
  57. .model = NULL,
  58. .nbuffers = 0,
  59. .name = "sched_ctx"
  60. };
  61. int main(void)
  62. {
  63. tasks_executed[0] = 0;
  64. tasks_executed[1] = 0;
  65. int ntasks = NTASKS;
  66. int ret, j, k;
  67. unsigned ncpus = 0;
  68. ret = starpu_init(NULL);
  69. if (ret == -ENODEV)
  70. return 77;
  71. STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
  72. int nprocs1 = 1;
  73. int nprocs2 = 1;
  74. int *procs1, *procs2;
  75. #ifdef STARPU_USE_CPU
  76. ncpus = starpu_cpu_worker_get_count();
  77. procs1 = (int*)malloc(ncpus*sizeof(int));
  78. starpu_worker_get_ids_by_type(STARPU_CPU_WORKER, procs1, ncpus);
  79. if (ncpus > 1)
  80. {
  81. nprocs1 = ncpus/2;
  82. nprocs2 = nprocs1;
  83. k = 0;
  84. procs2 = (int*)malloc(nprocs2*sizeof(int));
  85. for(j = nprocs1; j < nprocs1+nprocs2; j++)
  86. procs2[k++] = procs1[j];
  87. }
  88. else
  89. {
  90. procs2 = (int*)malloc(nprocs2*sizeof(int));
  91. procs2[0] = procs1[0];
  92. }
  93. #endif
  94. if (ncpus == 0)
  95. {
  96. #ifdef STARPU_USE_CPU
  97. free(procs1);
  98. free(procs2);
  99. #endif
  100. starpu_shutdown();
  101. return 77;
  102. }
  103. /*create contexts however you want*/
  104. unsigned sched_ctx1 = starpu_sched_ctx_create(procs1, nprocs1, "ctx1", STARPU_SCHED_CTX_POLICY_NAME, "eager", 0);
  105. unsigned sched_ctx2 = starpu_sched_ctx_create(procs2, nprocs2, "ctx2", STARPU_SCHED_CTX_POLICY_NAME, "dmda", 0);
  106. /*indicate what to do with the resources when context 2 finishes (it depends on your application)*/
  107. // starpu_sched_ctx_set_inheritor(sched_ctx2, sched_ctx1);
  108. int nprocs3 = nprocs1/2;
  109. int nprocs4 = nprocs3;
  110. int nprocs5 = nprocs2/2;
  111. int nprocs6 = nprocs5;
  112. int *procs3 = NULL;
  113. int *procs4 = NULL;
  114. int *procs5 = NULL;
  115. int *procs6 = NULL;
  116. if (nprocs3)
  117. procs3 = malloc(nprocs3 * sizeof(*procs3));
  118. if (nprocs4)
  119. procs4 = malloc(nprocs4 * sizeof(*procs4));
  120. if (nprocs5)
  121. procs5 = malloc(nprocs5 * sizeof(*procs5));
  122. if (nprocs6)
  123. procs6 = malloc(nprocs6 * sizeof(*procs6));
  124. k = 0;
  125. for(j = 0; j < nprocs3; j++)
  126. procs3[k++] = procs1[j];
  127. k = 0;
  128. for(j = nprocs3; j < nprocs3+nprocs4; j++)
  129. procs4[k++] = procs1[j];
  130. k = 0;
  131. for(j = 0; j < nprocs5; j++)
  132. procs5[k++] = procs2[j];
  133. k = 0;
  134. for(j = nprocs5; j < nprocs5+nprocs6; j++)
  135. procs6[k++] = procs2[j];
  136. int sched_ctx3 = -1;
  137. int sched_ctx4 = -1;
  138. int sched_ctx5 = -1;
  139. int sched_ctx6 = -1;
  140. if (nprocs3)
  141. sched_ctx3 = starpu_sched_ctx_create(procs3, nprocs3, "ctx3", STARPU_SCHED_CTX_NESTED, sched_ctx1, 0);
  142. if (nprocs4)
  143. sched_ctx4 = starpu_sched_ctx_create(procs4, nprocs4, "ctx4", STARPU_SCHED_CTX_NESTED, sched_ctx1, 0);
  144. if (nprocs5)
  145. sched_ctx5 = starpu_sched_ctx_create(procs5, nprocs5, "ctx5", STARPU_SCHED_CTX_NESTED, sched_ctx2, 0);
  146. if (nprocs6)
  147. sched_ctx6 = starpu_sched_ctx_create(procs6, nprocs6, "ctx6", STARPU_SCHED_CTX_NESTED, sched_ctx2, 0);
  148. int i;
  149. for (i = 0; i < ntasks; i++)
  150. {
  151. struct starpu_task *task = starpu_task_create();
  152. task->cl = &sched_ctx_codelet;
  153. task->cl_arg = (void*)(uintptr_t) sched_ctx1;
  154. task->possibly_parallel = 1;
  155. /*submit tasks to context*/
  156. ret = starpu_task_submit_to_ctx(task,sched_ctx1);
  157. STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
  158. }
  159. for (i = 0; i < ntasks; i++)
  160. {
  161. struct starpu_task *task = starpu_task_create();
  162. task->cl = &sched_ctx_codelet;
  163. task->cl_arg = (void*)(uintptr_t) sched_ctx2;
  164. task->possibly_parallel = 1;
  165. /*submit tasks to context*/
  166. ret = starpu_task_submit_to_ctx(task,sched_ctx2);
  167. STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
  168. }
  169. /* tell starpu when you finished submitting tasks to this context
  170. in order to allow moving resources from this context to the inheritor one
  171. when its corresponding tasks finished executing */
  172. /* wait for all tasks at the end*/
  173. starpu_task_wait_for_all();
  174. if (nprocs3)
  175. {
  176. starpu_sched_ctx_delete(sched_ctx3);
  177. free(procs3);
  178. }
  179. if (nprocs4)
  180. {
  181. starpu_sched_ctx_delete(sched_ctx4);
  182. free(procs4);
  183. }
  184. if (nprocs5)
  185. {
  186. starpu_sched_ctx_delete(sched_ctx5);
  187. free(procs5);
  188. }
  189. if (nprocs6)
  190. {
  191. starpu_sched_ctx_delete(sched_ctx6);
  192. free(procs6);
  193. }
  194. starpu_sched_ctx_delete(sched_ctx1);
  195. starpu_sched_ctx_delete(sched_ctx2);
  196. printf("ctx%u: tasks starpu executed %d out of %d\n", sched_ctx1, tasks_executed[0], NTASKS*NTASKS);
  197. printf("ctx%u: tasks starpu executed %d out of %d\n", sched_ctx2, tasks_executed[1], NTASKS*NTASKS);
  198. #ifdef STARPU_USE_CPU
  199. free(procs1);
  200. free(procs2);
  201. #endif
  202. starpu_shutdown();
  203. return 0;
  204. }