Arcane  v3.16.7.0
Documentation utilisateur
Chargement...
Recherche...
Aucune correspondance
MpiMachineMemoryWindowBaseInternal.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2025 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/* MpiMachineMemoryWindowBaseInternal.h (C) 2000-2025 */
9/* */
10/* Classe permettant de créer une fenêtre mémoire pour un noeud */
11/* de calcul avec MPI. Cette fenêtre sera contigüe pour tous les processus */
12/* d'un même noeud. */
13/*---------------------------------------------------------------------------*/
14
15#include "arccore/message_passing_mpi/internal/MpiMachineMemoryWindowBaseInternal.h"
16
17#include "arccore/base/FatalErrorException.h"
18
19/*---------------------------------------------------------------------------*/
20/*---------------------------------------------------------------------------*/
21
22namespace Arcane::MessagePassing::Mpi
23{
24
25/*---------------------------------------------------------------------------*/
26/*---------------------------------------------------------------------------*/
27
28MpiMachineMemoryWindowBaseInternal::
29MpiMachineMemoryWindowBaseInternal(Int64 sizeof_segment, Int32 sizeof_type, const MPI_Comm& comm_machine, Int32 comm_machine_rank, Int32 comm_machine_size, ConstArrayView<Int32> machine_ranks)
30: m_win()
31, m_win_sizeof_segments()
32, m_win_sum_sizeof_segments()
33, m_comm_machine(comm_machine)
34, m_comm_machine_size(comm_machine_size)
35, m_comm_machine_rank(comm_machine_rank)
36, m_sizeof_type(sizeof_type)
37, m_machine_ranks(machine_ranks)
38, m_actual_sizeof_win(-1)
39{
40 // Toutes les fenêtres de cette classe doivent être contigües.
41 MPI_Info win_info;
42 MPI_Info_create(&win_info);
43 MPI_Info_set(win_info, "alloc_shared_noncontig", "false");
44
45 // On alloue la fenêtre principale (qui contiendra les données de l'utilisateur.
46 // On ne récupère pas le pointeur vers le segment.
47 {
48 void* ptr_seg = nullptr;
49 int error = MPI_Win_allocate_shared(sizeof_segment, m_sizeof_type, win_info, m_comm_machine, &ptr_seg, &m_win);
50
51 if (error != MPI_SUCCESS) {
52 ARCCORE_FATAL("Error with MPI_Win_allocate_shared() call");
53 }
54 }
55
56 //--------------------------
57
58 // On alloue la fenêtre qui contiendra la taille de chaque segment de la
59 // fenêtre principale.
60 {
61 Int64* ptr_seg = nullptr;
62 int error = MPI_Win_allocate_shared(sizeof(Int64), sizeof(Int64), win_info, m_comm_machine, &ptr_seg, &m_win_sizeof_segments);
63
64 if (error != MPI_SUCCESS) {
65 ARCCORE_FATAL("Error with MPI_Win_allocate_shared() call");
66 }
67 // On utilise le pointeur vers notre segment pour mettre la taille de
68 // notre segment de la fenêtre principale.
69 *ptr_seg = sizeof_segment;
70 }
71
72 // On alloue la fenêtre qui contiendra la position de chaque segment de la
73 // fenêtre principale.
74 {
75 Int64* ptr_seg = nullptr;
76 int error = MPI_Win_allocate_shared(sizeof(Int64), sizeof(Int64), win_info, m_comm_machine, &ptr_seg, &m_win_sum_sizeof_segments);
77
78 if (error != MPI_SUCCESS) {
79 ARCCORE_FATAL("Error with MPI_Win_allocate_shared() call");
80 }
81 }
82
83 MPI_Info_free(&win_info);
84
85 MPI_Barrier(m_comm_machine);
86
87 //--------------------------
88
89#ifdef ARCCORE_DEBUG
90
91 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
92 // On crée une vue sur toute la fenêtre contenant les tailles.
93 // (la boucle est là uniquement en mode debug pour vérifier qu'on a bien
94 // des fenêtres contigües).
95 {
96 MPI_Aint size_seg;
97 int size_type;
98 Int64* ptr_seg = nullptr;
99 int error = MPI_Win_shared_query(m_win_sizeof_segments, i, &size_seg, &size_type, &ptr_seg);
100
101 if (error != MPI_SUCCESS) {
102 ARCCORE_FATAL("Error with MPI_Win_shared_query() call");
103 }
104 if (i == 0) {
105 m_sizeof_segments_span = SmallSpan<Int64>{ ptr_seg, m_comm_machine_size };
106 }
107
108 if (m_sizeof_segments_span.data() + i != ptr_seg) {
109 ARCCORE_FATAL("Pb d'adresse de segment");
110 }
111 if (m_sizeof_segments_span[i] != *ptr_seg) {
112 ARCCORE_FATAL("Pb taille de segment");
113 }
114 }
115
116 // On crée une vue sur toute la fenêtre contenant les positions des segments.
117 {
118 MPI_Aint size_seg;
119 int size_type;
120 Int64* ptr_seg = nullptr;
121 int error = MPI_Win_shared_query(m_win_sum_sizeof_segments, i, &size_seg, &size_type, &ptr_seg);
122
123 if (error != MPI_SUCCESS) {
124 ARCCORE_FATAL("Error with MPI_Win_shared_query() call");
125 }
126 if (i == 0) {
127 m_sum_sizeof_segments_span = SmallSpan<Int64>{ ptr_seg, m_comm_machine_size };
128 }
129
130 if (m_sum_sizeof_segments_span.data() + i != ptr_seg) {
131 ARCCORE_FATAL("Pb d'adresse de segment");
132 }
133 }
134 }
135#else
136 // On crée une vue sur toute la fenêtre contenant les tailles.
137 {
138 MPI_Aint size_seg;
139 int size_type;
140 Int64* ptr_seg = nullptr;
141 int error = MPI_Win_shared_query(m_win_sizeof_segments, 0, &size_seg, &size_type, &ptr_seg);
142 if (error != MPI_SUCCESS) {
143 ARCCORE_FATAL("Error with MPI_Win_shared_query() call");
144 }
145
146 m_sizeof_segments_span = SmallSpan<Int64>{ ptr_seg, m_comm_machine_size };
147 }
148
149 // On crée une vue sur toute la fenêtre contenant les positions des segments.
150 {
151 MPI_Aint size_seg;
152 int size_type;
153 Int64* ptr_seg = nullptr;
154 int error = MPI_Win_shared_query(m_win_sum_sizeof_segments, 0, &size_seg, &size_type, &ptr_seg);
155
156 if (error != MPI_SUCCESS) {
157 ARCCORE_FATAL("Error with MPI_Win_shared_query() call");
158 }
159
160 m_sum_sizeof_segments_span = SmallSpan<Int64>{ ptr_seg, m_comm_machine_size };
161 }
162#endif
163
164 //--------------------------
165
166 // Seul le processus 0 doit remplir les positions.
167 // Tout le monde calcule la taille de la fenêtre principale.
168 if (m_comm_machine_rank == 0) {
169 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
170 m_sum_sizeof_segments_span[i] = m_max_sizeof_win;
171 m_max_sizeof_win += m_sizeof_segments_span[i];
172 }
173 }
174 else {
175 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
176 m_max_sizeof_win += m_sizeof_segments_span[i];
177 }
178 }
179
180 MPI_Barrier(m_comm_machine);
181
182 // La taille actuelle de la fenêtre est sa taille max.
183 // Utile en cas de resize.
184 m_actual_sizeof_win = m_max_sizeof_win;
185
186 //--------------------------
187
188#ifdef ARCCORE_DEBUG
189 Int64 sum = 0;
190
191 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
192 // On crée la vue vers la fenêtre principale.
193 // (la boucle est là uniquement en mode debug pour vérifier qu'on a bien
194 // une fenêtre contigüe).
195 MPI_Aint size_seg;
196 int size_type;
197 std::byte* ptr_seg = nullptr;
198 int error = MPI_Win_shared_query(m_win, i, &size_seg, &size_type, &ptr_seg);
199
200 if (error != MPI_SUCCESS) {
201 ARCCORE_FATAL("Error with MPI_Win_shared_query() call");
202 }
203 if (i == 0) {
204 m_window_span = Span<std::byte>{ ptr_seg, m_max_sizeof_win };
205 }
206
207 if (ptr_seg != (m_window_span.data() + sum)) {
208 ARCCORE_FATAL("Pb d'adresse de segment");
209 }
210 if (size_seg != m_sizeof_segments_span[i]) {
211 ARCCORE_FATAL("Pb taille de segment");
212 }
213 sum += size_seg;
214 }
215 if (sum != m_max_sizeof_win) {
216 ARCCORE_FATAL("Pb taille de window -- Expected : {0} -- Found : {1}", m_max_sizeof_win, sum);
217 }
218#else
219 // On crée la vue vers la fenêtre principale.
220 {
221 MPI_Aint size_seg;
222 int size_type;
223 std::byte* ptr_seg = nullptr;
224 int error = MPI_Win_shared_query(m_win, 0, &size_seg, &size_type, &ptr_seg);
225
226 if (error != MPI_SUCCESS) {
227 ARCCORE_FATAL("Error with MPI_Win_shared_query() call");
228 }
229
230 m_window_span = Span<std::byte>{ ptr_seg, m_max_sizeof_win };
231 }
232#endif
233}
234
235/*---------------------------------------------------------------------------*/
236/*---------------------------------------------------------------------------*/
237
238MpiMachineMemoryWindowBaseInternal::
239~MpiMachineMemoryWindowBaseInternal()
240{
241 MPI_Win_free(&m_win);
242 MPI_Win_free(&m_win_sizeof_segments);
243 MPI_Win_free(&m_win_sum_sizeof_segments);
244}
245
246/*---------------------------------------------------------------------------*/
247/*---------------------------------------------------------------------------*/
248
249Int32 MpiMachineMemoryWindowBaseInternal::
250sizeofOneElem() const
251{
252 return m_sizeof_type;
253}
254
255/*---------------------------------------------------------------------------*/
256/*---------------------------------------------------------------------------*/
257
258Span<std::byte> MpiMachineMemoryWindowBaseInternal::
259segmentView()
260{
261 const Int64 begin_segment = m_sum_sizeof_segments_span[m_comm_machine_rank];
262 const Int64 size_segment = m_sizeof_segments_span[m_comm_machine_rank];
263
264 return m_window_span.subSpan(begin_segment, size_segment);
265}
266
267/*---------------------------------------------------------------------------*/
268/*---------------------------------------------------------------------------*/
269
270Span<std::byte> MpiMachineMemoryWindowBaseInternal::
271segmentView(Int32 rank)
272{
273 Int32 pos = -1;
274 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
275 if (m_machine_ranks[i] == rank) {
276 pos = i;
277 break;
278 }
279 }
280 if (pos == -1) {
281 ARCCORE_FATAL("Rank is not in machine");
282 }
283
284 const Int64 begin_segment = m_sum_sizeof_segments_span[pos];
285 const Int64 size_segment = m_sizeof_segments_span[pos];
286
287 return m_window_span.subSpan(begin_segment, size_segment);
288}
289
290/*---------------------------------------------------------------------------*/
291/*---------------------------------------------------------------------------*/
292
293Span<std::byte> MpiMachineMemoryWindowBaseInternal::
294windowView()
295{
296 return m_window_span;
297}
298
299/*---------------------------------------------------------------------------*/
300/*---------------------------------------------------------------------------*/
301
302Span<const std::byte> MpiMachineMemoryWindowBaseInternal::
303segmentConstView() const
304{
305 const Int64 begin_segment = m_sum_sizeof_segments_span[m_comm_machine_rank];
306 const Int64 size_segment = m_sizeof_segments_span[m_comm_machine_rank];
307
308 return m_window_span.subSpan(begin_segment, size_segment);
309}
310
311/*---------------------------------------------------------------------------*/
312/*---------------------------------------------------------------------------*/
313
314Span<const std::byte> MpiMachineMemoryWindowBaseInternal::
315segmentConstView(Int32 rank) const
316{
317 Int32 pos = -1;
318 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
319 if (m_machine_ranks[i] == rank) {
320 pos = i;
321 break;
322 }
323 }
324 if (pos == -1) {
325 ARCCORE_FATAL("Rank is not in machine");
326 }
327
328 const Int64 begin_segment = m_sum_sizeof_segments_span[pos];
329 const Int64 size_segment = m_sizeof_segments_span[pos];
330
331 return m_window_span.subSpan(begin_segment, size_segment);
332}
333
334/*---------------------------------------------------------------------------*/
335/*---------------------------------------------------------------------------*/
336
337Span<const std::byte> MpiMachineMemoryWindowBaseInternal::
338windowConstView() const
339{
340 return m_window_span;
341}
342
343/*---------------------------------------------------------------------------*/
344/*---------------------------------------------------------------------------*/
345
346void MpiMachineMemoryWindowBaseInternal::
347resizeSegment(Int64 new_sizeof_segment)
348{
349 m_sizeof_segments_span[m_comm_machine_rank] = new_sizeof_segment;
350
351 MPI_Barrier(m_comm_machine);
352
353 if (m_comm_machine_rank == 0) {
354 Int64 sum = 0;
355 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
356 m_sum_sizeof_segments_span[i] = sum;
357 sum += m_sizeof_segments_span[i];
358 }
359 if (sum > m_max_sizeof_win) {
360 ARCCORE_FATAL("New size of window (sum of size of all segments) is superior than the old size");
361 }
362 m_actual_sizeof_win = sum;
363 }
364 else {
365 Int64 sum = 0;
366 for (Int32 i = 0; i < m_comm_machine_size; ++i) {
367 sum += m_sizeof_segments_span[i];
368 }
369 if (sum > m_max_sizeof_win) {
370 ARCCORE_FATAL("New size of window (sum of size of all segments) is superior than the old size");
371 }
372 m_actual_sizeof_win = sum;
373 }
374
375 m_window_span = Span<std::byte>{ m_window_span.data(), m_actual_sizeof_win };
376
377 MPI_Barrier(m_comm_machine);
378}
379
380/*---------------------------------------------------------------------------*/
381/*---------------------------------------------------------------------------*/
382
383ConstArrayView<Int32> MpiMachineMemoryWindowBaseInternal::
384machineRanks() const
385{
386 return m_machine_ranks;
387}
388
389/*---------------------------------------------------------------------------*/
390/*---------------------------------------------------------------------------*/
391
392void MpiMachineMemoryWindowBaseInternal::
393barrier() const
394{
395 MPI_Barrier(m_comm_machine);
396}
397
398/*---------------------------------------------------------------------------*/
399/*---------------------------------------------------------------------------*/
400
401} // namespace Arcane::MessagePassing::Mpi
402
403/*---------------------------------------------------------------------------*/
404/*---------------------------------------------------------------------------*/
std::int64_t Int64
Type entier signé sur 64 bits.
std::int32_t Int32
Type entier signé sur 32 bits.