TRUST 1.9.8
HPC thermohydraulic platform
Loading...
Searching...
No Matches
MD_Vector_std.cpp
1/****************************************************************************
2* Copyright (c) 2024, CEA
3* All rights reserved.
4*
5* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
7* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
8* 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
9*
10* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
11* IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
12* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13*
14*****************************************************************************/
15
16#include <MD_Vector_std.h>
17#include <Param.h>
18#include <Array_tools.h>
19
20Implemente_instanciable(MD_Vector_std,"MD_Vector_std",MD_Vector_mono);
21
22
23/*! @brief Stupid ctor.
24 *
25 * Everything set to n.
26 */
28{
29 nb_items_tot_ = n;
33 blocs_items_to_sum_.resize_array(2, RESIZE_OPTIONS::NOCOPY_NOINIT);
36 blocs_items_to_compute_.resize_array(2, RESIZE_OPTIONS::NOCOPY_NOINIT);
39}
40
41/*! @brief Constructeur.
42 *
43 * Si nb_items_reels >= 0, items_to_compute contiendra un bloc avec les items reels,
44 * sinon, items_to_compute prendra tous les items (jusqu'a nb_items_tot).
45 *
46 * @param (nb_items_tot) valeur que prendra nb_items_tot_ (doit etre >= 0)
47 * @param (nb_items_reels) valeur que prendra nb_items_reels_ (doit etre >= -1, -1 signifie qu'il n'y a pas d'items "reels" groupes au debut du tableau
48 * @param (pe_voisins) liste des processeurs voisins, classes dans l'ordre croissant (les tableaux ArrsOfInt doivent avoir la meme taille). Cette liste n'est pas reprise integralement: on retire les processeurs pour lesquels toutes les trois listes d'items sont vides.
49 * @param (items_to_send) pour chaque pe_voisin, liste des items a envoyer (communs et virtuels). count_items_to_send_to_items_ est calcule par une communication a partir de items_to_recv.
50 * @param (items_to_recv) liste d'items individuels a recevoir des differents procs (souvent des items communs mais ce n'est pas obligatoire, ex front-tracking)
51 * @param (blocs_to_recv) liste de blocs d'items a recevoir (voir MD_Vector_std::blocs_to_recv_) (souvent les items virtuels...)
52 */
53MD_Vector_std::MD_Vector_std(int nb_items_tot, int nb_items_reels, const ArrOfInt& pe_voisins,
54 const ArrsOfInt& items_to_send, const ArrsOfInt& items_to_recv, const ArrsOfInt& blocs_to_recv)
55{
56 assert(nb_items_tot >= 0);
57 assert(nb_items_reels >= -1 && nb_items_reels <= nb_items_tot);
58 nb_items_tot_ = nb_items_tot;
59 nb_items_reels_ = nb_items_reels;
60 const int nb_voisins = pe_voisins.size_array();
61 assert(items_to_send.size() == nb_voisins);
62 assert(items_to_recv.size() == nb_voisins);
63 assert(blocs_to_recv.size() == nb_voisins);
64
65 // selection: liste des indices des pe a conserver dans pe_voisins
66 // (procs avec qui on echange effectivement des donnees)
67 ArrOfInt tmp, selection;
68
69
70 int i;
71 for (i = 0; i < nb_voisins; i++)
72 if (items_to_send[i].size_array() > 0 || items_to_recv[i].size_array() > 0 || blocs_to_recv[i].size_array() > 0)
73 {
75 selection.append_array(i);
76 }
77 const int nb_voisins2 = tmp.size_array();
78 // ** pe_voisins_ **
79 pe_voisins_ = tmp;
80
81 {
82 ArrsOfInt tmpbis(nb_voisins2);
83
84 for (i = 0; i < nb_voisins2; i++)
85 tmpbis[i] = items_to_send[selection[i]];
86 items_to_send_.set(tmpbis);
87
88 for (i = 0; i < nb_voisins2; i++)
89 tmpbis[i] = items_to_recv[selection[i]];
90 items_to_recv_.set(tmpbis);
91
92 for (i = 0; i < nb_voisins2; i++)
93 tmpbis[i] = blocs_to_recv[selection[i]];
94 blocs_to_recv_.set(tmpbis);
95 }
96
97 // Calcul de nb_items_to_items_
98 {
99 nb_items_to_items_.resize_array(nb_voisins2, RESIZE_OPTIONS::NOCOPY_NOINIT);
100 tmp.resize_array(nproc(), RESIZE_OPTIONS::NOCOPY_NOINIT);
101 tmp = 0;
102 for (i = 0; i < nb_voisins2; i++)
103 tmp[pe_voisins_[i]] = items_to_recv[selection[i]].size_array();
104 ;
105 envoyer_all_to_all(tmp, tmp);
106 for (i = 0; i < nb_voisins2; i++)
107 {
108 int n = tmp[pe_voisins_[i]];
109 assert(n <= items_to_send_.get_list_size(i));
110 nb_items_to_items_[i] = n;
111 }
112 }
113 // Calcul de blocs_items_count_
114 {
115 blocs_items_count_.resize_array(nb_voisins2, RESIZE_OPTIONS::NOCOPY_NOINIT);
116 for (i = 0; i < nb_voisins2; i++)
117 {
118 const int nblocs = blocs_to_recv_.get_list_size(i) / 2;
119 int count = 0;
120 for (int j = 0; j < nblocs; j++)
121 {
122 int deb = blocs_to_recv_(i, j * 2);
123 int fin = blocs_to_recv_(i, j * 2 + 1);
124 assert(deb >= 0 && fin > deb && fin <= nb_items_tot_);
125 count += fin - deb;
126 }
127 blocs_items_count_[i] = count;
128 }
129 }
130 // Calcul des blocs d'items sequentiels (items non recus d'un autre proc)
131 tmp.resize_array(nb_items_tot, RESIZE_OPTIONS::NOCOPY_NOINIT);
132 {
133 // Marquage des items recus a zero
134 tmp = 1;
135 const ArrOfInt& items = items_to_recv_.get_data();
136 int n = items.size_array();
137 for (i = 0; i < n; i++)
138 {
139 assert(tmp[items[i]] == 1); // sinon, c'est qu'on recoit deux fois le meme items
140 tmp[items[i]] = 0;
141 }
142 const ArrOfInt& items2 = blocs_to_recv_.get_data();
143 assert(items2.size_array() % 2 == 0);
144 n = items2.size_array() / 2;
145 for (i = 0; i < n; i++)
146 {
147 const int start = items2[i * 2];
148 const int end = items2[i * 2 + 1];
149 for (int j = start; j < end; j++)
150 {
151 assert(tmp[j] == 1); // sinon, c'est qu'on recoit deux fois le meme items
152 tmp[j] = 0;
153 }
154 }
155
156 // Construction d'une liste de blocs d'items sequentiels (ceux qui sont restes a 1)
157 ArrOfInt blocs;
158
159 int nb_seq = 0;
160 for (i = 0; i < nb_items_tot; i++)
161 {
162 if (tmp[i])
163 {
164 if (nb_items_reels >= 0 && i >= nb_items_reels)
165 {
166 // On a un item non recu parmi les items virtuels !
167 Cerr << "Error in MD_Vector_std::MD_Vector_std(...) [pe " << me() << "]\n "
168 "an item i(" << i << ") > nb_items_reels(" << nb_items_reels << ") is not received from any other processor" << finl;
170 }
171 append_item_to_blocs(blocs, i);
172 nb_seq++;
173 }
174 }
175 blocs_items_to_sum_ = blocs;
176 nb_items_seq_local_ = nb_seq;
177 nb_items_seq_tot_ = mp_sum(nb_seq);
178 }
179
180 // Bloc items to compute:
181 // Par defaut: un seul bloc
182 if (nb_items_reels_ >= 0)
183 {
184 // Les operateurs sur les tableaux calculent tous les items reels
185 blocs_items_to_compute_.resize(2, RESIZE_OPTIONS::NOCOPY_NOINIT);
188 }
189 else
190 {
191 // Les operateurs sur les tableaux calculent tout
192 blocs_items_to_compute_.resize(2, RESIZE_OPTIONS::NOCOPY_NOINIT);
195 }
196}
197
198/*! @brief method used to dump/restore a descriptor in a file Each process writes a different descriptor.
199 *
200 * See MD_Vector_tools::restore_vector_with_md()
201 *
202 */
204{
206 Param p(que_suis_je());
207 ArrOfInt items_send_index, items_send_data, items_index, items_data, blocs_index, blocs_data;
208 p.ajouter("pe_voisins", &pe_voisins_);
209 p.ajouter("items_to_send_index", &items_send_index);
210 p.ajouter("items_to_send_data", &items_send_data);
211 p.ajouter("nb_items_to_items", &nb_items_to_items_);
212 p.ajouter("items_to_recv_index", &items_index);
213 p.ajouter("items_to_recv_data", &items_data);
214 p.ajouter("blocs_to_recv_index", &blocs_index);
215 p.ajouter("blocs_to_recv_data", &blocs_data);
216 p.ajouter("blocs_items_count", &blocs_items_count_);
217 p.lire_avec_accolades(is);
218 if (items_send_data.size_array())
219 items_to_send_.set_index_data(items_send_index, items_send_data);
220 if (items_data.size_array())
221 items_to_recv_.set_index_data(items_index, items_data);
222 if (blocs_data.size_array())
223 blocs_to_recv_.set_index_data(blocs_index, blocs_data);
224 return is;
225}
226
227/*! @brief method used to dump/restore a descriptor in a file Each process writes a different descriptor.
228 *
229 * See MD_Vector_tools::dump_vector_with_md()
230 *
231 */
233{
235 os << "{" << finl;
236 os << "pe_voisins" << tspace << pe_voisins_ << finl;
237 os << "items_to_send_index" << tspace << items_to_send_.get_index() << finl;
238 os << "items_to_send_data" << tspace << items_to_send_.get_data() << finl;
239 os << "nb_items_to_items" << tspace << nb_items_to_items_ << finl;
240 os << "items_to_recv_index" << tspace << items_to_recv_.get_index();
241 os << "items_to_recv_data" << tspace << items_to_recv_.get_data();
242 os << "blocs_to_recv_index" << tspace << blocs_to_recv_.get_index() << finl;
243 os << "blocs_to_recv_data" << tspace << blocs_to_recv_.get_data();
244 os << "blocs_items_count" << tspace << blocs_items_count_ << finl;
245 os << "}" << finl;
246 return os;
247}
248
249namespace // Anonymous namespace
250{
251
252/*! @brief returns i such that a[i]==x, or -1 if x is not found
253 */
254int find_in_array(const ArrOfInt& a, int x)
255{
256 int n;
257 for (n = a.size_array() - 1; n >= 0; n--)
258 if (a[n] == x)
259 break;
260 return n;
261}
262
263/*! @brief Renvoie le nombre d'items extraits (pas le nombre de blocs)
264 */
265int extract_blocs(const ArrOfInt src, const ArrOfInt& renum, ArrOfInt& dest)
266{
267 const int nblocs_src = src.size_array() / 2;
268
269 dest.resize_array(0);
270 int end_last_bloc = -1;
271 int count = 0;
272 for (int i = 0; i < nblocs_src; i++)
273 {
274 const int deb = src[i*2];
275 const int fin = src[i*2+1];
276 for (int j = deb; j < fin; j++)
277 {
278 const int rj = renum[j];
279 if (rj >= 0)
280 {
281 count++;
282 // Blocs construction assumes that renum is ordered
283 assert(rj >= end_last_bloc);
284 if (rj == end_last_bloc)
285 {
286 // item is contiguous to last bloc in destination array, increase bloc size:
287 end_last_bloc++;
288 dest[dest.size_array()-1] = end_last_bloc;
289 }
290 else
291 {
292 // non contiguous item, create new bloc
293 end_last_bloc = rj;
294 dest.append_array(end_last_bloc);
295 end_last_bloc++;
296 dest.append_array(end_last_bloc);
297 }
298 }
299 }
300 }
301 return count;
302}
303
304} // end anonymous NS
305
306
307/*! Append all items in "src" to "this", duplicating src items "multiplier" times
308 * and adding the "offset" to item indexes. Also merge pe_voisins_ lists.
309 */
310void MD_Vector_std::append_from_other_std(const MD_Vector_std& src, int offset, int multiplier)
311{
312 // List sizes for items_to_send_, items_to_recv_ and blocs_to_recv_ of new descriptor
313 ArrOfInt x_sz, y_sz, z_sz;
314 // Data of these lists:
315 ArrOfInt x_data, y_data, z_data;
316 ArrOfInt new_blocs_items_count, new_nb_items_to_items;
317 ArrOfInt tmp;
318 ArrOfInt pe_list(pe_voisins_);
319
320 append_blocs(pe_list, src.pe_voisins_);
321 array_trier_retirer_doublons(pe_list);
322 const int np = pe_list.size_array();
323
324 new_blocs_items_count.resize_array(np);
325 new_nb_items_to_items.resize_array(np);
326
327 for (int i = 0; i < np; i++)
328 {
329 // Number of items to recv, send and blocs to recv for this processor:
330 int nx = 0, ny = 0, nz = 0;
331 int blocs_count = 0;
332 // Is processor pe_list[i] in initial "dest" descriptor ?
333 int j;
334
335 for (j = pe_voisins_.size_array()-1; j >= 0; j--)
336 if (pe_voisins_[j] == pe_list[i])
337 break;
338 const int pe = pe_list[i];
339
340 // Insert items to send and items to recv from dest
341 j = ::find_in_array(pe_voisins_, pe);
342 if (j >= 0)
343 {
344 const int count_items_single = nb_items_to_items_[j];
345 nx += count_items_single;
346 // take only single items to send
347 tmp.resize_array(0);
348 tmp.resize_array(count_items_single);
349 for (int k = 0; k < count_items_single; k++)
350 tmp[k] = items_to_send_(j, k);
351 append_blocs(x_data, tmp);
352
353 ny += items_to_recv_.get_list_size(j);
354 items_to_recv_.copy_list_to_array(j, tmp);
355 append_blocs(y_data, tmp);
356 }
357
358 // Insert items to send and items to recv from src, with multiplier
359 j = find_in_array(src.pe_voisins_, pe);
360 if (j >= 0)
361 {
362 const int count_items_single = src.nb_items_to_items_[j];
363 nx += count_items_single * multiplier;
364 // take only single items to send
365 tmp.resize_array(0);
366 tmp.resize_array(count_items_single);
367 for (int k = 0; k < count_items_single; k++)
368 tmp[k] = src.items_to_send_(j, k);
369 append_items(x_data, tmp, offset, multiplier);
370
371 ny += src.items_to_recv_.get_list_size(j) * multiplier;
373 append_items(y_data, tmp, offset, multiplier);
374 }
375 const int single_items_count = nx;
376 // Insert blocs to send and blocs to recv from dest
377 j = ::find_in_array(pe_voisins_, pe);
378 if (j >= 0)
379 {
380 const int count_items_tot = items_to_send_.get_list_size(j);
381 const int count_items_single = nb_items_to_items_[j];
382 nx += count_items_tot - count_items_single;
383 tmp.resize_array(0);
384 tmp.resize_array(count_items_tot - count_items_single);
385 for (int k = count_items_single; k < count_items_tot; k++)
386 tmp[k - count_items_single] = items_to_send_(j, k);
387 append_blocs(x_data, tmp);
388
389 nz += blocs_to_recv_.get_list_size(j);
390 blocs_to_recv_.copy_list_to_array(j, tmp);
391 append_blocs(z_data, tmp);
392
393 blocs_count += blocs_items_count_[j];
394 }
395 // Insert blocs to send and blocs to recv from src, with multiplier
396 j = find_in_array(src.pe_voisins_, pe);
397 if (j >= 0)
398 {
399 const int count_items_tot = src.items_to_send_.get_list_size(j);
400 const int count_items_single = src.nb_items_to_items_[j];
401 nx += (count_items_tot - count_items_single) * multiplier;
402 tmp.resize_array(0);
403 tmp.resize_array(count_items_tot - count_items_single);
404 for (int k = count_items_single; k < count_items_tot; k++)
405 tmp[k - count_items_single] = src.items_to_send_(j, k);
406 append_items(x_data, tmp, offset, multiplier);
407
408 nz += src.blocs_to_recv_.get_list_size(j);
410 append_blocs(z_data, tmp, offset, multiplier);
411
412 blocs_count += src.blocs_items_count_[j] * multiplier;
413 }
414
415 x_sz.append_array(nx);
416 y_sz.append_array(ny);
417 z_sz.append_array(nz);
418 new_blocs_items_count[i] = blocs_count;
419 new_nb_items_to_items[i] = single_items_count;
420 }
421
422 items_to_send_.set_list_sizes(x_sz);
423 items_to_send_.set_data(x_data);
424 items_to_recv_.set_list_sizes(y_sz);
425 items_to_recv_.set_data(y_data);
426 blocs_to_recv_.set_list_sizes(z_sz);
427 blocs_to_recv_.set_data(z_data);
428 pe_voisins_ = pe_list;
429 blocs_items_count_ = new_blocs_items_count;
430 nb_items_to_items_ = new_nb_items_to_items;
431}
432
433void MD_Vector_std::fill_md_vect_renum(const IntVect& renum, MD_Vector& md_vect) const
434{
435 MD_Vector_std dest;
436
437 // Calcul de nb_items_tot_ et nb_items_reels_
438 // nb_items_tot_ est le nombre d'items pour lesquels renum[i] >= 0
439 // Les items reels sont ceux qui etaient reels dans le tableau d'origine et qui sont a conserver
440 {
441 const int src_size = get_nb_items_tot();
442 const int src_size_r = get_nb_items_reels();
443 dest.nb_items_tot_ = 0;
444 dest.nb_items_reels_ = 0;
445 for (int i = 0; i < src_size; i++)
446 {
447 if (renum[i] >= 0)
448 {
449 dest.nb_items_tot_++;
450 if (i < src_size_r)
451 dest.nb_items_reels_++;
452 }
453 }
454 // Si l'attribut nb_items_reels_ est invalide dans le vecteur source, il est invalide dans le
455 // vecteur resultat:
456 if (src_size_r < 0)
457 dest.nb_items_reels_ = -1;
458 }
459 // Remplissage de blocs_items_to_sum_ et blocs_items_to_compute_
460 // Ce sont les items pour lesquels renum[i] >= 0 et qui sont dans les blocs_items_to_sum_
461 // et blocs_items_to_compute_ du descripteur source.
462 ::extract_blocs(blocs_items_to_sum_, renum, dest.blocs_items_to_sum_);
463 dest.nb_items_seq_local_ = ::extract_blocs(blocs_items_to_compute_, renum, dest.blocs_items_to_compute_);
465
466 // ********************************************************
467 // Calcul des items a recevoir: ce sont les items pour lesquels renum[i] >= 0 et qui etaient a
468 // recevoir dans le descripteur source.
469 // Chaque fois qu'on trouve un item a recevoir, il faut informer le processeur voisin qui possede l'item
470 // que c'est item doit etre envoye (utilisation du schema_comm). Pour identifier ces items, on utilise
471 // sont rang dans le tableau des items a envoyer dans le descripteur source (variable item_rank)
472 //
473 const int nb_pe_voisins = pe_voisins_.size_array();
474 Schema_Comm schema_comm;
476 schema_comm.begin_comm();
477 // Calcul des listes items_to_recv
478 // index+data forment les deux tableau d'un StaticIntLists.
479 // On construit pour commencer autant de listes que de processeurs voisins dans le descripteur source.
480 // On retirera a la fin les processeurs qui n'echangent pas de donnees
481 ArrOfInt dest_items_recv_index;
482 ArrOfInt dest_items_recv_data;
483 ArrOfInt dest_blocs_recv_index;
484 ArrOfInt dest_blocs_recv_data;
485
486 ArrOfInt tmp;
487
488 {
489 dest_items_recv_index.resize_array(nb_pe_voisins + 1, RESIZE_OPTIONS::NOCOPY_NOINIT);
490 dest_items_recv_index[0] = 0;
491 dest_blocs_recv_index.resize_array(nb_pe_voisins + 1, RESIZE_OPTIONS::NOCOPY_NOINIT);
492 dest_blocs_recv_index[0] = 0;
493 dest.blocs_items_count_.resize_array(nb_pe_voisins, RESIZE_OPTIONS::NOCOPY_NOINIT);
494 dest.nb_items_to_items_.resize_array(nb_pe_voisins, RESIZE_OPTIONS::NOCOPY_NOINIT);
495 // Preallocation de la taille maxi
496 dest_items_recv_data.resize_array(items_to_recv_.get_data().size_array(), RESIZE_OPTIONS::NOCOPY_NOINIT);
497
498 dest_items_recv_data.resize_array(0);
499 // On ne peut pas prevoir le nombre de blocs, il peut y en avoir plus que dans la source
500
501 for (int i_pe = 0; i_pe < nb_pe_voisins; i_pe++)
502 {
503 tmp.resize_array(0);
504 int item_rank = 0; // Compteur d'items recus dans le descripteur source
505 // 1) Extraction des items individuels
506 // (remplissage de dest_items_recv_index, dest_items_recv_data et tmp)
507 const int n = items_to_recv_.get_list_size(i_pe);
508 for (int i = 0; i < n; i++)
509 {
510 const int j = items_to_recv_(i_pe, i);
511 const int rj = renum[j];
512 if (rj >= 0)
513 {
514 // Ajout de cet item
515 dest_items_recv_data.append_array(rj);
516 // Demander au processeur voisin d'envoyer cet item
517 tmp.append_array(item_rank);
518 }
519 item_rank++;
520 }
521 // Initialisation de la taille de la liste d'items pour ce processeur:
522 dest_items_recv_index[i_pe+1] = dest_items_recv_data.size_array();
523
524 // 2) Extraction des blocs d'items recus de ce processeur
525 // (remplissage de dest_blocs_recv_index dest_blocs_recv_data dest.blocs_items_count_ et tmp)
526 const int nblocs = blocs_to_recv_.get_list_size(i_pe) / 2;
527 int received_count = 0; // nombre d'items recus de ce processeur
528 for (int ibloc = 0; ibloc < nblocs; ibloc++)
529 {
530 const int jdeb = blocs_to_recv_(i_pe, ibloc * 2);
531 const int jfin = blocs_to_recv_(i_pe, ibloc * 2 + 1);
532 int last_added = -2; // ne peut jamais etre egal a rj-1
533 // Pour chaque item du bloc, s'il doit etre conserve, le reporter dans les blocs a recevoir:
534 for (int j = jdeb; j < jfin; j++)
535 {
536 const int rj = renum[j];
537 if (rj >= 0)
538 {
539 if (rj <= last_added)
540 {
541 // Les items dans les blocs a recevoir doivent etre tries dans l'ordre croissant
542 // (sinon cet algorithme ne marche pas, il faut en utiliser un autre pour
543 // construire les blocs, et en plus le comptage des items reels ne veut peut-etre plus rien dire)
544 Cerr << "Error in creer_md_vect_renum: renum array is not sorted: cannot extract blocs to recv" << finl;
546 }
547 // Cet item est-il contigu avec le precedent ?
548 if (last_added == rj-1)
549 {
550 // Oui, augmenter la taille du dernier bloc
551 const int k = dest_blocs_recv_data.size_array();
552 // fin de bloc = indice du dernier plus 1
553 dest_blocs_recv_data[k-1] = rj+1;
554 }
555 else
556 {
557 // Non, creer un nouveau bloc
558 dest_blocs_recv_data.append_array(rj);
559 dest_blocs_recv_data.append_array(rj+1);
560 }
561 last_added = rj;
562 // Demander au processeur voisin d'envoyer cet item
563 tmp.append_array(item_rank);
564 received_count++;
565 }
566 item_rank++;
567 }
568 }
569 // Initialisation de la taille de la liste de blocs pour ce processeur:
570 dest_blocs_recv_index[i_pe+1] = dest_blocs_recv_data.size_array();
571 // Nombre d'items recus de ce processeur
572 dest.blocs_items_count_[i_pe] = received_count;
573 // Envoi du tableau tmp au processeur voisin:
574 schema_comm.send_buffer(pe_voisins_[i_pe]) << tmp;
575 }
576 }
577
578 schema_comm.echange_taille_et_messages();
579
580 // ********************************************************
581 // Construction de dest.items_to_send avec les infos recues
582 //
583 ArrOfInt dest_items_send_index;
584 dest_items_send_index.resize_array(nb_pe_voisins + 1, RESIZE_OPTIONS::NOCOPY_NOINIT);
585 ArrOfInt dest_items_send_data;
586 ArrOfInt nb_items_to_items(nb_pe_voisins); // Initialise a zero
587
588 // Allocation d'une taille par borne superieure:
589 dest_items_send_data.resize_array(items_to_send_.get_data().size_array(), RESIZE_OPTIONS::NOCOPY_NOINIT);
590 dest_items_send_index[0] = 0;
591 {
592 int count = 0;
593 int error = 0;
594 for (int i_pe = 0; i_pe < nb_pe_voisins; i_pe++)
595 {
596 // nb_item_received_single est le nombre d'items dans items_to_send_ qui seront receptionnes
597 // par items_to_recv_. Les suivants sont recus dans blocs_to_recv_.
598 schema_comm.recv_buffer(pe_voisins_[i_pe]) >> tmp;
599 const int n = tmp.size_array();
600 for (int i = 0; i < n; i++)
601 {
602 // tmp contient des indices qui pointent dans items_to_send_
603 int j = tmp[i];
604 // k est l'indice dans l'ancien tableau de l'item a envoyer
605 int k = items_to_send_(i_pe, j);
606 int renum_k = renum[k];
607 // Une erreur possible ici: un processeur a besoin d'un item virtuel et l'item
608 // reel a ete supprime sur le processeur source. Il faut alors utiliser un
609 // autre algo pour changer le proprietaire de l'item...
610 if (renum_k < 0)
611 error = 1;
612 dest_items_send_data[count++] = renum_k;
613 }
614 dest_items_send_index[i_pe+1] = count;
615 }
616 if (error)
617 {
618 Cerr << "Internal error in MD_Vector_tools::creer_md_vect_renum:\n"
619 << " processor " << Process::me()
620 << " received a request for distant items that are not in the new vector" << finl;
622 }
623 // On ajuste a la taille definitive
624
625 dest_items_send_data.resize_array(count);
626 }
627 schema_comm.end_comm();
628
629 /* nouveau nb_items_to_items */
630 schema_comm.begin_comm();
631 for (int i_pe = 0; i_pe < nb_pe_voisins; i_pe++)
632 schema_comm.send_buffer(pe_voisins_[i_pe]) << dest_items_recv_index(i_pe + 1) - dest_items_recv_index(i_pe);
633 schema_comm.echange_taille_et_messages();
634 for (int i_pe = 0; i_pe < nb_pe_voisins; i_pe++)
635 schema_comm.recv_buffer(pe_voisins_[i_pe]) >> nb_items_to_items[i_pe];
636 schema_comm.end_comm();
637
638 // Construction de la liste de processeurs voisins de dest
639 // (processeurs avec qui on echange des donnees)
640 // Et compression des indexes des StaticIntLists pour retirer les
641 // processeurs supprimes.
642 {
643 int pe_count = 0;
644 dest.pe_voisins_.resize_array(nb_pe_voisins, RESIZE_OPTIONS::NOCOPY_NOINIT);
645 for (int i_pe = 0; i_pe < nb_pe_voisins; i_pe++)
646 {
647 int flag = 0;
648 if (dest_items_recv_index[i_pe+1] - dest_items_recv_index[i_pe] > 0)
649 flag = 1;
650 if (dest_blocs_recv_index[i_pe+1] - dest_blocs_recv_index[i_pe] > 0)
651 flag = 1;
652 if (dest_items_send_index[i_pe+1] - dest_items_send_index[i_pe] > 0)
653 flag = 1;
654
655 if (flag)
656 {
657 dest_items_recv_index[pe_count+1] = dest_items_recv_index[i_pe+1];
658 dest_blocs_recv_index[pe_count+1] = dest_blocs_recv_index[i_pe+1];
659 dest_items_send_index[pe_count+1] = dest_items_send_index[i_pe+1];
660 dest.blocs_items_count_[pe_count] = dest.blocs_items_count_[i_pe];
661 dest.pe_voisins_[pe_count] = pe_voisins_[i_pe];
662 dest.nb_items_to_items_[pe_count] = nb_items_to_items[i_pe];
663 pe_count++;
664 }
665 }
666
667 dest_items_recv_index.resize_array(pe_count+1);
668
669 dest_blocs_recv_index.resize_array(pe_count+1);
670
671 dest_items_send_index.resize_array(pe_count+1);
672
673 dest.pe_voisins_.resize_array(pe_count);
674
675 dest.blocs_items_count_.resize_array(pe_count);
676
677 dest.nb_items_to_items_.resize_array(pe_count);
678 }
679 dest.items_to_send_.set_index_data(dest_items_send_index, dest_items_send_data);
680 dest.items_to_recv_.set_index_data(dest_items_recv_index, dest_items_recv_data);
681 dest.blocs_to_recv_.set_index_data(dest_blocs_recv_index, dest_blocs_recv_data);
682
683 md_vect.copy(dest);
684}
685
Class defining operators and methods for all reading operation in an input flow (file,...
Definition Entree.h:42
friend class MD_Vector
static void append_blocs(ArrOfInt &dest, const ArrOfInt &src, int offset=0, int multiplier=1)
trustIdType nb_items_seq_tot_
static void append_items(ArrOfInt &dest, const ArrOfInt &src, int offset=0, int multiplier=1)
virtual int get_nb_items_tot() const
virtual int get_nb_items_reels() const
static void append_item_to_blocs(ArrOfInt &blocs, int item)
methode outil pour ajouter un item a un tableau du genre "blocs" contenant des series de blocs.
Generic class for all mono-block MD_Vectors (i.e. non compoosite).
ArrOfInt blocs_items_to_sum_
ArrOfInt blocs_items_to_compute_
C'est le plus simple des descripteurs, utilise pour les tableaux de valeurs aux sommets,...
Static_Int_Lists items_to_send_
ArrOfInt blocs_items_count_
const Static_Int_Lists & items_to_recv() const
ArrOfInt pe_voisins_
void fill_md_vect_renum(const IntVect &renum, MD_Vector &md_vect) const override
const ArrOfInt & pe_voisins() const
Static_Int_Lists items_to_recv_
MD_Vector_std(int n)
Stupid ctor.
const Static_Int_Lists & items_to_send() const
const Static_Int_Lists & blocs_to_recv() const
void append_from_other_std(const MD_Vector_std &src, int offset, int multiplier) override
Static_Int_Lists blocs_to_recv_
ArrOfInt nb_items_to_items_
void copy(const MD_Vector_base &)
construction d'un objet MD_Vector par copie d'un objet existant.
Definition MD_Vector.cpp:26
const Nom & que_suis_je() const
renvoie la chaine identifiant la classe.
Definition Objet_U.cpp:104
virtual Entree & readOn(Entree &)
Lecture d'un Objet_U sur un flot d'entree Methode a surcharger.
Definition Objet_U.cpp:293
virtual Sortie & printOn(Sortie &) const
Ecriture de l'objet sur un flot de sortie Methode a surcharger.
Definition Objet_U.cpp:282
Helper class to factorize the readOn method of Objet_U classes.
Definition Param.h:112
static int nproc()
renvoie le nombre de processeurs dans le groupe courant Voir Comm_Group::nproc() et PE_Groups::curren...
Definition Process.cpp:104
static double mp_sum(double)
Calcule la somme de x sur tous les processeurs du groupe courant.
Definition Process.cpp:146
static int me()
renvoie mon rang dans le groupe de communication courant.
Definition Process.cpp:125
static void exit(int exit_code=-1)
Routine de sortie de TRUST dans une region Kokkos.
Definition Process.cpp:455
void echange_taille_et_messages() const
Cette methode lance l'echange de donnees entre tous les processeurs.
Sortie & send_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y entasser des donnees a envoyer.
void end_comm() const
Vide les buffers et libere les ressources: on a fini de lire les donnees recues dans les buffers.
Entree & recv_buffer(int num_PE) const
renvoie le buffer correspondant au processeur num_PE pour y lire les donnees recues.
void begin_comm() const
Reserve les buffers de comm pour une nouvelle communication.
void set_send_recv_pe_list(const ArrOfInt &send_pe_list, const ArrOfInt &recv_pe_list, const int me_to_me=0)
Definit la liste des processeurs a qui on va envoyer et de qui on va recevoir des donnees.
Classe de base des flux de sortie.
Definition Sortie.h:52
void copy_list_to_array(int_t i_liste, ArrOfInt_t &array) const
copie la i-ieme liste dans le tableau fourni Le tableau array doit etre resizable.
void set_index_data(const ArrOfInt_t &index, const ArrOfInt_t &data)
remplace index et data.
int_t get_list_size(int_t i_liste) const
renvoie le nombre d'elements de la liste i
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const
void resize_array(_SIZE_ new_size, RESIZE_OPTIONS opt=RESIZE_OPTIONS::COPY_INIT)