15#include "arccore/message_passing_mpi/internal/MpiMultiMachineShMemWinBaseInternal.h"
17#include "arccore/base/FatalErrorException.h"
22namespace Arcane::MessagePassing::Mpi
34, m_comm_machine(comm_machine)
35, m_comm_machine_size(comm_machine_size)
36, m_comm_machine_rank(comm_machine_rank)
37, m_sizeof_type(sizeof_type)
38, m_nb_segments_per_proc(nb_segments_per_proc)
39, m_machine_ranks(machine_ranks)
43 if (m_sizeof_type <= 0) {
46 for (
Integer i = 0; i < m_nb_segments_per_proc; ++i) {
47 if (sizeof_segments[i] < 0 || sizeof_segments[i] % m_sizeof_type != 0) {
51 if (m_nb_segments_per_proc <= 0) {
54 m_all_mpi_win.resize(m_comm_machine_size * m_nb_segments_per_proc);
57 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
62 MPI_Info win_info_true;
63 MPI_Info_create(&win_info_true);
64 MPI_Info_set(win_info_true,
"alloc_shared_noncontig",
"true");
66 MPI_Info win_info_false;
67 MPI_Info_create(&win_info_false);
68 MPI_Info_set(win_info_false,
"alloc_shared_noncontig",
"false");
70 const Int32 pos_my_wins = m_comm_machine_rank * m_nb_segments_per_proc;
74 for (
Integer i = 0; i < m_comm_machine_size; ++i) {
75 for (
Integer j = 0; j < m_nb_segments_per_proc; ++j) {
77 if (m_comm_machine_rank == i) {
78 if (sizeof_segments[j] == 0)
79 size_seg = m_sizeof_type;
81 size_seg = sizeof_segments[j];
83 std::byte* ptr_seg =
nullptr;
84 int error = MPI_Win_allocate_shared(size_seg, m_sizeof_type, win_info_true, m_comm_machine, &ptr_seg, &
m_all_mpi_win[j + i * m_nb_segments_per_proc]);
86 if (error != MPI_SUCCESS) {
92 for (
Integer i = 0; i < m_nb_segments_per_proc; ++i) {
95 std::byte* ptr_seg =
nullptr;
96 int error = MPI_Win_shared_query(
m_all_mpi_win[i + pos_my_wins], m_comm_machine_rank, &size_seg, &
size_type, &ptr_seg);
98 if (error != MPI_SUCCESS) {
110 Int64* ptr_seg =
nullptr;
111 Int64* ptr_win =
nullptr;
113 int error = MPI_Win_allocate_shared(
static_cast<Int64>(
sizeof(
Int64)) * m_nb_segments_per_proc,
sizeof(
Int64), win_info_false, m_comm_machine, &ptr_seg, &
m_win_need_resize);
115 if (error != MPI_SUCCESS) {
124 if (error != MPI_SUCCESS) {
130 for (
Integer i = 0; i < m_nb_segments_per_proc; ++i) {
134 if (ptr_win + pos_my_wins != ptr_seg) {
140 Int64* ptr_seg =
nullptr;
141 Int64* ptr_win =
nullptr;
143 int error = MPI_Win_allocate_shared(
static_cast<Int64>(
sizeof(
Int64)) * m_nb_segments_per_proc,
sizeof(
Int64), win_info_false, m_comm_machine, &ptr_seg, &
m_win_actual_sizeof);
145 if (error != MPI_SUCCESS) {
154 if (error != MPI_SUCCESS) {
160 for (
Integer i = 0; i < m_nb_segments_per_proc; ++i) {
164 if (ptr_win + pos_my_wins != ptr_seg) {
170 Int32* ptr_seg =
nullptr;
171 Int32* ptr_win =
nullptr;
173 int error = MPI_Win_allocate_shared(
static_cast<Int64>(
sizeof(
Int32)) * m_nb_segments_per_proc,
sizeof(
Int32), win_info_false, m_comm_machine, &ptr_seg, &
m_win_target_segments);
175 if (error != MPI_SUCCESS) {
184 if (error != MPI_SUCCESS) {
190 for (
Integer i = 0; i < m_nb_segments_per_proc; ++i) {
194 if (ptr_win + pos_my_wins != ptr_seg) {
199 MPI_Info_free(&win_info_false);
200 MPI_Info_free(&win_info_true);
202 MPI_Barrier(m_comm_machine);
208MpiMultiMachineShMemWinBaseInternal::
209~MpiMultiMachineShMemWinBaseInternal()
211 for (
Integer i = 0; i < m_comm_machine_size * m_nb_segments_per_proc; ++i) {
225 return m_sizeof_type;
234 return m_machine_ranks;
243 MPI_Barrier(m_comm_machine);
252 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
262 const Int32 segment_infos_pos = num_seg + _worldToMachine(rank) * m_nb_segments_per_proc;
266 std::byte* ptr_seg =
nullptr;
267 int error = MPI_Win_shared_query(
m_all_mpi_win[segment_infos_pos], rank, &size_seg, &
size_type, &ptr_seg);
269 if (error != MPI_SUCCESS) {
282 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
292 const Int32 segment_infos_pos = num_seg + _worldToMachine(rank) * m_nb_segments_per_proc;
296 std::byte* ptr_seg =
nullptr;
297 int error = MPI_Win_shared_query(
m_all_mpi_win[segment_infos_pos], rank, &size_seg, &
size_type, &ptr_seg);
299 if (error != MPI_SUCCESS) {
312 if (elem.
size() % m_sizeof_type) {
315 if (elem.
empty() || elem.
data() ==
nullptr) {
319 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
322 const Int64 future_sizeof_win = actual_sizeof_win + elem.
size();
325 if (future_sizeof_win > old_reserved) {
333 m_add_requested =
true;
344 if (!m_add_requested) {
347 m_add_requested =
false;
349 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
354 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
363 for (
Int64 pos_win = actual_sizeof_win, pos_elem = 0; pos_win < future_sizeof_win; ++pos_win, ++pos_elem) {
378 if (elem.
size() % m_sizeof_type) {
381 if (elem.
empty() || elem.
data() ==
nullptr) {
385 const Int32 machine_rank = _worldToMachine(rank);
386 const Int32 target_segment_infos_pos = num_seg + machine_rank * m_nb_segments_per_proc;
389 const Int32 segment_infos_pos = thread + m_comm_machine_rank * m_nb_segments_per_proc;
396 std::byte* ptr_seg =
nullptr;
398 int error = MPI_Win_shared_query(
m_all_mpi_win[target_segment_infos_pos], machine_rank, &size_seg, &
size_type, &ptr_seg);
400 if (error != MPI_SUCCESS) {
407 const Int64 future_sizeof_win = actual_sizeof_win + elem.
size();
408 const Int64 old_reserved = rank_reserved_part_span.
size();
410 if (future_sizeof_win > old_reserved) {
418 m_add_requested =
true;
427 MPI_Barrier(m_comm_machine);
432 auto is_my_seg_edited = std::make_unique<bool[]>(m_comm_machine_size);
433 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
435 if (rank_asked == m_comm_machine_rank) {
436 is_my_seg_edited[num_seg] =
true;
445 if (!m_add_requested) {
450 m_add_requested =
false;
453 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
454 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
456 if (seg_needs_to_edit == -1)
459 bool is_found =
false;
461 if (rank_asked == seg_needs_to_edit) {
466 ARCCORE_FATAL(
"Two subdomains ask same rank for addToAnotherSegment()");
475 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
480 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
482 if (target_segment_infos_pos == -1) {
493 std::byte* ptr_seg =
nullptr;
495 int error = MPI_Win_shared_query(
m_all_mpi_win[target_segment_infos_pos], target_segment_infos_pos / m_nb_segments_per_proc, &size_seg, &
size_type, &ptr_seg);
497 if (error != MPI_SUCCESS) {
503 if (rank_reserved_part_span.
size() < future_sizeof_win) {
504 ARCCORE_FATAL(
"Bad realloc -- New size : {1} -- Needed size : {2}", rank_reserved_part_span.
size(), future_sizeof_win);
508 for (
Int64 pos_win = actual_sizeof_win, pos_elem = 0; pos_win < future_sizeof_win; ++pos_win, ++pos_elem) {
509 rank_reserved_part_span[pos_win] =
m_add_requests[num_seg][pos_elem];
517 MPI_Barrier(m_comm_machine);
520 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
521 if (is_my_seg_edited[num_seg]) {
522 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
525 std::byte* ptr_seg =
nullptr;
527 int error = MPI_Win_shared_query(
m_all_mpi_win[segment_infos_pos], m_comm_machine_rank, &size_seg, &
size_type, &ptr_seg);
529 if (error != MPI_SUCCESS) {
543 if (new_capacity % m_sizeof_type) {
547 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
572 if (new_size == -1) {
575 if (new_size < 0 || new_size % m_sizeof_type) {
579 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
589 m_resize_requested =
true;
600 if (!m_resize_requested) {
603 m_resize_requested =
false;
605 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
610 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
627 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
628 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
661void MpiMultiMachineShMemWinBaseInternal::
666 MPI_Barrier(m_comm_machine);
672 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
673 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
682 MPI_Barrier(m_comm_machine);
688void MpiMultiMachineShMemWinBaseInternal::
692 MPI_Info_create(&win_info);
693 MPI_Info_set(win_info,
"alloc_shared_noncontig",
"true");
696 for (
Integer rank = 0; rank < m_comm_machine_size; ++rank) {
697 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
699 const Int32 local_segment_infos_pos = num_seg + rank * m_nb_segments_per_proc;
704 ARCCORE_ASSERT(
m_need_resize[local_segment_infos_pos] >= 0, (
"New size must be >= 0"));
705 ARCCORE_ASSERT(
m_need_resize[local_segment_infos_pos] % m_sizeof_type == 0, (
"New size must be % sizeof type"));
709 const Int64 size_seg = (m_comm_machine_rank == rank ? (
m_need_resize[local_segment_infos_pos] == 0 ? m_sizeof_type :
m_need_resize[local_segment_infos_pos]) : 0);
713 std::byte* ptr_new_seg =
nullptr;
716 int error = MPI_Win_allocate_shared(size_seg, m_sizeof_type, win_info, m_comm_machine, &ptr_new_seg, &
m_all_mpi_win[local_segment_infos_pos]);
717 if (error != MPI_SUCCESS) {
718 MPI_Win_free(&old_win);
723 if (m_comm_machine_rank == rank) {
729 std::byte* ptr_old_seg =
nullptr;
730 MPI_Aint mpi_reserved_size_new_seg;
734 MPI_Aint size_old_seg;
738 error = MPI_Win_shared_query(old_win, m_comm_machine_rank, &size_old_seg, &size_type, &ptr_old_seg);
739 if (error != MPI_SUCCESS || ptr_old_seg ==
nullptr) {
740 MPI_Win_free(&old_win);
747 std::byte* ptr_seg =
nullptr;
751 error = MPI_Win_shared_query(
m_all_mpi_win[local_segment_infos_pos], m_comm_machine_rank, &mpi_reserved_size_new_seg, &size_type, &ptr_seg);
752 if (error != MPI_SUCCESS || ptr_seg ==
nullptr || ptr_seg != ptr_new_seg) {
753 MPI_Win_free(&old_win);
763 memcpy(ptr_new_seg, ptr_old_seg, min_size);
766 MPI_Win_free(&old_win);
769 MPI_Info_free(&win_info);
772 for (
Integer num_seg = 0; num_seg < m_nb_segments_per_proc; ++num_seg) {
773 const Int32 segment_infos_pos = num_seg + m_comm_machine_rank * m_nb_segments_per_proc;
777 std::byte* ptr_seg =
nullptr;
778 int error = MPI_Win_shared_query(
m_all_mpi_win[segment_infos_pos], m_comm_machine_rank, &size_seg, &size_type, &ptr_seg);
780 if (error != MPI_SUCCESS) {
791Int32 MpiMultiMachineShMemWinBaseInternal::
792_worldToMachine(
Int32 world)
const
794 for (
Int32 i = 0; i < m_comm_machine_size; ++i) {
795 if (m_machine_ranks[i] == world) {
805Int32 MpiMultiMachineShMemWinBaseInternal::
806_machineToWorld(
Int32 machine)
const
808 return m_machine_ranks[machine];
#define ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Vue constante d'un tableau de type T.
void requestAdd(Int32 num_seg, Span< const std::byte > elem)
Méthode permettant de demander l'ajout d'éléments dans l'un de nos segments.
Span< const std::byte > segmentConstView(Int32 num_seg) const
Méthode permettant d'obtenir une vue sur l'un de nos segments.
void executeResize()
Méthode permettant d'exécuter les requêtes de redimensionnement.
void executeShrink()
Méthode permettant de réduire l'espace mémoire réservé pour les segments au minimum nécessaire.
void requestReserve(Int32 num_seg, Int64 new_capacity)
Méthode permettant de demander la réservation d'espace mémoire pour un de nos segments.
void requestAddToAnotherSegment(Int32 thread, Int32 rank, Int32 num_seg, Span< const std::byte > elem)
Méthode permettant de demander l'ajout d'éléments dans un des segments de la fenêtre.
void executeReserve()
Méthode permettant d'exécuter les requêtes de réservation.
void _requestRealloc(Int32 owner_pos_segment, Int64 new_capacity) const
Méthode permettant de demander une réallocation.
MpiMultiMachineShMemWinBaseInternal(SmallSpan< Int64 > sizeof_segments, Int32 nb_segments_per_proc, Int32 sizeof_type, const MPI_Comm &comm_machine, Int32 comm_machine_rank, Int32 comm_machine_size, ConstArrayView< Int32 > machine_ranks)
Le sizeof_segments ne doit pas être conservé !
void executeAdd()
Méthode permettant d'exécuter les requêtes d'ajout.
void requestResize(Int32 num_seg, Int64 new_size)
Méthode permettant de demander le redimensionnement d'un de nos segments.
Span< Int32 > m_target_segments
void barrier() const
Méthode permettant d'attendre que tous les processus du noeud appellent cette méthode pour continuer ...
void executeAddToAnotherSegment()
Méthode permettant d'exécuter les requêtes d'ajout dans les segments d'autres processus.
MPI_Win m_win_actual_sizeof
Fenêtre contiguë avec taille des fenêtres principales.
UniqueArray< MPI_Win > m_all_mpi_win
Span< Int64 > m_need_resize
UniqueArray< Span< std::byte > > m_reserved_part_span
UniqueArray< Span< const std::byte > > m_add_requests
Int32 sizeofOneElem() const
Méthode permettant d'obtenir la taille d'un élement de la fenêtre.
UniqueArray< Int64 > m_resize_requests
Span< Int64 > m_sizeof_used_part
MPI_Win m_win_need_resize
Span< std::byte > segmentView(Int32 num_seg)
Méthode permettant d'obtenir une vue sur l'un de nos segments.
MPI_Win m_win_target_segments
ConstArrayView< Int32 > machineRanks() const
Méthode permettant d'obtenir les rangs qui possèdent un segment dans la fenêtre.
Vue d'un tableau d'éléments de type T.
constexpr __host__ __device__ pointer data() const noexcept
Pointeur sur le début de la vue.
constexpr __host__ __device__ bool empty() const noexcept
Retourne true si le tableau est vide (dimension nulle)
constexpr __host__ __device__ SizeType size() const noexcept
Retourne la taille du tableau.
Vue d'un tableau d'éléments de type T.
std::int64_t Int64
Type entier signé sur 64 bits.
Int32 Integer
Type représentant un entier.
std::int32_t Int32
Type entier signé sur 32 bits.