UPstreamWindow.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2025 OpenCFD Ltd.
9 -------------------------------------------------------------------------------
10 License
11  This file is part of OpenFOAM.
12 
13  OpenFOAM is free software: you can redistribute it and/or modify it
14  under the terms of the GNU General Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25 
26 \*---------------------------------------------------------------------------*/
27 
28 #include "PstreamGlobals.H"
29 #include "profilingPstream.H"
30 
31 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
32 
34 :
35  UPstream::Window(MPI_WIN_NULL)
36 {}
37 
38 
39 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
40 
42 {
43  return MPI_WIN_NULL != PstreamUtils::Cast::to_mpi(*this);
44 }
45 
46 
48 {
49  *this = UPstream::Window(MPI_WIN_NULL);
50 }
51 
52 
54 {
55  int val = 0;
56 
57  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
58  MPI_Group group;
59 
60  // Get num of ranks from the group information
61  if
62  (
63  (MPI_WIN_NULL != win)
64  && (MPI_SUCCESS == MPI_Win_get_group(win, &group))
65  )
66  {
67  if (MPI_SUCCESS != MPI_Group_size(group, &val))
68  {
69  val = 0;
70  }
71  MPI_Group_free(&group);
72  }
73 
74  return val;
75 }
76 
77 
78 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
79 
80 //
81 // Allocate a local or shared memory window.
82 // Uses MPI_Win_allocate() or MPI_Win_allocate_shared(), respectively.
83 //
84 static std::pair<void*,int64_t>
86 (
88  MPI_Comm communicator,
89 
90  // [in] number of elements (not bytes)
91  std::streamsize num_elements,
92  // [in] size of each element == sizeof(Type)
93  const int disp_unit,
94  const bool shared
95 )
96 {
97  using namespace Foam;
98 
99  // No-op for non-parallel
100  if (!UPstream::parRun())
101  {
102  *self = UPstream::Window(MPI_WIN_NULL);
103  return {nullptr, 0};
104  }
105 
106  // if (FOAM_UNLIKELY(MPI_COMM_NULL == communicator))
107  // {
108  // FatalErrorInFunction
109  // << "Attempt to use NULL communicator"
110  // << Foam::abort(FatalError);
111  // return false;
112  // }
113 
114  MPI_Win win = PstreamUtils::Cast::to_mpi(*self);
115 
116  // Stringent handling of existing windows
117  if (FOAM_UNLIKELY(MPI_WIN_NULL != win))
118  {
120  << "Window already exists. Use close() first"
122  return {nullptr, 0};
123  }
124 
125  int returnCode(MPI_SUCCESS);
126  void *baseptr = nullptr;
127 
128  if (shared)
129  {
130  returnCode = MPI_Win_allocate_shared
131  (
132  // From num elements -> num of bytes
133  std::streamsize(num_elements * disp_unit),
134  disp_unit,
135  MPI_INFO_NULL,
136  communicator,
137  &baseptr,
138  &win
139  );
140  }
141  else
142  {
143  returnCode = MPI_Win_allocate
144  (
145  // From num elements -> num of bytes
146  std::streamsize(num_elements * disp_unit),
147  disp_unit,
148  MPI_INFO_NULL,
149  communicator,
150  &baseptr,
151  &win
152  );
153  }
154 
155  if (FOAM_UNLIKELY((MPI_SUCCESS != returnCode) || (MPI_WIN_NULL == win)))
156  {
157  if (shared)
158  {
159  FatalError("MPI_Win_allocate_shared()")
161  }
162  else
163  {
164  FatalError("MPI_Win_allocate()")
166  }
167 
168  return {nullptr, 0};
169  }
170 
171  // Now have a window
172  *self = UPstream::Window(win);
173 
174  // The address and the type-specific count
175  return {baseptr, num_elements};
176 }
177 
178 
179 // ------------------------------------------------------------------------- //
180 
181 std::pair<void*,int64_t>
183 (
184  std::streamsize num_elements,
185  int disp_unit,
186  UPstream::Communicator communicator,
187  const bool shared
188 )
189 {
190  return call_window_allocate
191  (
192  this,
193  PstreamUtils::Cast::to_mpi(communicator),
194 
195  num_elements,
196  disp_unit,
197  shared
198  );
199 }
200 
201 
202 std::pair<void*,int64_t>
204 (
205  std::streamsize num_elements,
206  int disp_unit,
207  int communicator, // Index into MPICommunicators_
208  const bool shared
209 )
210 {
211  return call_window_allocate
212  (
213  this,
214  PstreamGlobals::MPICommunicators_[communicator],
215 
216  num_elements,
217  disp_unit,
218  shared
219  );
220 }
221 
222 
223 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
224 
225 // NOTE: Currently no
226 // - MPI_Win_create_dynamic()
227 // - MPI_Win_attach()
228 // - MPI_Win_detach()
229 // since working with their addresses (and broadcasting them)
230 // is fairly painful and probably not particularly efficient either
231 
232 //
233 // Create a window to existing memory with MPI_Win_create().
234 //
235 static bool call_window_create
236 (
238  MPI_Comm communicator,
239 
240  // [in] base address
241  void *baseptr,
242  // [in] number of elements (not bytes)
243  std::streamsize num_elements,
244  // [in] size of each element == sizeof(Type)
245  const int disp_unit
246 )
247 {
248  using namespace Foam;
249 
250  // No-op for non-parallel
251  if (!UPstream::parRun())
252  {
253  *self = UPstream::Window(MPI_WIN_NULL);
254  return false;
255  }
256 
257  // if (FOAM_UNLIKELY(MPI_COMM_NULL == communicator))
258  // {
259  // using namespace Foam;
260  // FatalErrorInFunction
261  // << "Attempt to use NULL communicator"
262  // << Foam::abort(FatalError);
263  // return false;
264  // }
265 
266  MPI_Win win = PstreamUtils::Cast::to_mpi(*self);
267 
268  // Stringent handling of existing windows
269  if (FOAM_UNLIKELY(MPI_WIN_NULL != win))
270  {
272  << "Window already exists. Use close() first"
274  return false;
275  }
276 
277  // Leave nothing to chance
278  if (!baseptr || !num_elements)
279  {
280  baseptr = nullptr;
281  num_elements = 0;
282  }
283 
284  int returnCode = MPI_Win_create
285  (
286  baseptr,
287  // From num elements -> num of bytes
288  std::streamsize(num_elements * disp_unit),
289  disp_unit,
290  MPI_INFO_NULL,
291  communicator,
292  &win
293  );
294 
295  if (FOAM_UNLIKELY((MPI_SUCCESS != returnCode) || (MPI_WIN_NULL == win)))
296  {
297  FatalError("MPI_Win_create()")
299  return false;
300  }
301 
302  // Now have a window
303  *self = UPstream::Window(win);
304 
305  return (MPI_SUCCESS == returnCode);
306 }
307 
308 
310 (
311  void *baseptr,
312  std::streamsize num_elements,
313  const int disp_unit,
314  UPstream::Communicator communicator
315 )
316 {
317  return call_window_create
318  (
319  this,
320  PstreamUtils::Cast::to_mpi(communicator),
321 
322  baseptr,
323  num_elements,
324  disp_unit
325  );
326 }
327 
328 
330 (
331  void *baseptr,
332  std::streamsize num_elements,
333  const int disp_unit,
334  int communicator // Index into MPICommunicators_
335 )
336 {
337  return call_window_create
338  (
339  this,
340  PstreamGlobals::MPICommunicators_[communicator],
341 
342  baseptr,
343  num_elements,
344  disp_unit
345  );
346 }
347 
348 
349 // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
350 
352 {
353  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
354 
355  if (UPstream::parRun() && (MPI_WIN_NULL != win))
356  {
357  MPI_Win_free(&win);
358  *this = UPstream::Window(MPI_WIN_NULL);
359  }
360 }
361 
362 
363 // * * * * * * * * * * * * * * * Synchronization * * * * * * * * * * * * * * //
364 
366 {
367  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
368 
369  if (UPstream::parRun() && (MPI_WIN_NULL != win))
370  {
371  if (rank < 0)
372  {
373  if (local) MPI_Win_flush_local_all(win);
374  else /* */ MPI_Win_flush_all(win);
375  }
376  else
377  {
378  if (local) MPI_Win_flush_local(rank, win);
379  else /* */ MPI_Win_flush(rank, win);
380  }
381  }
382 }
383 
384 
386 {
387  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
388 
389  if (UPstream::parRun() && (MPI_WIN_NULL != win))
390  {
391  MPI_Win_sync(win);
392  }
393 }
394 
395 
396 void Foam::UPstream::Window::mpi_win_locking(int rank, bool exclusive)
397 {
398  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
399 
400  if (UPstream::parRun() && (MPI_WIN_NULL != win))
401  {
402  if (rank < 0)
403  {
404  MPI_Win_lock_all
405  (
406  (exclusive ? MPI_MODE_NOCHECK : 0),
407  win
408  );
409  }
410  else
411  {
412  MPI_Win_lock
413  (
414  (exclusive ? MPI_LOCK_EXCLUSIVE : MPI_LOCK_SHARED),
415  rank,
416  0, // No assertion
417  win
418  );
419  }
420  }
421 }
422 
423 
425 {
426  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
427 
428  if (UPstream::parRun() && (MPI_WIN_NULL != win))
429  {
430  if (rank < 0)
431  {
432  MPI_Win_unlock_all(win);
433  }
434  else
435  {
436  MPI_Win_unlock(rank, win);
437  }
438  }
439 }
440 
441 
442 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
443 
445 (
446  void* origin, // Type checking done by caller
447  std::streamsize count,
448  const UPstream::dataTypes dataTypeId,
449  int target_rank,
450  int target_disp
451 ) const
452 {
453  if (!UPstream::parRun() || !origin || !count)
454  {
455  // Nothing to do
456  return true;
457  }
458 
459  MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
460  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
461 
462  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
463  {
464  FatalError("MPI_Get()")
465  << "Called with MPI_WIN_NULL."
467  return false;
468  }
469 
470  int returnCode = MPI_Get
471  (
472  // origin
473  origin, count, datatype,
474  // target
475  target_rank, target_disp, count, datatype,
476  // window
477  win
478  );
479 
480  // Error handling
481  if (FOAM_UNLIKELY(returnCode != MPI_SUCCESS))
482  {
483  FatalError("MPI_Get()")
485  return false;
486  }
487 
488  return (MPI_SUCCESS == returnCode);
489 }
490 
491 
493 (
494  const void* origin, // Type checking done by caller
495  std::streamsize count,
496  const UPstream::dataTypes dataTypeId,
497  int target_rank,
498  int target_disp
499 ) const
500 {
501  if (!UPstream::parRun() || !origin || !count)
502  {
503  // Nothing to do
504  return true;
505  }
506 
507  MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
508  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
509 
510  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
511  {
512  FatalError("MPI_Put()")
513  << "Called with MPI_WIN_NULL."
515  return false;
516  }
517 
518  int returnCode = MPI_Put
519  (
520  // origin
521  origin, count, datatype,
522  // target
523  target_rank, target_disp, count, datatype,
524  // window
525  win
526  );
527 
528  // Error handling
529  if (FOAM_UNLIKELY(returnCode != MPI_SUCCESS))
530  {
531  FatalError("MPI_Put()")
533  return false;
534  }
535 
536  return (MPI_SUCCESS == returnCode);
537 }
538 
539 
541 (
542  const UPstream::opCodes opCodeId,
543  const void* origin, // Type checking done by caller
544  std::streamsize count,
545  const UPstream::dataTypes dataTypeId,
546  int target_rank,
547  int target_disp
548 ) const
549 {
550  if (UPstream::opCodes::invalid == opCodeId)
551  {
552  // Regular data put - doesn't use/need an op-type!
553  return this->put_data
554  (
555  origin,
556  count,
557  dataTypeId,
558  target_rank,
559  target_disp
560  );
561  }
562 
563  if (!UPstream::parRun() || !origin || !count)
564  {
565  // Nothing to do
566  return true;
567  }
568 
569  MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
570  MPI_Op optype = PstreamGlobals::getOpCode(opCodeId);
571  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
572 
573  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
574  {
575  FatalError("MPI_Accumulate()")
576  << "Called with MPI_WIN_NULL."
578  return false;
579  }
580  if (FOAM_UNLIKELY(MPI_OP_NULL == optype))
581  {
582  FatalError("MPI_Accumulate()")
583  << "Invalid opcode:" << int(opCodeId)
584  << " type:" << int(dataTypeId) << " count:" << label(count) << nl
586  return false;
587  }
588 
589  int returnCode = MPI_Accumulate
590  (
591  // origin
592  origin, count, datatype,
593  // target
594  target_rank, target_disp, count, datatype,
595  // operation
596  optype,
597  // window
598  win
599  );
600 
601  // Error handling
602  if (FOAM_UNLIKELY(returnCode != MPI_SUCCESS))
603  {
604  FatalError("MPI_Accumulate()")
606  return false;
607  }
608 
609  return (MPI_SUCCESS == returnCode);
610 }
611 
612 
614 (
615  const UPstream::opCodes opCodeId,
616  const void* origin, // Type checking done by caller
617  void* result, // Type checking done by caller
618  const UPstream::dataTypes dataTypeId,
619  int target_rank,
620  int target_disp
621 ) const
622 {
623  if (!UPstream::parRun())
624  {
625  // Fails in non-parallel
626  return false;
627  }
628 
629  MPI_Datatype datatype = PstreamGlobals::getDataType(dataTypeId);
630  MPI_Op optype = PstreamGlobals::getOpCode(opCodeId);
631  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
632 
633  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
634  {
635  FatalError("MPI_Fetch_and_op()")
636  << "Called with MPI_WIN_NULL."
638  return false;
639  }
640  if (FOAM_UNLIKELY(MPI_OP_NULL == optype))
641  {
642  FatalError("MPI_Fetch_and_op()")
643  << "Invalid opcode:" << int(opCodeId)
644  << " type:" << int(dataTypeId) << nl
646  return false;
647  }
648 
649  int returnCode = MPI_Fetch_and_op
650  (
651  origin, result, datatype,
652  // target
653  target_rank, target_disp,
654  // operation
655  optype,
656  // window
657  win
658  );
659 
660  // Error handling
661  if (FOAM_UNLIKELY(returnCode != MPI_SUCCESS))
662  {
663  FatalError("MPI_Fetch_and_op()")
665  return false;
666  }
667 
668  return (MPI_SUCCESS == returnCode);
669 }
670 
671 
672 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
673 
674 // Check for failure of MPI_Win_get_attr
675 #undef CheckFail_Win_get_attr
676 #define CheckFail_Win_get_attr(returnCode, flag, attribute) \
677 { \
678  if (FOAM_UNLIKELY((MPI_SUCCESS != returnCode) || !flag)) \
679  { \
680  FatalError("MPI_Win_get_attr()") \
681  << "Failed getting attribute " << attribute << endl \
682  << Foam::abort(FatalError); \
683  } \
684 }
685 
686 
687 bool Foam::UPstream::Window::is_shared(const bool failNonShared) const
688 {
689  if (!UPstream::parRun())
690  {
691  // Nothing to do
692  return false;
693  }
694 
695  MPI_Win win = PstreamUtils::Cast::to_mpi(*this);
696 
697  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
698  {
699  return false;
700  }
701 
702  // Error handling flags
703  int returnCode(MPI_ERR_UNKNOWN);
704  int flag(1);
705  int flavour(0);
706 
707  // MPI_WIN_CREATE_FLAVOR : Type (int *)
708  {
709  // const auto key = MPI_WIN_CREATE_FLAVOR;
710  typedef int value_type;
711  void* val(nullptr);
712 
713  returnCode = MPI_Win_get_attr(win, MPI_WIN_CREATE_FLAVOR, &val, &flag);
714  CheckFail_Win_get_attr(returnCode, flag, "MPI_WIN_CREATE_FLAVOR");
715 
716  flavour = int
717  (
718  *static_cast<value_type*>(val)
719  );
720  }
721 
722  if (failNonShared && (MPI_WIN_FLAVOR_SHARED != flavour))
723  {
725  << "Expecting a shared window but had ("
726  << flavour << ") flavour instead" << endl
728  }
729 
730  return (MPI_WIN_FLAVOR_SHARED == flavour);
731 }
732 
733 
734 std::pair<void*,int64_t>
736 (
737  UPstream::Window window,
738  const int expected_disp_unit
739 )
740 {
741  if (!UPstream::parRun())
742  {
743  // Nothing to do
744  return {nullptr, 0};
745  }
746 
747  MPI_Win win = PstreamUtils::Cast::to_mpi(window);
748 
749  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
750  {
751  FatalError("MPI_Win_get_attr()")
752  << "Called with MPI_WIN_NULL."
754  return {nullptr, 0};
755  }
756 
757 
758  // Error handling flags
759  int returnCode(MPI_ERR_UNKNOWN);
760  int flag(1);
761 
762  // Debugging
763  // MPI_WIN_CREATE_FLAVOR : Type (int *)
764  // if (FOAM_UNLIKELY(UPstream::debug & 2))
765  // {
766  // // const auto key = MPI_WIN_CREATE_FLAVOR;
767  // typedef int value_type;
768  // void* val(nullptr);
769  //
770  // returnCode =
771  // MPI_Win_get_attr(win, MPI_WIN_CREATE_FLAVOR, &val, &flag);
772  // CheckFail_Win_get_attr(returnCode, flag, "MPI_WIN_CREATE_FLAVOR");
773  //
774  // int flavour = *static_cast<value_type*>(val);
775  // Perr<< "Window created with flavour (" << flavour << ')' << endl;
776  // }
777 
778  std::pair<void*,int64_t> result(nullptr, 0);
779 
780  // The window size
781  // MPI_WIN_SIZE : Type (MPI_Aint *)
782  {
783  // const auto key = MPI_WIN_SIZE;
784  typedef MPI_Aint value_type;
785  void* val(nullptr);
786 
787  returnCode = MPI_Win_get_attr(win, MPI_WIN_SIZE, &val, &flag);
788  CheckFail_Win_get_attr(returnCode, flag, "MPI_WIN_SIZE");
789 
790  result.second = *static_cast<value_type*>(val);
791  }
792 
793  // Early exit
794  if (result.second == 0)
795  {
796  return {nullptr, 0};
797  }
798 
799  // The base address
800  // MPI_WIN_BASE : Type (void *)
801  {
802  // const auto key = MPI_WIN_BASE;
803  void* value(nullptr);
804 
805  returnCode = MPI_Win_get_attr(win, MPI_WIN_BASE, &value, &flag);
806  CheckFail_Win_get_attr(returnCode, flag, "MPI_WIN_BASE");
807 
808  result.first = value;
809  }
810 
811  // Early exit - this probably can never happen
812  // (ie, nullptr but non-zero size)
813  if (result.first == nullptr)
814  {
815  return {nullptr, 0};
816  }
817 
818  // Scale count by the expected displacement unit
819  if (expected_disp_unit)
820  {
821  result.second /= expected_disp_unit;
822 
823  int disp_unit = 1;
824 
825  // The displacement units
826  // MPI_WIN_DISP_UNIT : Type (int *)
827  {
828  // const auto key = MPI_WIN_DISP_UNIT;
829  typedef int value_type;
830  void* val(nullptr);
831 
832  returnCode = MPI_Win_get_attr(win, MPI_WIN_DISP_UNIT, &val, &flag);
833  CheckFail_Win_get_attr(returnCode, flag, "MPI_WIN_DISP_UNIT");
834 
835  disp_unit = *static_cast<value_type*>(val);
836  }
837 
838  // Error if the expected disp_unit is incorrect
839  // - ignore this check if the window is empty
840 
841  if (expected_disp_unit != disp_unit)
842  {
844  << "Window [size=" << result.second
845  << "] created with Type size=" << disp_unit
846  << " but expecting Type size=" << expected_disp_unit << endl
848  }
849  }
850 
851  return result;
852 }
853 
854 
855 std::pair<void*,int64_t>
857 (
858  UPstream::Window window,
859  int target_rank,
860  const int expected_disp_unit
861 )
862 {
863  if (!UPstream::parRun())
864  {
865  // Nothing to do
866  return {nullptr, 0};
867  }
868 
869  MPI_Win win = PstreamUtils::Cast::to_mpi(window);
870 
871  if (FOAM_UNLIKELY(MPI_WIN_NULL == win))
872  {
873  FatalError("MPI_Win_shared_query()")
874  << "Called with MPI_WIN_NULL."
876  return {nullptr, 0};
877  }
878 
879  // Fail if window is not shared
880  const bool shared = window.is_shared(true);
881 
882  if (!shared)
883  {
884  return {nullptr, 0};
885  }
886 
887  // Initial values and fallback
888  MPI_Aint num_bytes = 0;
889  void *baseptr = nullptr;
890  int disp_unit = 1;
891 
892  int returnCode = MPI_Win_shared_query
893  (
894  win,
895  target_rank,
896  &num_bytes,
897  &disp_unit,
898  &baseptr
899  );
900 
901  if (FOAM_UNLIKELY(MPI_SUCCESS != returnCode))
902  {
903  FatalError("MPI_Win_shared_query()")
905  return {nullptr, 0};
906  }
907 
908  std::pair<void*,int64_t> result(baseptr, num_bytes);
909 
910  // Scale count by the expected displacement unit
911  // - probably Fatal not to supply this value
912  //
913  // Note that with share the baseptr will be non-null even if the
914  // local window has zero bytes. This maintains the contiguous
915  // addressing across all ranks
916 
917  if (result.second && expected_disp_unit)
918  {
919  result.second /= expected_disp_unit;
920 
921  // Error if the expected disp_unit is incorrect
922  // - ignore this check if the window is empty
923 
924  if (expected_disp_unit != disp_unit)
925  {
927  << "Window on rank(" << target_rank
928  << ") [size=" << result.second
929  << "] created with Type size=" << disp_unit
930  << " but expecting Type size=" << expected_disp_unit << endl
932  }
933  }
934 
935  return result;
936 }
937 
938 
939 #undef CheckFail_Win_get_attr
940 
941 
942 // ************************************************************************* //
int size() const
The number of ranks associated with the window group.
bool mpi_win_create(void *baseptr, std::streamsize num_elements, int disp_unit, UPstream::Communicator communicator)
Create window onto existing memory with MPI_Win_create().
void mpi_win_flushing(int rank, bool local=false)
Entry point to MPI_Win_flush(), MPI_Win_flush_all(), MPI_Win_flush_local(), MPI_Win_flush_local_all()...
An opaque wrapper for MPI_Comm with a vendor-independent representation without any <mpi...
Definition: UPstream.H:2451
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:600
void mpi_win_unlocking(int rank)
Entry point to MPI_Win_unlock(), MPI_Win_unlock_all().
An opaque wrapper for MPI_Win with a vendor-independent representation and without any <mpi...
static std::pair< void *, int64_t > mpi_win_query(UPstream::Window window, const int expected_disp_unit)
Retrieve window sizing information as address/count tuple. The expected sizeof(Type) is supplied as a...
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
bool good() const noexcept
True if not equal to MPI_WIN_NULL.
DynamicList< MPI_Comm > MPICommunicators_
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:529
static bool & parRun() noexcept
Test if this a parallel run.
Definition: UPstream.H:1586
static Type to_mpi(UPstream::Communicator arg) noexcept
Cast UPstream::Communicator to MPI_Comm.
Definition: openfoam_mpi.H:54
bool mpi_fetch_and_op(const UPstream::opCodes opCodeId, const void *origin, void *result, const UPstream::dataTypes dataTypeId, int target_rank, int target_disp=0) const
Retrieve the remote content (a single value) and then combine in new content.
opCodes
Mapping of some MPI op codes.
Definition: UPstream.H:145
constexpr const char *const group
Group name for atomic constants.
unsigned int count(const UList< bool > &bools, const bool val=true)
Count number of &#39;true&#39; entries.
Definition: BitOps.H:73
Window() noexcept
Default construct as MPI_WIN_NULL.
void sync()
MPI_Win_sync() - ignored if the window is not active.
bool get_data(void *origin, std::streamsize count, const UPstream::dataTypes dataTypeId, int target_rank, int target_disp=0) const
Get buffer contents from given rank.
#define CheckFail_Win_get_attr(returnCode, flag, attribute)
std::pair< void *, int64_t > mpi_win_allocate(std::streamsize num_elements, int disp_unit, UPstream::Communicator communicator, const bool shared=false)
Allocate a local or shared memory window. Uses MPI_Win_allocate() or MPI_Win_allocate_shared(), respectively.
#define FOAM_UNLIKELY(cond)
Definition: stdFoam.H:64
bool local
Definition: EEqn.H:20
MPI_Op getOpCode(UPstream::opCodes id)
Lookup of opCodes enumeration as an MPI_Op.
bool is_shared(const bool failNonShared=false) const
Test if the window is a shared memory window.
errorManip< error > abort(error &err)
Definition: errorManip.H:139
bool put_data(const void *origin, std::streamsize count, const UPstream::dataTypes dataTypeId, int target_rank, int target_disp=0) const
Put buffer contents to given rank.
void close()
MPI_Win_free(). Closes the window view and frees any associated memory,.
const direction noexcept
Definition: scalarImpl.H:255
static bool call_window_create(Foam::UPstream::Window *self, MPI_Comm communicator, void *baseptr, std::streamsize num_elements, const int disp_unit)
dataTypes
Mapping of some fundamental and aggregate types to MPI data types.
Definition: UPstream.H:103
void mpi_win_locking(int rank, bool exclusive=false)
Entry point to MPI_Win_lock(), MPI_Win_lock_all(), optionally as exclusive lock.
static std::pair< void *, int64_t > mpi_win_query_shared(UPstream::Window window, int target_rank, const int expected_disp_unit)
Retrieve shared window information as address/count tuple. The expected sizeof(Type) is supplied as a...
MPI_Datatype getDataType(UPstream::dataTypes id)
Lookup of dataTypes enumeration as an MPI_Datatype.
::Foam::direction rank(const expressions::valueTypeCode) noexcept
The vector-space rank associated with given valueTypeCode.
Definition: exprTraits.C:70
static std::pair< void *, int64_t > call_window_allocate(Foam::UPstream::Window *self, MPI_Comm communicator, std::streamsize num_elements, const int disp_unit, const bool shared)
void reset() noexcept
Reset to default constructed value (MPI_WIN_NULL)
Namespace for OpenFOAM.