Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
BlockSizes.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#include <alien/utils/Precomp.h>
9#include <alien/index_manager/IIndexManager.h>
10#include "BlockSizes.h"
11
12#include <alien/utils/Precomp.h>
13#include <alien/utils/Trace.h>
14
15#include <arccore/message_passing/ISerializeMessageList.h>
16#include <arccore/message_passing/Messages.h>
17
18#include <map>
19#include <list>
20
21/*---------------------------------------------------------------------------*/
22/*---------------------------------------------------------------------------*/
23
24namespace Alien
25{
26
27/*---------------------------------------------------------------------------*/
28/*---------------------------------------------------------------------------*/
29
30BlockSizes::
31BlockSizes()
32: m_is_prepared(false)
33, m_local_size(0)
34, m_max_size(0)
35{
36 ;
37}
38
39/*---------------------------------------------------------------------------*/
40
42{
43 EntrySendRequest() {}
44
45 ~EntrySendRequest()
46 {}
47
48 Arccore::Ref<Arccore::MessagePassing::ISerializeMessage> m_comm;
49 Integer m_count = 0;
50};
51
53{
54 EntryRecvRequest()
55 {
56 ;
57 }
58
59 ~EntryRecvRequest()
60 {}
61
62 Arccore::Ref<Arccore::MessagePassing::ISerializeMessage> m_comm;
63 UniqueArray<Integer> m_ids;
64};
65
66void BlockSizes::
67prepare(const IIndexManager& index_mng, ConstArrayView<Integer> block_sizes)
68{
69 if (m_is_prepared)
70 throw FatalErrorException(A_FUNCINFO, "BlockSizes is already prepared");
71
72 m_parallel_mng = index_mng.parallelMng();
73
74 const Integer offset = index_mng.minLocalIndex();
75
76 const Integer size = block_sizes.size();
77
78 m_local_sizes.resize(size);
79 m_local_offsets.resize(size + 1);
80
81 Integer sum = 0, max_size = 0;
82 for (Integer i = 0; i < size; ++i) {
83 const Integer block_size = block_sizes[i];
84 max_size = (max_size > block_size) ? max_size : block_size;
85 const Integer index = i + offset;
86 m_sizes[index] = m_local_sizes[i] = block_size;
87 m_offsets[index] = m_local_offsets[i] = sum;
88 sum += block_size;
89 }
90 m_local_offsets[size] = sum;
91 m_max_size = max_size;
92 m_local_size = sum;
93 m_is_prepared = true;
94
95 const bool is_parallel = (m_parallel_mng != nullptr) && (m_parallel_mng->commSize() > 1);
96 if (not is_parallel)
97 return;
98
99 const Integer rank = m_parallel_mng->commRank();
100
101 typedef std::map<String, EntrySendRequest> SendRequestByEntry;
102 typedef std::map<Integer, SendRequestByEntry> SendRequests;
103 SendRequests sendRequests;
104
105 typedef SharedArray<Integer> Owners;
106 typedef std::map<String, Owners> OwnersByEntry;
107 OwnersByEntry owners_by_entry;
108
109 for (IIndexManager::EntryEnumerator e = index_mng.enumerateEntry(); e.hasNext(); ++e) {
110 //ConstArrayView<Integer> all_indexes = e->getAllIndexes();
111 ConstArrayView<Integer> all_lids = e->getAllLocalIds();
112 Owners owners = e->getFamily().owners(all_lids);
113 const String name = e->getName();
114 owners_by_entry[name] = owners;
115 for (Integer i = 0; i < owners.size(); ++i) {
116 if (owners[i] != rank)
117 sendRequests[owners[i]][name].m_count++;
118 }
119 }
120
121 //Arcane::ISerializeMessageList* messageList = m_parallel_mng->createSerializeMessageList();
122 Alien::Ref<ISerializeMessageList> messageList =
123 Arccore::MessagePassing::mpCreateSerializeMessageListRef(m_parallel_mng);
124
125 UniqueArray<Integer> sendToDomains(2 * m_parallel_mng->commSize(), 0);
126
127 for (SendRequests::iterator i = sendRequests.begin(); i != sendRequests.end(); ++i) {
128 const Integer destDomainId = i->first;
129 SendRequestByEntry& requests = i->second;
130 for (SendRequestByEntry::iterator j = requests.begin(); j != requests.end(); ++j) {
131 EntrySendRequest& request = j->second;
132 const String& nameString = j->first;
133 sendToDomains[2 * destDomainId + 0] += 1;
134 sendToDomains[2 * destDomainId + 1] += request.m_count;
135 request.m_comm = messageList->createAndAddMessage(MessageRank(destDomainId),
136 Arccore::MessagePassing::ePointToPointMessageType::MsgSend);
137 auto sbuf = request.m_comm->serializer();
138
139 sbuf->setMode(Alien::ISerializer::ModeReserve);
140 sbuf->reserve(nameString); // Chaine de caractère du nom de l'entrée
141 sbuf->reserveInteger(1); // Nb d'item
142 sbuf->reserve(Alien::ISerializer::DT_Int32, request.m_count); // Les indices demandés
143 sbuf->allocateBuffer();
144 sbuf->setMode(Alien::ISerializer::ModePut);
145 sbuf->put(nameString);
146 sbuf->put(request.m_count);
147 }
148 }
149
150 for (IIndexManager::EntryEnumerator e = index_mng.enumerateEntry(); e.hasNext(); ++e) {
151 const String name = e->getName();
152 Owners& owners = owners_by_entry[name];
153 ConstArrayView<Integer> all_indexes = e->getAllIndexes();
154 for (Integer i = 0; i < owners.size(); ++i) {
155 if (owners[i] != rank)
156 sendRequests[owners[i]][name].m_comm->serializer()->put(all_indexes[i]);
157 }
158 }
159
160 UniqueArray<Integer> recvFromDomains(2 * m_parallel_mng->commSize());
161 Arccore::MessagePassing::mpAllToAll(m_parallel_mng, sendToDomains, recvFromDomains, 2);
162
163 typedef std::list<EntryRecvRequest> RecvRequests;
164 RecvRequests recvRequests;
165
166 for (Integer isd = 0, nsd = m_parallel_mng->commSize(); isd < nsd; ++isd) {
167 Integer recvCount = recvFromDomains[2 * isd + 0];
168 while (recvCount-- > 0) {
169 auto recvMsg = messageList->createAndAddMessage(MessageRank(isd),
170 Arccore::MessagePassing::ePointToPointMessageType::MsgReceive);
171
172 recvRequests.push_back(EntryRecvRequest());
173 EntryRecvRequest& recvRequest = recvRequests.back();
174 recvRequest.m_comm = recvMsg;
175 }
176 }
177
178 messageList->processPendingMessages();
179 messageList->waitMessages(Arccore::MessagePassing::WaitAll);
180 messageList.reset();
181
182 messageList = Arccore::MessagePassing::mpCreateSerializeMessageListRef(m_parallel_mng);
183
184 for (RecvRequests::iterator i = recvRequests.begin(); i != recvRequests.end(); ++i) {
185 EntryRecvRequest& recvRequest = *i;
186 String nameString;
187 Integer uidCount;
188
189 {
190 //Arcane::SerializeBuffer& sbuf = recvRequest.comm->buffer();
191 //sbuf.setMode(Arcane::ISerializer::ModeGet);
192 auto sbuf = recvRequest.m_comm->serializer();
193 sbuf->setMode(Alien::ISerializer::ModeGet);
194
195 sbuf->get(nameString);
196 uidCount = sbuf->getInteger();
197 recvRequest.m_ids.resize(uidCount);
198 sbuf->get(recvRequest.m_ids);
199 ALIEN_ASSERT((uidCount == recvRequest.m_ids.size()), ("Inconsistency detected"));
200 }
201
202 {
203 auto dest = recvRequest.m_comm->destination(); // Attention à l'ordre bizarre
204 auto orig = recvRequest.m_comm->source(); // de SerializeMessage
205 recvRequest.m_comm.reset();
206 recvRequest.m_comm = messageList->createAndAddMessage(dest, Arccore::MessagePassing::ePointToPointMessageType::MsgSend);
207
208 //Arcane::SerializeBuffer & sbuf = recvRequest.comm->buffer();
209 auto sbuf = recvRequest.m_comm->serializer();
210
211 sbuf->setMode(Alien::ISerializer::ModeReserve);
212 sbuf->reserve(nameString); // Chaine de caractère du nom de l'entrée
213 sbuf->reserveInteger(1); // Nb d'item
214 sbuf->reserveInteger(uidCount); // Les tailles
215 sbuf->allocateBuffer();
216 sbuf->setMode(Alien::ISerializer::ModePut);
217 sbuf->put(nameString);
218 sbuf->put(uidCount);
219 }
220 }
221
222 for (RecvRequests::iterator i = recvRequests.begin(); i != recvRequests.end(); ++i) {
223 EntryRecvRequest& recvRequest = *i;
224 //Arcane::SerializeBuffer& sbuf = recvRequest.comm->buffer();
225 auto sbuf = recvRequest.m_comm->serializer();
226 auto& ids = recvRequest.m_ids;
227 for (Integer j = 0; j < ids.size(); ++j) {
228 sbuf->putInteger(block_sizes[ids[j] - offset]);
229 }
230 }
231
232 //typedef std::list<Arcane::SerializeMessage*> ReturnedRequests;
233 typedef std::list<Alien::Ref<Alien::ISerializeMessage>> ReturnedRequests;
234 ReturnedRequests returnedRequests;
235
236 typedef std::map<Integer, EntrySendRequest*> SubFastReturnMap;
237 typedef std::map<String, SubFastReturnMap> FastReturnMap;
238 FastReturnMap fastReturnMap;
239
240 for (SendRequests::iterator i = sendRequests.begin(); i != sendRequests.end(); ++i) {
241 const Integer destDomainId = i->first;
242 SendRequestByEntry& requests = i->second;
243 for (SendRequestByEntry::iterator j = requests.begin(); j != requests.end(); ++j) {
244 EntrySendRequest& request = j->second;
245 const String nameString = j->first;
246 //delete request.comm; request.comm = NULL;
247 request.m_comm.reset();
248 //Arcane::SerializeMessage * msg = new Arcane::SerializeMessage(parallel_mng->commRank(),destDomainId,Arcane::ISerializeMessage::MT_Recv);
249 auto msg = messageList->createAndAddMessage(MessageRank(destDomainId),
250 Arccore::MessagePassing::ePointToPointMessageType::MsgReceive);
251
252 returnedRequests.push_back(msg);
253
254 fastReturnMap[nameString][destDomainId] = &request;
255 }
256 }
257
258 messageList->processPendingMessages();
259 messageList->waitMessages(Arccore::MessagePassing::WaitAll);
260 messageList.reset();
261
262 for (ReturnedRequests::iterator i = returnedRequests.begin(); i != returnedRequests.end(); ++i) {
263 //Arcane::SerializeMessage * message = *i;
264 //const Integer origDomainId = message->destRank();
265 //Arcane::SerializeBuffer& sbuf = message->buffer();
266 auto& message = *i;
267 auto origDomainId = message->destination().value();
268 auto sbuf = message->serializer();
269 sbuf->setMode(Alien::ISerializer::ModeGet);
270 String nameString;
271 sbuf->get(nameString);
272 ALIEN_ASSERT((fastReturnMap[nameString][origDomainId] != NULL), ("Inconsistency detected"));
273 EntrySendRequest& request = *fastReturnMap[nameString][origDomainId];
274 request.m_comm = *i;
275 const Integer idCount = sbuf->getInteger();
276 ALIEN_ASSERT((request.m_count == idCount), ("Inconsistency detected"));
277 }
278
279 for (IIndexManager::EntryEnumerator e = index_mng.enumerateEntry(); e.hasNext(); ++e) {
280 ConstArrayView<Integer> all_indexes = e->getAllIndexes();
281 Owners owners = owners_by_entry[(*e).getName()];
282 for (Integer i = 0; i < owners.size(); ++i) {
283 const Integer index = all_indexes[i];
284 if (owners[i] != rank) {
285 EntrySendRequest& request = sendRequests[owners[i]][e->getName()];
286 ALIEN_ASSERT((request.m_count > 0), ("Unexpected empty request"));
287 --request.m_count;
288 const Integer block_size = request.m_comm->serializer()->getInteger();
289 m_sizes[index] = block_size;
290 m_max_size = (m_max_size > block_size) ? m_max_size : block_size;
291 m_offsets[index] = sum;
292 sum += block_size;
293 }
294 }
295 }
296
297 // for(IIndexManager::EntryEnumerator e = index_mng.enumerateEntry(); e.hasNext(); ++e) {
298 // ConstArrayView<Integer> all_indexes = e->getAllIndexes();
299 // for(Integer i = 0; i < all_indexes.size(); ++i) {
300 // const Integer index = all_indexes[i];
301 // trace->info() << "index=" << index << " size = " << m_sizes[index] << ", offset = " << m_offsets[index];
302 // }
303 // }
304
305 m_is_prepared = true;
306}
307
308/*---------------------------------------------------------------------------*/
309
310Integer
311BlockSizes::
312size(Integer index) const
313{
314 ALIEN_ASSERT((m_is_prepared), ("BlockSizes is not prepared"));
315
316 ValuePerBlock::const_iterator it = m_sizes.find(index);
317
318 if (it == m_sizes.end())
319 throw Alien::FatalErrorException(A_FUNCINFO, "index is not registered");
320
321 return it.value();
322}
323
324/*---------------------------------------------------------------------------*/
325
326Integer
327BlockSizes::
328sizeFromLocalIndex(Integer index) const
329{
330 //A. Anciaux
331 //ToDo pas faire une mapping --> aller vers un tableau pointeur
332 ALIEN_ASSERT((m_is_prepared), ("BlockSizes is not prepared"));
333
334 return m_local_sizes[index];
335}
336
337/*---------------------------------------------------------------------------*/
338
339Integer
340BlockSizes::
341offset(Integer index) const
342{
343 //A. Anciaux
344 //ToDo pas faire une mapping --> aller vers un tableau pointeur
345 ALIEN_ASSERT((m_is_prepared), ("BlockSizes is not prepared"));
346
347 ValuePerBlock::const_iterator it = m_offsets.find(index);
348
349 if (it == m_offsets.end())
350 throw Alien::FatalErrorException(A_FUNCINFO, "index is not registered");
351
352 return it.value();
353}
354
355/*---------------------------------------------------------------------------*/
356
357Integer
358BlockSizes::
359offsetFromLocalIndex(Integer index) const
360{
361 ALIEN_ASSERT((m_is_prepared), ("BlockSizes is not prepared"));
362
363 return m_local_offsets[index];
364}
365
366/*---------------------------------------------------------------------------*/
367
368Integer
369BlockSizes::
370localSize() const
371{
372 ALIEN_ASSERT((m_is_prepared), ("BlockSizes is not prepared"));
373
374 return m_local_size;
375}
376
377/*---------------------------------------------------------------------------*/
378
379Integer
380BlockSizes::
381maxSize() const
382{
383 ALIEN_ASSERT((m_is_prepared), ("BlockSizes is not prepared"));
384
385 return m_max_size;
386}
387
388/*---------------------------------------------------------------------------*/
389
390ConstArrayView<Integer>
391BlockSizes::
392sizeOfLocalIndex() const
393{
394 return m_local_sizes;
395}
396
397/*---------------------------------------------------------------------------*/
398
399ConstArrayView<Integer>
400BlockSizes::
401offsetOfLocalIndex() const
402{
403 return m_local_offsets;
404}
405
406/*---------------------------------------------------------------------------*/
407/*---------------------------------------------------------------------------*/
408
409} // namespace Alien
410
411/*---------------------------------------------------------------------------*/
412/*---------------------------------------------------------------------------*/
Classe d'énumération des Entry connues.
bool hasNext() const
Teste l'existence d'un élément suivant.
virtual Arccore::Integer minLocalIndex() const =0
Retourne l'indice minimum local.
virtual Alien::IMessagePassingMng * parallelMng() const =0
Donne le gestionnaire parallèle ayant servi à l'indexation.
virtual EntryEnumerator enumerateEntry() const =0
Construction d'un enumerateur sur les Entry.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17