starpu_mpi_early_data.c 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. /* StarPU --- Runtime system for heterogeneous multicore architectures.
  2. *
  3. * Copyright (C) 2009, 2010-2014 Université de Bordeaux
  4. * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 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>
  18. #include <starpu_mpi.h>
  19. #include <starpu_mpi_early_data.h>
  20. #include <starpu_mpi_private.h>
  21. #include <common/uthash.h>
  22. struct _starpu_mpi_early_data_handle_hashlist
  23. {
  24. struct _starpu_mpi_early_data_handle_list *list;
  25. UT_hash_handle hh;
  26. struct _starpu_mpi_node_tag node_tag;
  27. };
  28. /** stores data which have been received by MPI but have not been requested by the application */
  29. static struct _starpu_mpi_early_data_handle_hashlist *_starpu_mpi_early_data_handle_hashmap = NULL;
  30. static int _starpu_mpi_early_data_handle_hashmap_count = 0;
  31. void _starpu_mpi_early_data_init(void)
  32. {
  33. _starpu_mpi_early_data_handle_hashmap = NULL;
  34. _starpu_mpi_early_data_handle_hashmap_count = 0;
  35. }
  36. void _starpu_mpi_early_data_check_termination(void)
  37. {
  38. STARPU_ASSERT_MSG(_starpu_mpi_early_data_handle_hashmap_count == 0, "Number of unexpected received messages left is not zero, did you forget to post a receive corresponding to a send?");
  39. }
  40. void _starpu_mpi_early_data_free(void)
  41. {
  42. struct _starpu_mpi_early_data_handle_hashlist *current, *tmp;
  43. HASH_ITER(hh, _starpu_mpi_early_data_handle_hashmap, current, tmp)
  44. {
  45. _starpu_mpi_early_data_handle_list_delete(current->list);
  46. HASH_DEL(_starpu_mpi_early_data_handle_hashmap, current);
  47. free(current);
  48. }
  49. }
  50. struct _starpu_mpi_early_data_handle *_starpu_mpi_early_data_create(struct _starpu_mpi_envelope *envelope, int source, MPI_Comm comm)
  51. {
  52. struct _starpu_mpi_early_data_handle* early_data_handle = calloc(1, sizeof(struct _starpu_mpi_early_data_handle));
  53. STARPU_ASSERT(early_data_handle);
  54. STARPU_PTHREAD_MUTEX_INIT(&early_data_handle->req_mutex, NULL);
  55. STARPU_PTHREAD_COND_INIT(&early_data_handle->req_cond, NULL);
  56. early_data_handle->env = envelope;
  57. early_data_handle->node_tag.comm = comm;
  58. early_data_handle->node_tag.rank = source;
  59. early_data_handle->node_tag.data_tag = envelope->data_tag;
  60. return early_data_handle;
  61. }
  62. #ifdef STARPU_VERBOSE
  63. static void _starpu_mpi_early_data_handle_display_hash(struct _starpu_mpi_node_tag *node_tag)
  64. {
  65. struct _starpu_mpi_early_data_handle_hashlist *hashlist;
  66. HASH_FIND(hh, _starpu_mpi_early_data_handle_hashmap, node_tag, sizeof(struct _starpu_mpi_node_tag), hashlist);
  67. if (hashlist == NULL)
  68. {
  69. _STARPU_MPI_DEBUG(60, "Hashlist for comm %p source %d and tag %d does not exist\n", node_tag->comm, node_tag->rank, node_tag->data_tag);
  70. }
  71. else if (_starpu_mpi_early_data_handle_list_empty(hashlist->list))
  72. {
  73. _STARPU_MPI_DEBUG(60, "Hashlist for comm %p source %d and tag %d is empty\n", node_tag->comm, node_tag->rank, node_tag->data_tag);
  74. }
  75. else
  76. {
  77. struct _starpu_mpi_early_data_handle *cur;
  78. for (cur = _starpu_mpi_early_data_handle_list_begin(hashlist->list) ;
  79. cur != _starpu_mpi_early_data_handle_list_end(hashlist->list);
  80. cur = _starpu_mpi_early_data_handle_list_next(cur))
  81. {
  82. _STARPU_MPI_DEBUG(60, "Element for comm %p source %d and tag %d: %p\n", node_tag->comm, node_tag->rank, node_tag->data_tag, cur);
  83. }
  84. }
  85. }
  86. #endif
  87. static
  88. struct _starpu_mpi_early_data_handle *_starpu_mpi_early_data_pop(struct _starpu_mpi_node_tag *node_tag, int delete)
  89. {
  90. struct _starpu_mpi_early_data_handle_hashlist *hashlist;
  91. struct _starpu_mpi_early_data_handle *early_data_handle;
  92. _STARPU_MPI_DEBUG(60, "Looking for early_data_handle with comm %p source %d tag %d\n", node_tag->comm, node_tag->rank, node_tag->data_tag);
  93. HASH_FIND(hh, _starpu_mpi_early_data_handle_hashmap, node_tag, sizeof(struct _starpu_mpi_node_tag), hashlist);
  94. if (hashlist == NULL)
  95. {
  96. early_data_handle = NULL;
  97. }
  98. else
  99. {
  100. if (_starpu_mpi_early_data_handle_list_empty(hashlist->list))
  101. {
  102. early_data_handle = NULL;
  103. }
  104. else
  105. {
  106. if (delete == 1)
  107. {
  108. early_data_handle = _starpu_mpi_early_data_handle_list_pop_front(hashlist->list);
  109. }
  110. else
  111. {
  112. early_data_handle = _starpu_mpi_early_data_handle_list_front(hashlist->list);
  113. }
  114. }
  115. }
  116. _STARPU_MPI_DEBUG(60, "Found early_data_handle %p with comm %p source %d tag %d\n", early_data_handle, node_tag->comm, node_tag->rank, node_tag->data_tag);
  117. return early_data_handle;
  118. }
  119. struct _starpu_mpi_early_data_handle *_starpu_mpi_early_data_find(struct _starpu_mpi_node_tag *node_tag)
  120. {
  121. return _starpu_mpi_early_data_pop(node_tag, 0);
  122. }
  123. void _starpu_mpi_early_data_add(struct _starpu_mpi_early_data_handle *early_data_handle)
  124. {
  125. _STARPU_MPI_DEBUG(60, "Trying to add early_data_handle %p with comm %p source %d tag %d\n", early_data_handle, early_data_handle->node_tag.comm,
  126. early_data_handle->node_tag.rank, early_data_handle->node_tag.data_tag);
  127. struct _starpu_mpi_early_data_handle_hashlist *hashlist;
  128. HASH_FIND(hh, _starpu_mpi_early_data_handle_hashmap, &early_data_handle->node_tag, sizeof(struct _starpu_mpi_node_tag), hashlist);
  129. if (hashlist == NULL)
  130. {
  131. hashlist = malloc(sizeof(struct _starpu_mpi_early_data_handle_hashlist));
  132. hashlist->list = _starpu_mpi_early_data_handle_list_new();
  133. hashlist->node_tag = early_data_handle->node_tag;
  134. HASH_ADD(hh, _starpu_mpi_early_data_handle_hashmap, node_tag, sizeof(hashlist->node_tag), hashlist);
  135. }
  136. _starpu_mpi_early_data_handle_list_push_back(hashlist->list, early_data_handle);
  137. _starpu_mpi_early_data_handle_hashmap_count ++;
  138. #ifdef STARPU_VERBOSE
  139. _starpu_mpi_early_data_handle_display_hash(&hashlist->node_tag);
  140. #endif
  141. }
  142. void _starpu_mpi_early_data_delete(struct _starpu_mpi_early_data_handle *early_data_handle)
  143. {
  144. _STARPU_MPI_DEBUG(60, "Trying to delete early_data_handle %p with comm %p source %d tag %d\n", early_data_handle, early_data_handle->node_tag.comm,
  145. early_data_handle->node_tag.rank, early_data_handle->node_tag.data_tag);
  146. struct _starpu_mpi_early_data_handle *found = _starpu_mpi_early_data_pop(&early_data_handle->node_tag, 1);
  147. STARPU_ASSERT_MSG(found == early_data_handle,
  148. "[_starpu_mpi_early_data_delete][error] early_data_handle %p with comm %p source %d tag %d is NOT available\n",
  149. early_data_handle, early_data_handle->node_tag.comm, early_data_handle->node_tag.rank, early_data_handle->node_tag.data_tag);
  150. _starpu_mpi_early_data_handle_hashmap_count --;
  151. #ifdef STARPU_VERBOSE
  152. _starpu_mpi_early_data_handle_display_hash(&early_data_handle->node_tag);
  153. #endif
  154. }