sched_ctx.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010-2014 Université de Bordeaux
  4. * Copyright (C) 2010-2014, 2016 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. #include <starpu.h>
  18. #include <stdlib.h>
  19. #ifdef STARPU_QUICK_CHECK
  20. #define NTASKS 64
  21. #else
  22. #define NTASKS 1000
  23. #endif
  24. int tasks_executed = 0;
  25. starpu_pthread_mutex_t mut;
  26. static void sched_ctx_cpu_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg STARPU_ATTRIBUTE_UNUSED)
  27. {
  28. STARPU_PTHREAD_MUTEX_LOCK(&mut);
  29. tasks_executed++;
  30. STARPU_PTHREAD_MUTEX_UNLOCK(&mut);
  31. }
  32. static void sched_ctx_cuda_func(void *descr[] STARPU_ATTRIBUTE_UNUSED, void *arg STARPU_ATTRIBUTE_UNUSED)
  33. {
  34. }
  35. static struct starpu_codelet sched_ctx_codelet1 =
  36. {
  37. .cpu_funcs = {sched_ctx_cpu_func},
  38. .model = NULL,
  39. .nbuffers = 0,
  40. .name = "sched_ctx"
  41. };
  42. static struct starpu_codelet sched_ctx_codelet2 =
  43. {
  44. .cpu_funcs = {sched_ctx_cpu_func},
  45. .cuda_funcs = {sched_ctx_cuda_func},
  46. .model = NULL,
  47. .nbuffers = 0,
  48. .name = "sched_ctx"
  49. };
  50. int main(int argc, char **argv)
  51. {
  52. int ntasks = NTASKS;
  53. int ret;
  54. unsigned ncuda = 0;
  55. int nprocs1 = 0;
  56. int nprocs2 = 0;
  57. int procs1[STARPU_NMAXWORKERS], procs2[STARPU_NMAXWORKERS];
  58. char *sched;
  59. ret = starpu_init(NULL);
  60. if (ret == -ENODEV)
  61. return 77;
  62. STARPU_CHECK_RETURN_VALUE(ret, "starpu_init");
  63. starpu_pthread_mutex_init(&mut, NULL);
  64. #ifdef STARPU_USE_CPU
  65. nprocs1 = starpu_cpu_worker_get_count();
  66. starpu_worker_get_ids_by_type(STARPU_CPU_WORKER, procs1, nprocs1);
  67. #endif
  68. // if there is no cpu, skip
  69. if (nprocs1 == 0) goto enodev;
  70. #ifdef STARPU_USE_CUDA
  71. ncuda = nprocs2 = starpu_cuda_worker_get_count();
  72. starpu_worker_get_ids_by_type(STARPU_CUDA_WORKER, procs2, nprocs2);
  73. #endif
  74. if (nprocs2 == 0)
  75. {
  76. nprocs2 = 1;
  77. procs2[0] = procs1[0];
  78. }
  79. /*create contexts however you want*/
  80. sched = getenv("STARPU_SCHED");
  81. unsigned sched_ctx1 = starpu_sched_ctx_create(procs1, nprocs1, "ctx1", STARPU_SCHED_CTX_POLICY_NAME, sched?sched:"eager", 0);
  82. unsigned sched_ctx2 = starpu_sched_ctx_create(procs2, nprocs2, "ctx2", STARPU_SCHED_CTX_POLICY_NAME, sched?sched:"eager", 0);
  83. /*indicate what to do with the resources when context 2 finishes (it depends on your application)*/
  84. starpu_sched_ctx_set_inheritor(sched_ctx2, sched_ctx1);
  85. starpu_sched_ctx_display_workers(sched_ctx2, stderr);
  86. int i;
  87. for (i = 0; i < ntasks/2; i++)
  88. {
  89. struct starpu_task *task = starpu_task_create();
  90. task->cl = &sched_ctx_codelet1;
  91. task->cl_arg = NULL;
  92. /*submit tasks to context*/
  93. ret = starpu_task_submit_to_ctx(task,sched_ctx1);
  94. STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
  95. }
  96. /* tell starpu when you finished submitting tasks to this context
  97. in order to allow moving resources from this context to the inheritor one
  98. when its corresponding tasks finished executing */
  99. starpu_sched_ctx_finished_submit(sched_ctx1);
  100. /* task with no cuda impl submitted to a ctx with gpus only */
  101. struct starpu_task *task2 = starpu_task_create();
  102. task2->cl = &sched_ctx_codelet1;
  103. task2->cl_arg = NULL;
  104. /*submit tasks to context*/
  105. ret = starpu_task_submit_to_ctx(task2,sched_ctx2);
  106. if (ncuda == 0)
  107. {
  108. STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
  109. }
  110. else
  111. {
  112. STARPU_ASSERT_MSG(ret == -ENODEV, "submit task should ret enodev when the ctx does not have the PUs needed by the task");
  113. }
  114. for (i = 0; i < ntasks/2; i++)
  115. {
  116. struct starpu_task *task = starpu_task_create();
  117. task->cl = &sched_ctx_codelet2;
  118. task->cl_arg = NULL;
  119. ret = starpu_task_submit_to_ctx(task,sched_ctx2);
  120. STARPU_CHECK_RETURN_VALUE(ret, "starpu_task_submit");
  121. }
  122. starpu_sched_ctx_finished_submit(sched_ctx2);
  123. /* wait for all tasks at the end*/
  124. starpu_task_wait_for_all();
  125. starpu_sched_ctx_add_workers(procs1, nprocs1, sched_ctx2);
  126. starpu_sched_ctx_delete(sched_ctx1);
  127. starpu_sched_ctx_delete(sched_ctx2);
  128. printf("tasks executed %d out of %d\n", tasks_executed, ntasks/2);
  129. enodev:
  130. starpu_shutdown();
  131. return nprocs1 == 0 ? 77 : 0;
  132. }