Alien  1.3.0
Developer documentation
Loading...
Searching...
No Matches
IndexManager.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 <algorithm>
9#include <list>
10#include <map>
11#include <utility>
12#include <vector>
13
14#include <arccore/message_passing/ISerializeMessageList.h>
15#include <arccore/message_passing/Messages.h>
16
17#include <alien/index_manager/IAbstractFamily.h>
18#include <alien/index_manager/IndexManager.h>
19#include <alien/utils/Precomp.h>
20#include <alien/utils/Trace.h>
21
22/*---------------------------------------------------------------------------*/
23/*---------------------------------------------------------------------------*/
24
25namespace Alien
26{
27
28/*---------------------------------------------------------------------------*/
29/*---------------------------------------------------------------------------*/
30
32{
33 explicit EntryLocalId(Alien::Integer size)
34 : m_is_defined(size, false)
35 {}
36
37 void reserveLid(const Integer count)
38 {
39 m_defined_lids.reserve(m_defined_lids.size() + count);
40 }
41
42 [[nodiscard]] bool isDefinedLid(const Integer localId) const
43 {
44 return m_is_defined[localId];
45 }
46
47 void defineLid(const Integer localId, const Integer pos)
48 {
49 m_is_defined[localId] = true;
50 Alien::add(m_defined_lids, std::make_pair(localId, pos));
51 }
52
53 void undefineLid(const Integer localId)
54 {
55 m_is_defined[localId] = false;
56 for (Integer i = 0; i < m_defined_lids.size(); ++i) {
57 if (m_defined_lids[i].first == localId) {
58 m_defined_lids[i] = m_defined_lids.back();
59 m_defined_lids.resize(m_defined_lids.size() - 1);
60 return;
61 }
62 }
63 throw FatalErrorException(
64 A_FUNCINFO, "Inconsistent state : cannot find id to remove");
65 }
66
67 [[nodiscard]] const UniqueArray<std::pair<Integer, Integer>>& definedLids() const
68 {
69 return m_defined_lids;
70 }
71
72 void freeDefinedLids()
73 {
74 Alien::freeData(m_defined_lids);
75 std::vector<bool>().swap(m_is_defined);
76 }
77
78 std::vector<bool> m_is_defined;
79 UniqueArray<std::pair<Integer, Integer>> m_defined_lids;
80};
81
82/*---------------------------------------------------------------------------*/
83/*---------------------------------------------------------------------------*/
84
86{
87 EntrySendRequest() = default;
88
89 ~EntrySendRequest() = default;
90
91 EntrySendRequest(const EntrySendRequest& esr)
92 : count(esr.count)
93 {}
94
95 Arccore::Ref<Arccore::MessagePassing::ISerializeMessage> comm;
96 Integer count = 0;
97
98 void operator=(const EntrySendRequest&) = delete;
99};
100
101/*---------------------------------------------------------------------------*/
102
104{
105 EntryRecvRequest() = default;
106
107 ~EntryRecvRequest() = default;
108
109 explicit EntryRecvRequest(const EntrySendRequest& err) {}
110
111 Arccore::Ref<Arccore::MessagePassing::ISerializeMessage> comm;
112 UniqueArray<Int64> ids;
113
114 void operator=(const EntryRecvRequest&) = delete;
115};
116
117/*---------------------------------------------------------------------------*/
118/*---------------------------------------------------------------------------*/
119
120IndexManager::IndexManager(
121Alien::IMessagePassingMng* parallelMng, Alien::ITraceMng* traceMng)
122: m_parallel_mng(parallelMng)
123, m_trace_mng(traceMng)
124, m_local_owner(0)
125, m_state(Undef)
126, m_verbose(false)
127, m_local_entry_count(0)
128, m_global_entry_count(0)
129, m_global_entry_offset(0)
130, m_local_removed_entry_count(0)
131, m_global_removed_entry_count(0)
132, m_max_null_index_opt(false)
133{
134 this->init();
135}
136
137/*---------------------------------------------------------------------------*/
138/*---------------------------------------------------------------------------*/
139
140IndexManager::~IndexManager()
141{
142 this->init();
143}
144
145/*---------------------------------------------------------------------------*/
146
148{
149 m_local_owner = m_parallel_mng->commRank();
150
151 m_state = Initialized;
152
153 m_local_entry_count = 0;
154 m_global_entry_count = 0;
155 m_global_entry_offset = 0;
156 m_local_removed_entry_count = 0;
157 m_global_removed_entry_count = 0;
158
159 // Destruction des structure de type entry
160 for (auto& m_entrie : m_entries) {
161 delete m_entrie;
162 }
163 m_entries.clear();
164
165 m_abstract_families.clear();
166}
167
168/*---------------------------------------------------------------------------*/
169
170void IndexManager::setVerboseMode(bool verbose)
171{
172 m_verbose = verbose;
173}
174
175/*---------------------------------------------------------------------------*/
176
177ScalarIndexSet
178IndexManager::buildEntry(
179const String& name, const IAbstractFamily* family, const Integer kind)
180{
181 if (m_state != Initialized)
182 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
183
184 for (auto* e : m_entries) {
185 if (name == e->getName())
186 throw FatalErrorException(A_FUNCINFO, "Already defined entry");
187 }
188
189 const Integer uid = m_entries.size();
190
191 m_entry_families[uid] = family;
192
193 auto* entry = new ScalarIndexSet(name, uid, this, kind);
194
195 m_entries.push_back(entry);
196
197 return *entry;
198}
199
200/*---------------------------------------------------------------------------*/
201
202void IndexManager::defineIndex(const ScalarIndexSet& entry, ConstArrayView<Integer> localIds)
203{
204 if (m_state != Initialized)
205 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
206
207 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
208
209 const Integer uid = entry.getUid();
210
211 const auto* family = m_entry_families[uid];
212
213 auto entry_local_ids = std::make_shared<EntryLocalId>(family->maxLocalId());
214
215 m_entry_local_ids[uid] = entry_local_ids;
216
217 auto owners = family->owners(localIds);
218
219 entry_local_ids->reserveLid(localIds.size());
220 for (Integer i = 0, is = localIds.size(); i < is; ++i) {
221 const Integer localId = localIds[i];
222 if (not entry_local_ids->isDefinedLid(localId)) { // nouvelle entrée
223 if (owners[i] == m_local_owner) {
224 entry_local_ids->defineLid(
225 localId, +(m_local_removed_entry_count + m_local_entry_count++));
226 }
227 else {
228 entry_local_ids->defineLid(
229 localId, -(m_global_removed_entry_count + (++m_global_entry_count)));
230 }
231 }
232 }
233}
234
235/*---------------------------------------------------------------------------*/
236
237void IndexManager::removeIndex(const ScalarIndexSet& entry, ConstArrayView<Integer> localIds)
238{
239 if (m_state != Initialized)
240 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
241
242 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
243
244 const Integer uid = entry.getUid();
245
246 const auto* family = m_entry_families[uid];
247
248 auto entry_local_ids = m_entry_local_ids[uid];
249
250 const auto owners = family->owners(localIds);
251
252 for (Integer localId : localIds) {
253 if (entry_local_ids->isDefinedLid(localId)) {
254 entry_local_ids->undefineLid(localId);
255 if (owners[localId] == m_local_owner) {
256 --m_local_entry_count;
257 ++m_local_removed_entry_count;
258 }
259 else {
260 --m_global_entry_count;
261 ++m_global_removed_entry_count;
262 }
263 }
264 }
265}
266
267/*---------------------------------------------------------------------------*/
268
270{
271 EntryIndexMap entry_index;
272
273 begin_prepare(entry_index);
274
275 if (m_parallel_mng->commSize() > 1) {
276 begin_parallel_prepare(entry_index);
277 end_parallel_prepare(entry_index);
278 }
279 else {
280 sequential_prepare(entry_index);
281 }
282
283 end_prepare(entry_index);
284}
285
286/*---------------------------------------------------------------------------*/
287
288void IndexManager::begin_prepare(EntryIndexMap& entry_index)
289{
290 if (m_state != Initialized)
291 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
292
293 Integer total_size = 0;
294 for (auto* entry : m_entries) {
295 auto entry_local_ids = m_entry_local_ids[entry->getUid()];
296 total_size += entry_local_ids->definedLids().size();
297 }
298
299 entry_index.reserve(total_size);
300
301 for (auto* entry : m_entries) {
302 const Integer entry_uid = entry->getUid();
303 const auto* family = m_entry_families[entry_uid];
304 const Integer entry_kind = entry->getKind();
305 auto entry_local_ids = m_entry_local_ids[entry_uid];
306 const auto& lids = entry_local_ids->definedLids();
307 for (Integer i = 0, is = lids.size(); i < is; ++i) {
308 const Integer item_localid = lids[i].first;
309 auto item = family->item(item_localid);
310 entry_index.push_back(InternalEntryIndex{ entry_uid, entry_kind, item.uniqueId(),
311 item_localid, lids[i].second, item.owner() });
312 }
313 entry_local_ids->freeDefinedLids();
314 }
315
316 m_entry_local_ids.clear();
317
318 // Tri par défaut
319 std::sort(entry_index.begin(), entry_index.end(),
320 [](const InternalEntryIndex& a, const InternalEntryIndex& b) {
321 if (a.m_entry_kind != b.m_entry_kind)
322 return a.m_entry_kind < b.m_entry_kind;
323 else if (a.m_item_uid != b.m_item_uid)
324 return a.m_item_uid < b.m_item_uid;
325 else
326 return a.m_entry_uid < b.m_entry_uid;
327 });
328 ALIEN_ASSERT(
329 ((Integer)entry_index.size() == m_local_entry_count + m_global_entry_count),
330 ("Inconsistent global size"));
331}
332
333/*---------------------------------------------------------------------------*/
334
335void IndexManager::end_prepare(EntryIndexMap& entryIndex)
336{
337 // Calcul de la taille des indices par entrée
338 std::map<Integer, Integer> count_table;
339 for (auto& i : entryIndex) {
340 count_table[i.m_entry_uid]++;
341 }
342
343 auto isOwn = [&](const InternalEntryIndex& i) -> bool {
344 return i.m_item_owner == m_local_owner;
345 };
346
347 // Dimensionnement des buffers de chaque entrée
348 for (auto* entry : m_entries) {
349 const Integer uid = entry->getUid();
350 const Integer size = count_table[uid];
351 auto& all_items = m_entry_all_items[uid];
352 auto& all_indices = m_entry_all_indices[uid];
353
354 all_items.resize(size);
355 all_indices.resize(size);
356
357 Integer own_i = 0;
358 Integer ghost_i = size;
359 for (auto& i : entryIndex) {
360 if (i.m_entry_uid == uid) {
361 const Integer local_id = i.m_item_localid;
362 const Integer index = i.m_item_index;
363 const bool is_own = isOwn(i);
364 if (is_own) {
365 all_items[own_i] = local_id;
366 all_indices[own_i] = index;
367 ++own_i;
368 }
369 else {
370 --ghost_i;
371 all_items[ghost_i] = local_id;
372 all_indices[ghost_i] = index;
373 }
374 }
375 }
376
377 const Integer own_size = own_i;
378 ALIEN_ASSERT((own_i == ghost_i), ("Not merged insertion"));
379
380 m_entry_own_items[uid] = ConstArrayView<Integer>(own_size, &all_items[0]);
381 m_entry_own_indices[uid] = ConstArrayView<Integer>(own_size, &all_indices[0]);
382 }
383
384 m_state = Prepared;
385
386 if (m_verbose) {
387 alien_info([&] {
388 cout() << "Entry ordering :";
389 for (auto* entry : m_entries) {
390 cout() << "\tEntry '" << entry->getName() << "' placed at rank "
391 << entry->getUid() << " with " << getOwnLocalIds(*entry).size()
392 << " local / " << getAllLocalIds(*entry).size() << " global indexes ";
393 }
394 cout() << "Total local Entry indexes = " << m_local_entry_count;
395 });
396 }
397}
398
399/*---------------------------------------------------------------------------*/
400/*---------------------------------------------------------------------------*/
401
403{
404 // Structure pour accumuler et structurer la collecte de l'information
405 typedef std::map<Integer, EntrySendRequest> SendRequestByEntry;
406 typedef std::map<Integer, SendRequestByEntry> SendRequests;
407 SendRequests sendRequests;
408
409 // Table des requetes exterieures (reçoit les uid et renverra les EntryIndex finaux)
410 typedef std::list<EntryRecvRequest> RecvRequests;
411 RecvRequests recvRequests;
412
413 Alien::Ref<ISerializeMessageList> messageList;
414};
415
416/*---------------------------------------------------------------------------*/
417/*---------------------------------------------------------------------------*/
418
419void IndexManager::begin_parallel_prepare(EntryIndexMap& entry_index)
420{
421
422 ALIEN_ASSERT((m_parallel_mng->commSize() > 1), ("Parallel mode expected"));
423
424 /* Algorithme:
425 * 1 - listing des couples Entry-Item non locaux
426 * 2 - Envoi vers les propriétaires des items non locaux
427 * 3 - Prise en compte éventuelle de nouvelles entrées
428 * 4 - Nommage locales
429 * 5 - Retour vers demandeurs des EntryIndex non locaux
430 * 6 - Finalisation de la numérotation (table reindex)
431 */
432
433 parallel = std::make_shared<ParallelRequests>();
434
435 // 1 - Comptage des Items non locaux
436 for (auto& entryIndex : entry_index) {
437 const Integer item_owner = entryIndex.m_item_owner;
438 if (item_owner != m_local_owner) {
439 parallel->sendRequests[item_owner][entryIndex.m_entry_uid].count++;
440 }
441 }
442
443 // Liste de synthèse des messages (emissions / réceptions)
444 parallel->messageList =
445 Arccore::MessagePassing::mpCreateSerializeMessageListRef(m_parallel_mng);
446
447 // Contruction de la table de communications + préparation des messages d'envoi
448 UniqueArray<Integer> sendToDomains(2 * m_parallel_mng->commSize(), 0);
449
450 for (auto i = parallel->sendRequests.begin(); i != parallel->sendRequests.end(); ++i) {
451 const Integer destDomainId = i->first;
452 auto& requests = i->second;
453 for (auto& j : requests) {
454 EntrySendRequest& request = j.second;
455 const Integer entryImpl = j.first;
456 const String nameString = m_entries[entryImpl]->getName();
457
458 // Données pour receveur
459 sendToDomains[2 * destDomainId + 0] += 1;
460 sendToDomains[2 * destDomainId + 1] += request.count;
461
462 // Construction du message du EntrySendRequest
463 request.comm = parallel->messageList->createAndAddMessage(MessageRank(destDomainId),
464 Arccore::MessagePassing::ePointToPointMessageType::MsgSend);
465
466 auto sbuf = request.comm->serializer();
467 sbuf->setMode(Alien::ISerializer::ModeReserve); // phase préparatoire
468 sbuf->reserve(nameString); // Chaine de caractère du nom de l'entrée
469 sbuf->reserveInteger(1); // Nb d'item
470 sbuf->reserve(Alien::ISerializer::DT_Int64, request.count); // Les uid
471 sbuf->allocateBuffer(); // allocation mémoire
472 sbuf->setMode(Alien::ISerializer::ModePut);
473 sbuf->put(nameString);
474 sbuf->put(request.count);
475 }
476 }
477
478 // 2 - Accumulation des valeurs à demander
479
480 for (auto& entryIndex : entry_index) {
481 const Integer entryImpl = entryIndex.m_entry_uid;
482 const Integer item_owner = entryIndex.m_item_owner;
483 const Int64 item_uid = entryIndex.m_item_uid;
484 if (item_owner != m_local_owner)
485 parallel->sendRequests[item_owner][entryImpl].comm->serializer()->put(item_uid);
486 }
487
488 // Réception des annonces de demandes (les nombres d'entrée + taille)
489
490 UniqueArray<Integer> recvFromDomains(2 * m_parallel_mng->commSize());
491 Arccore::MessagePassing::mpAllToAll(m_parallel_mng, sendToDomains, recvFromDomains, 2);
492
493 for (Integer isd = 0, nsd = m_parallel_mng->commSize(); isd < nsd; ++isd) {
494 Integer recvCount = recvFromDomains[2 * isd + 0];
495 while (recvCount-- > 0) {
496 auto recvMsg = parallel->messageList->createAndAddMessage(MessageRank(isd),
497 Arccore::MessagePassing::ePointToPointMessageType::MsgReceive);
498 parallel->recvRequests.push_back(EntryRecvRequest());
499 EntryRecvRequest& recvRequest = parallel->recvRequests.back();
500 recvRequest.comm = recvMsg;
501 }
502 }
503
504 // Traitement des communications
505 parallel->messageList->processPendingMessages();
506 parallel->messageList->waitMessages(Arccore::MessagePassing::WaitAll);
507 parallel->messageList.reset();
508 // delete parallel->messageList;
509 // parallel->messageList = NULL; // Destruction propre
510
511 // Pour les réponses vers les demandeurs
512 parallel->messageList =
513 Arccore::MessagePassing::mpCreateSerializeMessageListRef(m_parallel_mng);
514
515 // 3 - Réception et mise en base local des demandes
516 for (auto i = parallel->recvRequests.begin(); i != parallel->recvRequests.end(); ++i) {
517 auto& recvRequest = *i;
518 String nameString;
519 Integer uidCount;
520
521 { // Traitement des arrivées
522 auto sbuf = recvRequest.comm->serializer();
523 sbuf->setMode(Alien::ISerializer::ModeGet);
524
525 sbuf->get(nameString);
526 uidCount = sbuf->getInteger();
527 recvRequest.ids.resize(uidCount);
528 sbuf->getSpan(recvRequest.ids);
529 ALIEN_ASSERT((uidCount == recvRequest.ids.size()), ("Inconsistency detected"));
530
531#ifndef NO_USER_WARNING
532#ifdef _MSC_VER
533#pragma message("CHECK: optimisable ?")
534#else
535#warning "CHECK: optimisable ?"
536#endif
537#endif
538 /* Si on est sûr que les entrées et l'item demandées doivent
539 * toujours exister (même les pires cas), on peut faire
540 * l'indexation locale avant et envoyer immédiatement (via un
541 * buffer; dans la présente boucle) la réponse.
542 */
543
544 // Reconstruction de l'entrée à partir du nom
545 auto lookup = std::find_if(m_entries.begin(), m_entries.end(),
546 [&](ScalarIndexSet* s) { return s->getName() == nameString; });
547
548 // Si pas d'entrée de ce côté => système défectueux ?
549 if (lookup == m_entries.end())
550 throw FatalErrorException("Non local Entry Requested : degenerated system ?");
551
552 auto* currentEntry = *lookup;
553 const Integer entry_uid = currentEntry->getUid();
554
555 // Passage de l'uid à l'item associé (travaille sur place : pas de recopie)
556 ArrayView<Int64> ids = recvRequest.ids;
557
558 const auto* family = m_entry_families[entry_uid];
559 const Integer entry_kind = currentEntry->getKind();
560 UniqueArray<Int32> lids(ids.size());
561 family->uniqueIdToLocalId(lids, ids);
562 // Vérification d'intégrité : toutes les entrées demandées sont définies localement
563 auto owners = family->owners(lids);
564 for (Integer j = 0; j < uidCount; ++j) {
565 const Integer current_item_lid = lids[j];
566 const Int64 current_item_uid = ids[j];
567 const Integer current_item_owner = owners[j];
568 if (current_item_owner != m_local_owner) {
569 throw FatalErrorException("Non local EntryIndex requested");
570 }
571 InternalEntryIndex lookup_entry{ entry_uid, entry_kind, current_item_uid,
572 current_item_lid, 0, current_item_owner };
573
574 // Recherche de la liste triée par défaut
575 auto lookup2 = std::lower_bound(entry_index.begin(), entry_index.end(),
576 lookup_entry, [](const InternalEntryIndex& a, const InternalEntryIndex& b) {
577 if (a.m_entry_kind != b.m_entry_kind)
578 return a.m_entry_kind < b.m_entry_kind;
579 else if (a.m_item_uid != b.m_item_uid)
580 return a.m_item_uid < b.m_item_uid;
581 else
582 return a.m_entry_uid < b.m_entry_uid;
583 });
584
585 if ((lookup2 == entry_index.end()) || !(*lookup2 == lookup_entry))
586 throw FatalErrorException("Not locally defined entry requested");
587
588 // Mise en place de la pre-valeur retour [avant renumérotation locale] (EntryIndex
589 // écrit sur un Int64)
590 ids[j] = lookup2->m_item_index;
591 }
592 }
593
594 { // Préparation des retours
595 auto dest = recvRequest.comm->destination(); // Attention à l'ordre bizarre
596 auto orig = recvRequest.comm->source(); // de SerializeMessage
597 recvRequest.comm.reset();
598 recvRequest.comm = parallel->messageList->createAndAddMessage(dest,
599 Arccore::MessagePassing::ePointToPointMessageType::MsgSend);
600
601 auto sbuf = recvRequest.comm->serializer();
602 sbuf->setMode(Alien::ISerializer::ModeReserve); // phase préparatoire
603 sbuf->reserve(nameString); // Chaine de caractère du nom de l'entrée
604 sbuf->reserveInteger(1); // Nb d'item
605 sbuf->reserveInteger(uidCount); // Les index
606 sbuf->allocateBuffer(); // allocation mémoire
607 sbuf->setMode(Alien::ISerializer::ModePut);
608 sbuf->put(nameString);
609 sbuf->put(uidCount);
610 }
611 }
612
613 // 4 - Indexation locale
614 /* La politique naive ici appliquée est de numéroter tous les
615 * (Entry,Item) locaux d'abord.
616 */
617 // Calcul de des offsets globaux sur Entry (via les tailles locales)
618 UniqueArray<Integer> allLocalSizes(m_parallel_mng->commSize());
619 UniqueArray<Integer> myLocalSize(1);
620 myLocalSize[0] = m_local_entry_count;
621 Arccore::MessagePassing::mpAllGather(m_parallel_mng, myLocalSize, allLocalSizes);
622
623 // Mise à jour du contenu des entrées
624 m_global_entry_offset = 0;
625 for (Integer i = 0; i < m_parallel_mng->commRank(); ++i) {
626 m_global_entry_offset += allLocalSizes[i];
627 }
628
629 // Calcul de la taille global d'indexation (donc du système associé)
630 m_global_entry_count = 0;
631 for (Integer i = 0; i < m_parallel_mng->commSize(); ++i) {
632 m_global_entry_count += allLocalSizes[i];
633 }
634}
635
636/*---------------------------------------------------------------------------*/
637
638void IndexManager::end_parallel_prepare(EntryIndexMap& entry_index)
639{
640 ALIEN_ASSERT((m_parallel_mng->commSize() > 1), ("Parallel mode expected"));
641
642 {
643 // Table de ré-indexation (EntryIndex->Integer)
644 Alien::UniqueArray<Integer> entry_reindex(m_local_entry_count);
645 Alien::fill(entry_reindex, -1); // valeur de type Erreur par défaut
646
647 // C'est ici et uniquement ici qu'est matérialisé l'ordre des entrées
648 Integer currentEntryIndex = m_global_entry_offset; // commence par l'offset local
649 for (auto& i : entry_index) {
650 if (i.m_item_owner == m_local_owner) { // Numérotation locale !
651 const Integer newIndex = currentEntryIndex++;
652 ALIEN_ASSERT(newIndex >= 0, "Invalid local id");
653 entry_reindex[i.m_item_index] = newIndex; // Table de translation
654 i.m_item_index = newIndex;
655 }
656 }
657
658 // 5 - Envoie des retours (EntryIndex globaux)
659 for (auto& recvRequest : parallel->recvRequests) {
660 auto sbuf = recvRequest.comm->serializer();
661 for (auto id : recvRequest.ids) {
662 sbuf->putInteger(entry_reindex[id]); // Via la table de réindexation
663 }
664 }
665 }
666 // Table des buffers de retour
667 typedef std::list<Alien::Ref<Alien::ISerializeMessage>> ReturnedRequests;
668 ReturnedRequests returnedRequests;
669
670 // Acces rapide aux buffers connaissant le proc emetteur et le nom d'une entrée
671 /* Car on ne peut tager les buffers donc l'entrée reçue dans un buffer est non
672 * déterminée
673 * surtout si 2 domaines se communiquent plus d'une entrée
674 */
675 typedef std::map<Integer, EntrySendRequest*> SubFastReturnMap;
676 typedef std::map<String, SubFastReturnMap> FastReturnMap;
677 FastReturnMap fastReturnMap;
678
679 // Préparation des réceptions [sens inverse]
680 for (auto i = parallel->sendRequests.begin(); i != parallel->sendRequests.end(); ++i) {
681 const Integer destDomainId = i->first;
682 auto& requests = i->second;
683 for (auto& j : requests) {
684 auto& request = j.second;
685 const Integer entryImpl = j.first;
686 const String nameString = m_entries[entryImpl]->getName();
687
688 // On ne peut pas associer directement le message à cette entrée
689 // : dans le cas d'échange multiple il n'y pas de garantie d'arrivée
690 // à la bonne place
691 // delete request.comm;
692 // request.comm = NULL;
693 request.comm.reset();
694
695 auto msg = parallel->messageList->createAndAddMessage(MessageRank(destDomainId),
696 Arccore::MessagePassing::ePointToPointMessageType::MsgReceive);
697
698 returnedRequests.push_back(msg);
699
700 fastReturnMap[nameString][destDomainId] = &request;
701 }
702 }
703
704 // Traitement des communications
705 parallel->messageList->processPendingMessages();
706
707 parallel->messageList->waitMessages(Arccore::MessagePassing::WaitAll);
708 parallel->messageList.reset();
709
710 // 6 - Traitement des réponses
711 // Association aux EntrySendRequest du buffer correspondant
712 for (auto& returnedRequest : returnedRequests) {
713 auto& message = returnedRequest;
714 auto origDomainId = message->destination().value();
715 auto sbuf = message->serializer();
716 sbuf->setMode(Alien::ISerializer::ModeGet);
717 String nameString;
718 sbuf->get(nameString);
719 ALIEN_ASSERT(
720 (fastReturnMap[nameString][origDomainId] != nullptr), ("Inconsistency detected"));
721 auto& request = *fastReturnMap[nameString][origDomainId];
722 request.comm =
723 returnedRequest; // Reconnection pour accès rapide depuis l'EntrySendRequest
724#ifdef ALIEN_DEBUG_ASSERT
725 const Integer idCount = sbuf.getInteger();
726 ALIEN_ASSERT((request.count == idCount), ("Inconsistency detected"));
727#else
728 const Integer idCount = sbuf->getInteger();
729 ALIEN_ASSERT((request.count == idCount), ("Inconsistency detected"));
730#endif
731 }
732
733 // Distribution des reponses
734 // Par parcours dans ordre initial (celui de la demande)
735 for (auto& entry : entry_index) {
736 const Integer item_owner = entry.m_item_owner;
737 if (item_owner != m_local_owner) {
738 const Integer entryImpl = entry.m_entry_uid;
739 auto& request = parallel->sendRequests[item_owner][entryImpl];
740 ALIEN_ASSERT((request.count > 0), ("Unexpected empty request"));
741 --request.count;
742 auto sbuf = request.comm->serializer();
743 const Integer newIndex = sbuf->getInteger();
744 entry.m_item_index = newIndex;
745 }
746 }
747}
748
749/*---------------------------------------------------------------------------*/
750
751void IndexManager::sequential_prepare(EntryIndexMap& entry_index)
752{
753 ALIEN_ASSERT((m_parallel_mng->commSize() <= 1), ("Sequential mode expected"));
754 ALIEN_ASSERT((m_global_entry_count == 0),
755 ("Unexpected global entries (%d)", m_global_entry_count));
756
757 // Très similaire à la section parallèle :
758 // 4 - Indexation locale
759 /* La politique naive ici appliquée est de numéroter tous les
760 * (Entry,Item) locaux d'abord.
761 */
762
763 // Mise à jour du contenu des entrées
764
765 // C'est ici et uniquement ici qu'est matérialisé l'ordre des entrées
766 Integer currentEntryIndex = 0; // commence par l'offset local
767 for (auto i = entry_index.begin(); i != entry_index.end(); ++i) {
768 ALIEN_ASSERT((i->m_item_owner == m_local_owner),
769 ("Item cannot be non-local for sequential mode"));
770 // Numérotation locale only !
771 const Integer newIndex = currentEntryIndex++;
772 i->m_item_index = newIndex;
773 }
774
775 m_global_entry_count = m_local_entry_count;
776}
777
778/*---------------------------------------------------------------------------*/
779
780UniqueArray<Integer>
782{
783 if (m_state != Prepared)
784 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
785
786 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
787 const IAbstractFamily& family = entry.getFamily();
788 UniqueArray<Integer> allIds(family.maxLocalId(), nullIndex());
789 const ConstArrayView<Integer> allIndices = getAllIndexes(entry);
790 const ConstArrayView<Integer> allLocalIds = getAllLocalIds(entry);
791 const Integer size = allIndices.size();
792 for (Integer i = 0; i < size; ++i)
793 allIds[allLocalIds[i]] = allIndices[i];
794 return allIds;
795}
796
797/*---------------------------------------------------------------------------*/
798
799UniqueArray2<Integer>
800IndexManager::getIndexes(const VectorIndexSet& entries) const
801{
802 if (m_state != Prepared)
803 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
804
805 Integer max_family_size = 0;
806 for (Integer i = 0; i < entries.size(); ++i) {
807 // controles uniquement en première passe
808 ALIEN_ASSERT(
809 (entries[i].manager() == this), ("Incompatible entry from another manager"));
810 const auto& entry = entries[i];
811 const IAbstractFamily& family = entry.getFamily();
812 max_family_size = std::max(max_family_size, family.maxLocalId());
813 }
814
815 UniqueArray2<Integer> allIds;
816 Alien::allocateData(allIds, max_family_size, entries.size());
817 Alien::fill(allIds, nullIndex());
818
819 for (Integer i = 0; i < entries.size(); ++i) {
820 const auto& entry = entries[i];
821 const ConstArrayView<Integer> allIndices = getAllIndexes(entry);
822 const ConstArrayView<Integer> allLocalIds = getAllLocalIds(entry);
823 const Integer size = allIndices.size();
824 for (Integer j = 0; j < size; ++j)
825 allIds[allLocalIds[j]][i] = allIndices[i];
826 }
827 return allIds;
828}
829
830/*---------------------------------------------------------------------------*/
831
832void IndexManager::stats(Integer& globalSize, Integer& minLocalIndex, Integer& localSize) const
833{
834 if (m_state != Prepared)
835 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
836
837 globalSize = m_global_entry_count;
838 minLocalIndex = m_global_entry_offset;
839 localSize = m_local_entry_count;
840}
841
842/*---------------------------------------------------------------------------*/
843
844Integer
845IndexManager::globalSize() const
846{
847 if (m_state != Prepared)
848 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
849
850 return m_global_entry_count;
851}
852
853/*---------------------------------------------------------------------------*/
854
855Integer
856IndexManager::minLocalIndex() const
857{
858 if (m_state != Prepared)
859 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
860
861 return m_global_entry_offset;
862}
863
864/*---------------------------------------------------------------------------*/
865
866Integer
867IndexManager::localSize() const
868{
869 if (m_state != Prepared)
870 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
871
872 return m_local_entry_count;
873}
874
875/*---------------------------------------------------------------------------*/
876
877ScalarIndexSet
879 ConstArrayView<Integer> localIds,
880 const IAbstractFamily& family,
881 Integer kind,
882 eKeepAlive alive)
883{
884 alien_debug([&] {
885 cout() << "IndexManager: build scalar index set '" << name << "', kind=" << kind;
886 });
887 ScalarIndexSet en = buildEntry(name, addNewAbstractFamily(&family, alive), kind);
888 defineIndex(en, localIds);
889 return en;
890}
891
892/*---------------------------------------------------------------------------*/
893
896const String& name, const IAbstractFamily& family, Integer kind, eKeepAlive alive)
897{
898 alien_debug([&] {
899 cout() << "IndexManager: build scalar index set '" << name << "', kind=" << kind;
900 });
901 auto localIds = family.allLocalIds();
902 ScalarIndexSet en = buildEntry(name, addNewAbstractFamily(&family, alive), kind);
903 defineIndex(en, localIds.view());
904 return en;
905}
906
907/*---------------------------------------------------------------------------*/
908
909IndexManager::VectorIndexSet
911 ConstArrayView<Integer> localIds,
912 const IAbstractFamily& family,
913 const UniqueArray<Integer>& kind,
914 eKeepAlive alive)
915{
916 alien_debug([&] {
917 cout() << "IndexManager: build vector index set '" << name
918 << "', size=" << kind.size();
919 });
920 const Integer size = kind.size();
921 VectorIndexSet ens(size);
922 const auto* f = addNewAbstractFamily(&family, alive);
923 for (Integer i = 0; i < size; ++i) {
924 ens[i] = buildEntry(Alien::format("{0}[{1}]", name, i), f, kind[i]);
925 defineIndex(ens[i], localIds);
926 }
927 return ens;
928}
929
930/*---------------------------------------------------------------------------*/
931
932IndexManager::VectorIndexSet
934 const IAbstractFamily& family,
935 const UniqueArray<Integer>& kind,
936 eKeepAlive alive)
937{
938 alien_debug([&] {
939 cout() << "IndexManager: build vector index set '" << name
940 << "', size=" << kind.size();
941 });
942 auto localIds = family.allLocalIds();
943 const Integer size = kind.size();
944 VectorIndexSet ens(size);
945 const auto* f = addNewAbstractFamily(&family, alive);
946 for (Integer i = 0; i < size; ++i) {
947 ens[i] = buildEntry(Alien::format("{0}[{1}]", name, i), f, kind[i]);
948 defineIndex(ens[i], localIds.view());
949 }
950 return ens;
951}
952
953/*---------------------------------------------------------------------------*/
954
955const IAbstractFamily*
956IndexManager::addNewAbstractFamily(const IAbstractFamily* family, eKeepAlive alive)
957{
958 auto finder = m_abstract_families.find(family);
959 if (finder == m_abstract_families.end()) // La famille n'est pas stockée, nouvelle famille
960 {
961 if (alive == eKeepAlive::DontClone) {
962 m_abstract_families[family] = std::shared_ptr<IAbstractFamily>();
963 return family;
964 }
965 else {
966 auto clone = std::shared_ptr<IAbstractFamily>(family->clone());
967 m_abstract_families[family] = clone;
968 // On remplace les familles des entrées
969 for (auto& f : m_entry_families) {
970 if (f.second == family)
971 f.second = clone.get();
972 }
973 return clone.get();
974 }
975 }
976 else // La famille est connue
977 {
978 if (finder->second) // Si clone, on le renvoit
979 return finder->second.get();
980 else { // Sinon, on crée éventuellement le clone
981 if (alive == eKeepAlive::DontClone) {
982 return family;
983 }
984 else {
985 auto clone = std::shared_ptr<IAbstractFamily>(family->clone());
986 m_abstract_families[family] = clone;
987 // On remplace les familles des entrées
988 for (auto& f : m_entry_families) {
989 if (f.second == family)
990 f.second = clone.get();
991 }
992 return clone.get();
993 }
994 }
995 }
996}
997
998/*---------------------------------------------------------------------------*/
999
1000ConstArrayView<Integer>
1001IndexManager::getOwnIndexes(const ScalarIndexSet& entry) const
1002{
1003 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
1004 if (m_state != Prepared)
1005 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
1006 auto it = m_entry_own_indices.find(entry.getUid());
1007 return it->second;
1008}
1009
1010/*---------------------------------------------------------------------------*/
1011
1012ConstArrayView<Integer>
1013IndexManager::getOwnLocalIds(const ScalarIndexSet& entry) const
1014{
1015 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
1016 if (m_state != Prepared)
1017 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
1018 auto it = m_entry_own_items.find(entry.getUid());
1019 return it->second;
1020}
1021
1022/*---------------------------------------------------------------------------*/
1023
1024ConstArrayView<Integer>
1025IndexManager::getAllIndexes(const ScalarIndexSet& entry) const
1026{
1027 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
1028 if (m_state != Prepared)
1029 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
1030 auto it = m_entry_all_indices.find(entry.getUid());
1031 return it->second;
1032}
1033
1034/*---------------------------------------------------------------------------*/
1035
1036ConstArrayView<Integer>
1037IndexManager::getAllLocalIds(const ScalarIndexSet& entry) const
1038{
1039 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
1040 if (m_state != Prepared)
1041 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
1042 auto it = m_entry_all_items.find(entry.getUid());
1043 return it->second;
1044}
1045
1046/*---------------------------------------------------------------------------*/
1047
1048const IAbstractFamily&
1049IndexManager::getFamily(const ScalarIndexSet& entry) const
1050{
1051 ALIEN_ASSERT((entry.manager() == this), ("Incompatible entry from another manager"));
1052 if (m_state != Prepared)
1053 throw FatalErrorException(A_FUNCINFO, "Inconsistent state");
1054 auto it = m_entry_families.find(entry.getUid());
1055 return *(it->second);
1056}
1057
1058/*---------------------------------------------------------------------------*/
1059
1061{
1062 m_max_null_index_opt = flag;
1063
1064 alien_debug(flag, [&] { cout() << "IndexManager: null index optimized enabled"; });
1065}
1066
1067/*---------------------------------------------------------------------------*/
1068
1069Integer
1070IndexManager::nullIndex() const
1071{
1072 ALIEN_ASSERT((m_state == Prepared), ("nullIndex is valid only in Prepared state"));
1073 if (m_max_null_index_opt)
1074 return m_global_entry_offset + m_local_entry_count;
1075 else
1076 return -1;
1077}
1078
1079/*---------------------------------------------------------------------------*/
1080/*---------------------------------------------------------------------------*/
1081} // namespace Alien
1082
1083/*---------------------------------------------------------------------------*/
1084/*---------------------------------------------------------------------------*/
Interface for abstract families of items.
virtual SafeConstArrayView< Int32 > allLocalIds() const =0
Local ids of this family members.
virtual Int32 maxLocalId() const =0
Max local Id for this family.
void init()
Initialisation.
Integer getUid() const
Creation label.
const IndexManager * manager() const
Associated index manager.
std::map< Integer, UniqueArray< Integer > > m_entry_all_items
Local ids, sorted by owned then ghosts. By entry.
IMessagePassingMng * parallelMng() const
Parallel Manager used for the index computation.
UniqueArray< Integer > getIndexes(const ScalarIndexSet &entry) const
Give a translation table, indexed by items.
std::map< Integer, ConstArrayView< Integer > > m_entry_own_indices
Unique ids, only for owned, by entry.
std::map< const IAbstractFamily *, std::shared_ptr< IAbstractFamily > > m_abstract_families
Abstract families and associated clones (if handled).
void setMaxNullIndexOpt(bool flag)
define null index : default = -1, if true null_index = max_index+1
ScalarIndexSet buildScalarIndexSet(const String &name, ConstArrayView< Integer > localIds, const IAbstractFamily &family, Integer kind, eKeepAlive alive=DontClone)
std::map< Integer, ConstArrayView< Integer > > m_entry_own_items
Local ids, only for owned, by entry.
std::map< Integer, UniqueArray< Integer > > m_entry_all_indices
Unique ids, sorted by owned then ghosts. By entry.
Integer m_local_owner
current owner.
ScalarIndexSetVector m_entries
Table des Entry connues localement.
std::map< Integer, const IAbstractFamily * > m_entry_families
Family, by entry.
VectorIndexSet buildVectorIndexSet(const String &name, ConstArrayView< Integer > localIds, const IAbstractFamily &family, const UniqueArray< Integer > &kind, eKeepAlive alive=DontClone)
void removeIndex(const ScalarIndexSet &entry, ConstArrayView< Integer > localIds)
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --
Definition BackEnd.h:17