combined_workers.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2010-2013 Université de Bordeaux 1
  4. * Copyright (C) 2010, 2011 Centre National de la Recherche Scientifique
  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 <stdlib.h> // for qsort
  18. #include <starpu.h>
  19. #include <common/config.h>
  20. #include <core/workers.h>
  21. #ifdef __GLIBC__
  22. #include <sched.h>
  23. #endif
  24. #ifdef __MINGW32__
  25. #include <windows.h>
  26. #endif
  27. static int compar_int(const void *pa, const void *pb)
  28. {
  29. int a = *((int *)pa);
  30. int b = *((int *)pb);
  31. return a - b;
  32. }
  33. static void sort_workerid_array(int nworkers, int workerid_array[])
  34. {
  35. qsort(workerid_array, nworkers, sizeof(int), compar_int);
  36. }
  37. /* Create a new worker id for a combination of workers. This method should
  38. * typically be called at the initialization of the scheduling policy. This
  39. * worker should be the combination of the list of id's contained in the
  40. * workerid_array array which has nworkers entries. This function returns
  41. * the identifier of the combined worker in case of success, a negative value
  42. * is returned otherwise. */
  43. int starpu_combined_worker_assign_workerid(int nworkers, int workerid_array[])
  44. {
  45. int new_workerid;
  46. /* Return the number of actual workers. */
  47. struct _starpu_machine_config *config = _starpu_get_machine_config();
  48. int basic_worker_count = (int)config->topology.nworkers;
  49. int combined_worker_id = (int)config->topology.ncombinedworkers;
  50. /* We sort the ids */
  51. sort_workerid_array(nworkers, workerid_array);
  52. /* Test that all workers are not combined workers already. */
  53. int i;
  54. for (i = 0; i < nworkers; i++)
  55. {
  56. int id = workerid_array[i];
  57. #ifdef STARPU_USE_MIC
  58. STARPU_ASSERT(config->workers[id].arch == STARPU_CPU_WORKER || config->workers[id].arch == STARPU_MIC_WORKER);
  59. STARPU_ASSERT(config->workers[id].worker_mask == STARPU_CPU || config->workers[id].worker_mask == STARPU_MIC);
  60. #else/* STARPU_USE_MIC */
  61. /* We only combine CPUs */
  62. STARPU_ASSERT(config->workers[id].arch == STARPU_CPU_WORKER);
  63. STARPU_ASSERT(config->workers[id].worker_mask == STARPU_CPU);
  64. #endif /* STARPU_USE_MIC */
  65. /* We only combine valid "basic" workers */
  66. if ((id < 0) || (id >= basic_worker_count))
  67. return -EINVAL;
  68. }
  69. /* Get an id for that combined worker. Note that this is not thread
  70. * safe because thhis method should only be called when the scheduler
  71. * is being initialized. */
  72. new_workerid = basic_worker_count + combined_worker_id;
  73. config->topology.ncombinedworkers++;
  74. #if 0
  75. fprintf(stderr, "COMBINED WORKERS ");
  76. for (i = 0; i < nworkers; i++)
  77. {
  78. fprintf(stderr, "%d ", workerid_array[i]);
  79. }
  80. fprintf(stderr, "into worker %d\n", new_workerid);
  81. #endif
  82. struct _starpu_combined_worker *combined_worker =
  83. &config->combined_workers[combined_worker_id];
  84. combined_worker->worker_size = nworkers;
  85. #ifdef STARPU_USE_MIC
  86. if(config->workers[workerid_array[0]].worker_mask == STARPU_MIC)
  87. {
  88. combined_worker->perf_arch = (enum starpu_perfmodel_archtype) (STARPU_MIC_DEFAULT + config->workers[workerid_array[0]].mp_nodeid /* *STARPU_MAXMICCPUS + nworkers - 1*/);
  89. combined_worker->worker_mask = STARPU_MIC;
  90. }
  91. #endif
  92. if(config->workers[workerid_array[0]].worker_mask == STARPU_CPU)
  93. {
  94. combined_worker->perf_arch = (enum starpu_perfmodel_archtype) (STARPU_CPU_DEFAULT + nworkers - 1);
  95. combined_worker->worker_mask = STARPU_CPU;
  96. }
  97. #ifdef STARPU_USE_MIC
  98. combined_worker->count = nworkers -1;
  99. pthread_mutex_init(&combined_worker->count_mutex,NULL);
  100. #endif
  101. /* We assume that the memory node should either be that of the first
  102. * entry, and it is very likely that every worker in the combination
  103. * should be on the same memory node.*/
  104. int first_id = workerid_array[0];
  105. combined_worker->memory_node = config->workers[first_id].memory_node;
  106. /* Save the list of combined workers */
  107. memcpy(&combined_worker->combined_workerid, workerid_array, nworkers*sizeof(int));
  108. /* Note that we maintain both the cpu_set and the hwloc_cpu_set so that
  109. * the application is not forced to use hwloc when it is available. */
  110. #ifdef __GLIBC__
  111. CPU_ZERO(&combined_worker->cpu_set);
  112. #endif /* __GLIBC__ */
  113. #ifdef STARPU_HAVE_HWLOC
  114. combined_worker->hwloc_cpu_set = hwloc_bitmap_alloc();
  115. #endif
  116. for (i = 0; i < nworkers; i++)
  117. {
  118. #if defined(__GLIBC__) || defined(STARPU_HAVE_HWLOC)
  119. int id = workerid_array[i];
  120. #ifdef __GLIBC__
  121. #ifdef CPU_OR
  122. CPU_OR(&combined_worker->cpu_set,
  123. &combined_worker->cpu_set,
  124. &config->workers[id].cpu_set);
  125. #else
  126. int j;
  127. for (j = 0; j < CPU_SETSIZE; j++)
  128. {
  129. if (CPU_ISSET(j, &config->workers[id].cpu_set))
  130. CPU_SET(j, &combined_worker->cpu_set);
  131. }
  132. #endif
  133. #endif /* __GLIBC__ */
  134. #ifdef STARPU_HAVE_HWLOC
  135. hwloc_bitmap_or(combined_worker->hwloc_cpu_set,
  136. combined_worker->hwloc_cpu_set,
  137. config->workers[id].hwloc_cpu_set);
  138. #endif
  139. #endif
  140. }
  141. return new_workerid;
  142. }
  143. int starpu_combined_worker_get_description(int workerid, int *worker_size, int **combined_workerid)
  144. {
  145. /* Check that this is the id of a combined worker */
  146. struct _starpu_combined_worker *worker;
  147. worker = _starpu_get_combined_worker_struct(workerid);
  148. STARPU_ASSERT(worker);
  149. if (worker_size)
  150. *worker_size = worker->worker_size;
  151. if (combined_workerid)
  152. *combined_workerid = worker->combined_workerid;
  153. return 0;
  154. }