TrioCFD 1.9.8
TrioCFD documentation
Loading...
Searching...
No Matches
Schema_Comm_Vecteurs.h
1/****************************************************************************
2* Copyright (c) 2026, 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#ifndef Schema_Comm_Vecteurs_included
17#define Schema_Comm_Vecteurs_included
18
19#include <TRUSTArray.h>
20
21enum IsExchangeBlocking
22{
23 DefaultBlocking,
24 NonBlockingStart,
25 NonBlockingFinish
26};
27
29
30/*! @brief Classe outil utilisee notamment par les methodes MD_Vector::echange_espace_virtuel()
31 *
32 * Permet d'echanger avec d'autres processeurs des blocs d'ints ou de double
33 * accessibles par des tableaux dans lesquels on lit et on ecrit directement
34 * (contrairement a Schema_Comm qui utilise readOn et printOn, plus lent).
35 * Pour des raisons de performances, la communication est separee en deux parties
36 * - definition des tailles de buffers (permet d'allouer a l'avance les bufffers
37 * begin_init()
38 * add_send/recv_area_int/double(processeur, size)
39 * (declaration des types, tailles et processeurs destinataire des blocs que l'on va envoyer,
40 * on peut envoyer plusieurs blocs de types identiques ou differents a chaque processeur)
41 * end_init()
42 * - echange de donnees (autant de fois qu'on veut):
43 * begin_comm()
44 * for(each bloc to send) {
45 * ArrOfInt/Double & buf = get_next_area_int/double(pe, size);
46 * for (i=0; i<size; i++)
47 * buf[i] = ...
48 * }
49 * exchange();
50 * for (each bloc to recv) {
51 * ... get_next_area_int/double(...)
52 * end_comm();
53 *
54 */
55extern bool check_comm_vector;
57{
58public:
61 void begin_init();
62
63 template <typename _TYPE_>
64 inline void add_send_area_template(int pe, int size);
65
66 template <typename _TYPE_>
67 inline void add_recv_area_template(int pe, int size);
68
69 template <typename _TYPE_>
70 inline TRUSTArray<_TYPE_>& get_next_area_template(int pe, int array_size);
71
72 void end_init();
73 void begin_comm(bool bufferOnDevice=false);
74 void exchange(IsExchangeBlocking exchange_type = IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname");
75 void end_comm();
76
77 static void CleanMyStaticViews();
78
79protected:
80 inline void add(int pe, int size, ArrOfInt& procs, ArrOfInt& buf_sizes, int align_size);
81 int check_buffers_full() const;
82 int check_next_area(int pe, int byte_size) const;
83
84 // Pour chaque processeur de send_proc ou recv_proc_, taille totale des buffers en "bytes"
85 // Pendant la phase begin_init(), ces deux tableaux sont de taille nproc(), valeur nulle
86 // pour les processeurs a qui on ne parle pas.
87 // ensuite, il sont de la meme taille que send_procs_ et recv_procs_
90 // Liste des proceseurs a qui on envoie des donnees
91 ArrOfInt send_procs_;
92 ArrOfInt recv_procs_;
93 // A l'issue de la phase d'initialisation, les processeurs sont-ils dans l'ordre croissant ?
94 int sorted_ = 1;
95 // Taille du buffer requis pour ce schema
96 int min_buf_size_ = -1;
97 // Buffer packing/uncpacking on device:
98 bool bufferOnDevice_ = false;
99 // Support GPU par MPI:
100 bool use_gpu_aware_mpi_ = false;
101
104
105 // Le buffer global est-il en cours d'utilisation ?
106 static bool buffer_locked_;
107 // Zones temporaires de lecture/ecriture, renvoyees par get_next... et qui pointent dans buffer_
108 static ArrOfDouble tmp_area_double_;
109 static ArrOfFloat tmp_area_float_;
110 static ArrOfInt tmp_area_int_;
111#if INT_is_64_ == 2
112 static ArrOfTID tmp_area_tid_;
113#endif
114
115 // Classe contenant des tableaux malloc (pour destruction automatique en fin d'execution)
117};
118
119/*! @brief Donnees statiques communes a toutes les classes Schema_Comm_Vecteur, avec destructeur pour liberer la memoire en fin d'execution
120 *
121 */
123{
124public:
127 void init(int size, bool bufferOnDevice);
128
133 // Pour chaque processeur entre 0 et nproc(), adresse des prochaines donnees a lire/ecrire
134 // de ce proc dans le tableau buffer
136};
137
138// Taille en bytes d'un bloc de sz ints, arrondi aux 8 octets superieurs
139#ifdef INT_is_64_
140#if INT_is_64_ == 1
141#define BLOCSIZE_INT(sz) (sz<<3) // == sz*8
142#else
143#define BLOCSIZE_INT(sz) (sz<<2) // == sz*4
144#define BLOCSIZE_TID(sz) (sz<<3) // == sz*8
145#endif
146#else
147#define BLOCSIZE_INT(sz) (sz<<2) // == sz*4
148#endif
149
150#define BLOCSIZE_DOUBLE(sz) (sz<<3)
151#define BLOCSIZE_FLOAT(sz) (sz<<2)
152#define ALIGN_SIZE(ptr,sz) ptr=sdata_.buffer_base_+((ptr-sdata_.buffer_base_+(sz-1))&(~(sz-1)))
153
154inline void Schema_Comm_Vecteurs::add(int pe, int size, ArrOfInt& procs, ArrOfInt& buf_sizes, int align_size)
155{
156 assert(status_ == BEGIN_INIT);
157 assert(size >= 0);
158 int& x = buf_sizes[pe];
159 if (x == 0 && size > 0)
160 {
161 const int n = procs.size_array();
162 if (n > 0 && procs[n - 1] > pe)
163 sorted_ = 0;
164 procs.append_array(pe);
165 }
166 x = ((x + align_size - 1) & (~(align_size - 1))) + size; // Padding before block
167}
168
170{
171#ifdef KOKKOS //If Kokkos is defined, we can clear the views
172 tmp_area_double_.CleanMyView();
173 tmp_area_float_.CleanMyView();
174 tmp_area_int_.CleanMyView();
175#endif
176 return;
177}
178template<>
180{
181 add(pe, BLOCSIZE_INT(size), send_procs_, send_buf_sizes_, sizeof(int));
182}
183
184template<>
186{
187 add(pe, BLOCSIZE_DOUBLE(size), send_procs_, send_buf_sizes_, sizeof(double));
188}
189
190template<>
192{
193 add(pe, BLOCSIZE_FLOAT(size), send_procs_, send_buf_sizes_, sizeof(float));
194}
195
196template<>
198{
199 add(pe, BLOCSIZE_INT(size), recv_procs_, recv_buf_sizes_, sizeof(int));
200}
201
202template<>
204{
205 add(pe, BLOCSIZE_DOUBLE(size), recv_procs_, recv_buf_sizes_, sizeof(double));
206}
207
208template<>
210{
211 add(pe, BLOCSIZE_FLOAT(size), recv_procs_, recv_buf_sizes_, sizeof(float));
212}
213
214#if INT_is_64_ == 2
215template<>
217{
218 add(pe, BLOCSIZE_TID(size), send_procs_, send_buf_sizes_, sizeof(trustIdType));
219}
220
221template<>
223{
224 add(pe, BLOCSIZE_TID(size), recv_procs_, recv_buf_sizes_, sizeof(trustIdType));
225}
226#endif
227
228/*! @brief renvoie un tableau contenant les "size" valeurs suivantes recues du processeur pe lors de la communication en cours.
229 *
230 * Attention:
231 * Le tableau renvoye est une reference a un tableau interne qui n'est valide que
232 * jusqu'au prochain appel a une methode get_next_xxx.
233 *
234 */
235template<>
237{
238 ALIGN_SIZE(sdata_.buf_pointers_[pe], sizeof(int));
239 assert(check_next_area(pe, BLOCSIZE_INT(size)));
240 int *bufptr = (int *) (sdata_.buf_pointers_[pe]);
241 // attention a l'arithmetique de pointeurs, ajout d'une taille en octets
242 sdata_.buf_pointers_[pe] += BLOCSIZE_INT(size);
243 tmp_area_int_.ref_data(bufptr, size);
244 tmp_area_int_.set_data_location(bufferOnDevice_ ? DataLocation::Device : DataLocation::HostOnly);
245 return tmp_area_int_;
246}
247
248#if INT_is_64_ == 2
249template<>
250inline ArrOfTID& Schema_Comm_Vecteurs::get_next_area_template<trustIdType>(int pe, int size)
251{
252 ALIGN_SIZE(sdata_.buf_pointers_[pe], sizeof(trustIdType));
253 assert(check_next_area(pe, BLOCSIZE_TID(size)));
254 trustIdType *bufptr = (trustIdType *) (sdata_.buf_pointers_[pe]);
255 // attention a l'arithmetique de pointeurs, ajout d'une taille en octets
256 sdata_.buf_pointers_[pe] += BLOCSIZE_TID(size);
257 tmp_area_tid_.ref_data(bufptr, size);
258 return tmp_area_tid_;
259}
260#endif
261
262template<>
263inline ArrOfDouble& Schema_Comm_Vecteurs::get_next_area_template<double>(int pe, int size)
264{
265 ALIGN_SIZE(sdata_.buf_pointers_[pe], sizeof(double));
266 assert(check_next_area(pe, BLOCSIZE_DOUBLE(size)));
267 double *bufptr = (double *) (sdata_.buf_pointers_[pe]);
268 // attention a l'arithmetique de pointeurs, ajout d'une taille en octets
269 sdata_.buf_pointers_[pe] += BLOCSIZE_DOUBLE(size);
270 tmp_area_double_.ref_data(bufptr, size);
271 tmp_area_double_.set_data_location(bufferOnDevice_ ? DataLocation::Device : DataLocation::HostOnly);
272 if (check_comm_vector)
273 {
274#ifndef NDEBUG
275 // en debug, mettre des valeurs bidon dans le tableau
276 if (status_ != EXCHANGED)
277 tmp_area_double_ = DMAXFLOAT * 0.999;
278#endif
279 }
280 return tmp_area_double_;
281}
282
283template<>
284inline ArrOfFloat& Schema_Comm_Vecteurs::get_next_area_template<float>(int pe, int size)
285{
286 ALIGN_SIZE(sdata_.buf_pointers_[pe], sizeof(float));
287 assert(check_next_area(pe, BLOCSIZE_FLOAT(size)));
288 float *bufptr = (float *) (sdata_.buf_pointers_[pe]);
289 // attention a l'arithmetique de pointeurs, ajout d'une taille en octets
290 sdata_.buf_pointers_[pe] += BLOCSIZE_FLOAT(size);
291 tmp_area_float_.ref_data(bufptr, size);
292 tmp_area_float_.set_data_location(bufferOnDevice_ ? DataLocation::Device : DataLocation::HostOnly);
293 return tmp_area_float_;
294}
295
296#undef BLOCSIZE_INT
297#undef BLOCSIZE_DOUBLE
298#undef BLOCSIZE_FLOAT
299
300#endif /* Schema_Comm_Vecteurs_included */
Donnees statiques communes a toutes les classes Schema_Comm_Vecteur, avec destructeur pour liberer la...
void init(int size, bool bufferOnDevice)
void add_send_area_template(int pe, int size)
static Schema_Comm_Vecteurs_Static_Data sdata_
static ArrOfDouble tmp_area_double_
int check_next_area(int pe, int byte_size) const
verifie qu'il reste au moins byte_size octets dans le buffer du processeur pe
TRUSTArray< _TYPE_ > & get_next_area_template(int pe, int array_size)
void add_recv_area_template(int pe, int size)
void end_init()
Une fois les donnees a echanger declarees avec add_send/recv_area_.
void begin_init()
Reinitialise les tailles de buffers.
int check_buffers_full() const
Selon status_, verifie que tous les pointeurs de buffers pointent a la fin du buffer aloue pour chaqu...
static ArrOfFloat tmp_area_float_
void exchange(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
void begin_comm(bool bufferOnDevice=false)
Commence un nouvel echange de donnees (les tailles de buffers doivent avoir ete initialisees avec beg...
void add(int pe, int size, ArrOfInt &procs, ArrOfInt &buf_sizes, int align_size)
Represents a an array of int/int64/double/... values.
Definition TRUSTArray.h:81
void append_array(_TYPE_ valeur)
_SIZE_ size_array() const