deal.II version GIT relicensing-6809-ge913b9bb34 2026-09-25 17:20:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
mpi_large_count.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2022 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13//
14// The content of this file is a slightly modified version of the
15// header-only library BigMPICompat - a tiny MPI 4.x compatibility
16// library released under MIT license at
17// https://github.com/tjhei/BigMPICompat and relicensed and included
18// here with permission.
19//
20
21#ifndef dealii_base_mpi_large_count_h
22#define dealii_base_mpi_large_count_h
23
24#include <deal.II/base/config.h>
25
26#ifdef DEAL_II_WITH_MPI
27
29# include <mpi.h>
31
32// required for std::numeric_limits used below.
33# include <limits>
34
35#endif
36
38
39#ifdef DEAL_II_WITH_MPI
40namespace Utilities
41{
42 namespace MPI
43 {
49 namespace LargeCount
50 {
55 inline constexpr MPI_Count mpi_max_int_count =
56 std::numeric_limits<int>::max();
57
63 inline int
64 Type_contiguous_c(MPI_Count count,
65 MPI_Datatype oldtype,
66 MPI_Datatype *newtype)
67 {
68# if MPI_VERSION >= 4
69 return MPI_Type_contiguous_c(count, oldtype, newtype);
70# else
72 return MPI_Type_contiguous(count, oldtype, newtype);
73 else
74 {
75 int ierr;
76 const MPI_Count max_signed_int = LargeCount::mpi_max_int_count;
77
78 MPI_Count size_old;
79 ierr = MPI_Type_size_x(oldtype, &size_old);
80
81 MPI_Count n_chunks = count / max_signed_int;
82 MPI_Count n_remaining_elements = count % max_signed_int;
83
84 MPI_Datatype chunks;
85 ierr = MPI_Type_vector(
86 n_chunks, max_signed_int, max_signed_int, oldtype, &chunks);
87 if (ierr != MPI_SUCCESS)
88 return ierr;
89
90 MPI_Datatype remainder;
91 ierr =
92 MPI_Type_contiguous(n_remaining_elements, oldtype, &remainder);
93 if (ierr != MPI_SUCCESS)
94 return ierr;
95
96 int blocklengths[2] = {1, 1};
97 MPI_Aint displacements[2] = {0,
98 static_cast<MPI_Aint>(n_chunks) *
99 size_old * max_signed_int};
100 MPI_Datatype types[2] = {chunks, remainder};
101 ierr = MPI_Type_create_struct(
102 2, blocklengths, displacements, types, newtype);
103 if (ierr != MPI_SUCCESS)
104 return ierr;
105
106 ierr = MPI_Type_commit(newtype);
107 if (ierr != MPI_SUCCESS)
108 return ierr;
109
110 ierr = MPI_Type_free(&chunks);
111 if (ierr != MPI_SUCCESS)
112 return ierr;
113
114 ierr = MPI_Type_free(&remainder);
115 if (ierr != MPI_SUCCESS)
116 return ierr;
117
118# ifndef MPI_COMPAT_SKIP_SIZE_CHECK
119 MPI_Count size_new;
120 ierr = MPI_Type_size_x(*newtype, &size_new);
121 if (ierr != MPI_SUCCESS)
122 return ierr;
123
124 if (size_old * count != size_new)
125 {
126 // This error can happen when you are using a very old and
127 // buggy MPI implementation. There is nothing we can do
128 // here, unfortunately. Please update your installation.
129 // std::cerr
130 //<< "MPI_Type_contiguous_c() produced an invalid result.
131 // Expected =
132 //"
133 //<< size_old << " * " << count << " = " << size_old * count
134 //<< " but received " << size_new << std::endl;
135 return MPI_ERR_INTERN;
136 }
137# endif
138
139 return MPI_SUCCESS;
140 }
141# endif
142 }
143
144
150 inline int
151 Send_c(const void *buf,
152 MPI_Count count,
153 MPI_Datatype datatype,
154 int dest,
155 int tag,
157 {
158# if MPI_VERSION >= 4
159 return MPI_Send_c(buf, count, datatype, dest, tag, comm);
160# else
162 return MPI_Send(buf, count, datatype, dest, tag, comm);
163
164 MPI_Datatype bigtype;
165 int ierr;
166 ierr = Type_contiguous_c(count, datatype, &bigtype);
167 if (ierr != MPI_SUCCESS)
168 return ierr;
169 ierr = MPI_Type_commit(&bigtype);
170 if (ierr != MPI_SUCCESS)
171 return ierr;
172
173 ierr = MPI_Send(buf, 1, bigtype, dest, tag, comm);
174 if (ierr != MPI_SUCCESS)
175 return ierr;
176
177 ierr = MPI_Type_free(&bigtype);
178 if (ierr != MPI_SUCCESS)
179 return ierr;
180 return MPI_SUCCESS;
181# endif
182 }
183
189 inline int
190 Recv_c(void *buf,
191 MPI_Count count,
192 MPI_Datatype datatype,
193 int source,
194 int tag,
196 MPI_Status *status)
197 {
198# if MPI_VERSION >= 4
199 return MPI_Recv_c(buf, count, datatype, source, tag, comm, status);
200# else
202 return MPI_Recv(buf, count, datatype, source, tag, comm, status);
203
204 MPI_Datatype bigtype;
205 int ierr;
206 ierr = Type_contiguous_c(count, datatype, &bigtype);
207 if (ierr != MPI_SUCCESS)
208 return ierr;
209
210 ierr = MPI_Type_commit(&bigtype);
211 if (ierr != MPI_SUCCESS)
212 return ierr;
213
214 ierr = MPI_Recv(buf, 1, bigtype, source, tag, comm, status);
215 if (ierr != MPI_SUCCESS)
216 return ierr;
217
218 ierr = MPI_Type_free(&bigtype);
219 if (ierr != MPI_SUCCESS)
220 return ierr;
221 return MPI_SUCCESS;
222# endif
223 }
224
231 inline int
232 Bcast_c(void *buf,
233 MPI_Count count,
234 MPI_Datatype datatype,
235 unsigned int root_mpi_rank,
237 {
238# if MPI_VERSION >= 4
239 return MPI_Bcast_c(buf, count, datatype, root_mpi_rank, comm);
240# else
242 return MPI_Bcast(buf, count, datatype, root_mpi_rank, comm);
243
244 MPI_Datatype bigtype;
245 int ierr;
246 ierr = Type_contiguous_c(count, datatype, &bigtype);
247 if (ierr != MPI_SUCCESS)
248 return ierr;
249 ierr = MPI_Type_commit(&bigtype);
250 if (ierr != MPI_SUCCESS)
251 return ierr;
252
253 ierr = MPI_Bcast(buf, 1, bigtype, root_mpi_rank, comm);
254 if (ierr != MPI_SUCCESS)
255 return ierr;
256
257 ierr = MPI_Type_free(&bigtype);
258 if (ierr != MPI_SUCCESS)
259 return ierr;
260 return MPI_SUCCESS;
261# endif
262 }
263
269 inline int
270 File_write_at_c(MPI_File fh,
271 MPI_Offset offset,
272 const void *buf,
273 MPI_Count count,
274 MPI_Datatype datatype,
275 MPI_Status *status)
276 {
278 return MPI_File_write_at(fh, offset, buf, count, datatype, status);
279
280 MPI_Datatype bigtype;
281 int ierr;
282 ierr = Type_contiguous_c(count, datatype, &bigtype);
283 if (ierr != MPI_SUCCESS)
284 return ierr;
285 ierr = MPI_Type_commit(&bigtype);
286 if (ierr != MPI_SUCCESS)
287 return ierr;
288
289 ierr = MPI_File_write_at(fh, offset, buf, 1, bigtype, status);
290 if (ierr != MPI_SUCCESS)
291 return ierr;
292
293 ierr = MPI_Type_free(&bigtype);
294 if (ierr != MPI_SUCCESS)
295 return ierr;
296 return MPI_SUCCESS;
297 }
298
305 inline int
307 MPI_Offset offset,
308 const void *buf,
309 MPI_Count count,
310 MPI_Datatype datatype,
311 MPI_Status *status)
312 {
314 return MPI_File_write_at_all(
315 fh, offset, buf, count, datatype, status);
316
317 MPI_Datatype bigtype;
318 int ierr;
319 ierr = Type_contiguous_c(count, datatype, &bigtype);
320 if (ierr != MPI_SUCCESS)
321 return ierr;
322 ierr = MPI_Type_commit(&bigtype);
323 if (ierr != MPI_SUCCESS)
324 return ierr;
325
326 ierr = MPI_File_write_at_all(fh, offset, buf, 1, bigtype, status);
327 if (ierr != MPI_SUCCESS)
328 return ierr;
329
330 ierr = MPI_Type_free(&bigtype);
331 if (ierr != MPI_SUCCESS)
332 return ierr;
333 return MPI_SUCCESS;
334 }
335
341 inline int
343 const void *buf,
344 MPI_Count count,
345 MPI_Datatype datatype,
346 MPI_Status *status)
347 {
349 return MPI_File_write_ordered(fh, buf, count, datatype, status);
350
351 MPI_Datatype bigtype;
352 int ierr;
353 ierr = Type_contiguous_c(count, datatype, &bigtype);
354 if (ierr != MPI_SUCCESS)
355 return ierr;
356 ierr = MPI_Type_commit(&bigtype);
357 if (ierr != MPI_SUCCESS)
358 return ierr;
359
360 ierr = MPI_File_write_ordered(fh, buf, 1, bigtype, status);
361 if (ierr != MPI_SUCCESS)
362 return ierr;
363
364 ierr = MPI_Type_free(&bigtype);
365 if (ierr != MPI_SUCCESS)
366 return ierr;
367 return MPI_SUCCESS;
368 }
369
376 inline int
377 File_read_at_c(MPI_File fh,
378 MPI_Offset offset,
379 void *buf,
380 MPI_Count count,
381 MPI_Datatype datatype,
382 MPI_Status *status)
383 {
385 return MPI_File_read_at(fh, offset, buf, count, datatype, status);
386
387 MPI_Datatype bigtype;
388 int ierr;
389 ierr = Type_contiguous_c(count, datatype, &bigtype);
390 if (ierr != MPI_SUCCESS)
391 return ierr;
392 ierr = MPI_Type_commit(&bigtype);
393 if (ierr != MPI_SUCCESS)
394 return ierr;
395
396 ierr = MPI_File_read_at(fh, offset, buf, 1, bigtype, status);
397 if (ierr != MPI_SUCCESS)
398 return ierr;
399
400 ierr = MPI_Type_free(&bigtype);
401 if (ierr != MPI_SUCCESS)
402 return ierr;
403 return MPI_SUCCESS;
404 }
405
412 inline int
414 MPI_Offset offset,
415 void *buf,
416 MPI_Count count,
417 MPI_Datatype datatype,
418 MPI_Status *status)
419 {
421 return MPI_File_read_at_all(fh, offset, buf, count, datatype, status);
422
423 MPI_Datatype bigtype;
424 int ierr;
425 ierr = Type_contiguous_c(count, datatype, &bigtype);
426 if (ierr != MPI_SUCCESS)
427 return ierr;
428 ierr = MPI_Type_commit(&bigtype);
429 if (ierr != MPI_SUCCESS)
430 return ierr;
431
432 ierr = MPI_File_read_at_all(fh, offset, buf, 1, bigtype, status);
433 if (ierr != MPI_SUCCESS)
434 return ierr;
435
436 ierr = MPI_Type_free(&bigtype);
437 if (ierr != MPI_SUCCESS)
438 return ierr;
439 return MPI_SUCCESS;
440 }
441
442 } // namespace LargeCount
443 } // namespace MPI
444} // namespace Utilities
445
446#endif
447
449#endif
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_DISABLE_EXTRA_DIAGNOSTICS
Definition config.h:636
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define DEAL_II_ENABLE_EXTRA_DIAGNOSTICS
Definition config.h:680
const MPI_Comm comm
Definition mpi.cc:912
int File_write_at_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_write_ordered_c(MPI_File fh, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int File_write_at_all_c(MPI_File fh, MPI_Offset offset, const void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int Recv_c(void *buf, MPI_Count count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)
int File_read_at_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
int Type_contiguous_c(MPI_Count count, MPI_Datatype oldtype, MPI_Datatype *newtype)
int Bcast_c(void *buf, MPI_Count count, MPI_Datatype datatype, unsigned int root_mpi_rank, MPI_Comm comm)
int Send_c(const void *buf, MPI_Count count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)
int File_read_at_all_c(MPI_File fh, MPI_Offset offset, void *buf, MPI_Count count, MPI_Datatype datatype, MPI_Status *status)
constexpr MPI_Count mpi_max_int_count
Definition types.h:30