TrioCFD 1.9.9_beta
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 Utility class used notably by MD_Vector::echange_espace_virtuel() methods.
31 *
32 * Allows exchanging blocks of ints or doubles with other processors,
33 * accessible via arrays that are read and written directly
34 * (unlike Schema_Comm which uses readOn and printOn, which is slower).
35 * For performance reasons, communication is split into two phases:
36 * - buffer size definition (allows pre-allocating buffers):
37 * begin_init()
38 * add_send/recv_area_int/double(processor, size)
39 * (declaration of types, sizes and destination processors for blocks to be sent;
40 * multiple blocks of identical or different types can be sent to each processor)
41 * end_init()
42 * - data exchange (as many times as desired):
43 * begin_comm()
44 * for(each block 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 block 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 // For each processor in send_proc or recv_proc_, total buffer size in bytes.
85 // During the begin_init() phase, these two arrays are of size nproc(), with zero value
86 // for processors we don't communicate with.
87 // Afterwards, they are the same size as send_procs_ and recv_procs_.
90 // List of processors to which we send data
91 ArrOfInt send_procs_;
92 ArrOfInt recv_procs_;
93 // After the initialization phase, are the processors in ascending order?
94 int sorted_ = 1;
95 // Buffer size required for this 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 // Is the global buffer currently in use?
106 static bool buffer_locked_;
107 // Temporary read/write areas, returned by get_next... and pointing into 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 // Class containing malloc arrays (for automatic destruction at end of execution)
117};
118
119/*! @brief Static data shared by all Schema_Comm_Vecteur classes, with destructor to free memory at end of execution.
120 *
121 */
123{
124public:
127 void init(int size, bool bufferOnDevice);
128
133 // For each processor between 0 and nproc(), address of the next data to read/write
134 // from this proc in the buffer array
136};
137
138// Size in bytes of a block of sz ints, rounded up to the next 8 bytes
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 Returns an array containing the next "size" values received from processor pe during the current communication.
229 *
230 * Warning:
231 * The returned array is a reference to an internal array that is only valid
232 * until the next call to a get_next_xxx method.
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 // caution with pointer arithmetic, adding a size in bytes
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 // caution with pointer arithmetic, adding a size in bytes
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 // caution with pointer arithmetic, adding a size in bytes
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 // in debug, put dummy values in the array
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 // caution with pointer arithmetic, adding a size in bytes
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 */
Static data shared by all Schema_Comm_Vecteur classes, with destructor to free memory at end of execu...
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
Verifies that there are at least byte_size bytes remaining in the buffer of processor pe.
TRUSTArray< _TYPE_ > & get_next_area_template(int pe, int array_size)
void add_recv_area_template(int pe, int size)
void end_init()
Once the data to exchange has been declared with add_send/recv_area_..(),.
void begin_init()
Resets buffer sizes.
int check_buffers_full() const
Depending on status_, verifies that all buffer pointers point to the end of the buffer allocated for ...
static ArrOfFloat tmp_area_float_
void exchange(IsExchangeBlocking exchange_type=IsExchangeBlocking::DefaultBlocking, const std::string kernel_name="noname")
void begin_comm(bool bufferOnDevice=false)
Starts a new data exchange (buffer sizes must have been initialized with begin_init()....
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