20 #ifndef GEOS_COMMON_MPIWRAPPER_HPP_
21 #define GEOS_COMMON_MPIWRAPPER_HPP_
29 #if defined(GEOS_USE_MPI)
31 #define MPI_PARAM( x ) x
33 #define MPI_PARAM( x )
36 #define MPI_COMM_NULL ((MPI_Comm)0x04000000)
37 #define MPI_COMM_WORLD ((MPI_Comm)0x44000000)
38 #define MPI_COMM_SELF ((MPI_Comm)0x40000000)
41 typedef int MPI_Datatype;
42 #define MPI_CHAR ((MPI_Datatype)0x4c000101)
43 #define MPI_SIGNED_CHAR ((MPI_Datatype)0x4c000118)
44 #define MPI_UNSIGNED_CHAR ((MPI_Datatype)0x4c000102)
45 #define MPI_BYTE ((MPI_Datatype)0x4c00010d)
46 #define MPI_C_BOOL ((MPI_Datatype)0x4c00013f)
47 #define MPI_WCHAR ((MPI_Datatype)0x4c00040e)
48 #define MPI_SHORT ((MPI_Datatype)0x4c000203)
49 #define MPI_UNSIGNED_SHORT ((MPI_Datatype)0x4c000204)
50 #define MPI_INT ((MPI_Datatype)0x4c000405)
51 #define MPI_UNSIGNED ((MPI_Datatype)0x4c000406)
52 #define MPI_LONG ((MPI_Datatype)0x4c000807)
53 #define MPI_UNSIGNED_LONG ((MPI_Datatype)0x4c000808)
54 #define MPI_FLOAT ((MPI_Datatype)0x4c00040a)
55 #define MPI_DOUBLE ((MPI_Datatype)0x4c00080b)
56 #define MPI_LONG_DOUBLE ((MPI_Datatype)0x4c00100c)
57 #define MPI_LONG_LONG_INT ((MPI_Datatype)0x4c000809)
58 #define MPI_UNSIGNED_LONG_LONG ((MPI_Datatype)0x4c000819)
59 #define MPI_LONG_LONG MPI_LONG_LONG_INT
63 #define MPI_MAX (MPI_Op)(0x58000001)
64 #define MPI_MIN (MPI_Op)(0x58000002)
65 #define MPI_SUM (MPI_Op)(0x58000003)
66 #define MPI_PROD (MPI_Op)(0x58000004)
67 #define MPI_LAND (MPI_Op)(0x58000005)
68 #define MPI_BAND (MPI_Op)(0x58000006)
69 #define MPI_LOR (MPI_Op)(0x58000007)
70 #define MPI_BOR (MPI_Op)(0x58000008)
71 #define MPI_LXOR (MPI_Op)(0x58000009)
72 #define MPI_BXOR (MPI_Op)(0x5800000a)
73 #define MPI_MINLOC (MPI_Op)(0x5800000b)
74 #define MPI_MAXLOC (MPI_Op)(0x5800000c)
75 #define MPI_REPLACE (MPI_Op)(0x5800000d)
76 #define MPI_NO_OP (MPI_Op)(0x5800000e)
79 #define MPI_UNDEFINED (-32766)
80 #define MPI_STATUS_IGNORE (MPI_Status *)1
81 #define MPI_STATUSES_IGNORE (MPI_Status *)1
82 #define MPI_REQUEST_NULL ((MPI_Request)0x2c000000)
83 typedef int MPI_Request;
86 #define MPI_INFO_NULL (MPI_Info)(0x60000000)
96 #define MPI_CHECK_ERROR( error ) ((void) error)
98 #define MPI_CHECK_ERROR( error ) GEOS_ERROR_IF_NE( error, MPI_SUCCESS );
154 template<
typename FIRST,
typename SECOND >
177 static void barrier( MPI_Comm
const & MPI_PARAM( comm )=
MPI_COMM_GEOS );
179 static int cartCoords( MPI_Comm comm,
int rank,
int maxdims,
int coords[] );
181 static int cartCreate( MPI_Comm comm_old,
int ndims,
const int dims[],
const int periods[],
182 int reorder, MPI_Comm * comm_cart );
184 static int cartRank( MPI_Comm comm,
const int coords[] );
186 static void commFree( MPI_Comm & comm );
188 static int commRank( MPI_Comm
const & MPI_PARAM( comm )=
MPI_COMM_GEOS );
190 static int commSize( MPI_Comm
const & MPI_PARAM( comm )=
MPI_COMM_GEOS );
192 static bool commCompare( MPI_Comm
const & comm1, MPI_Comm
const & comm2 );
194 static bool initialized();
196 static int init(
int * argc,
char * * * argv );
204 static MPI_Comm commDup( MPI_Comm
const comm );
206 static MPI_Comm commSplit( MPI_Comm
const comm,
int color,
int key );
208 static int test( MPI_Request * request,
int * flag,
MPI_Status * status );
210 static int testAny(
int count, MPI_Request array_of_requests[],
int * idx,
int * flags,
MPI_Status array_of_statuses[] );
212 static int testSome(
int count, MPI_Request array_of_requests[],
int * outcount,
int array_of_indices[],
MPI_Status array_of_statuses[] );
214 static int testAll(
int count, MPI_Request array_of_requests[],
int * flags,
MPI_Status array_of_statuses[] );
236 static int checkAny(
int count, MPI_Request array_of_requests[],
int * idx,
int * flag,
MPI_Status array_of_statuses[] );
247 static int checkAll(
int count, MPI_Request array_of_requests[],
int * flag,
MPI_Status array_of_statuses[] );
249 static int wait( MPI_Request * request,
MPI_Status * status );
251 static int waitAny(
int count, MPI_Request array_of_requests[],
int * indx,
MPI_Status array_of_statuses[] );
253 static int waitSome(
int count, MPI_Request array_of_requests[],
int * outcount,
int array_of_indices[],
MPI_Status array_of_statuses[] );
255 static int waitAll(
int count, MPI_Request array_of_requests[],
MPI_Status array_of_statuses[] );
257 static double wtime(
void );
270 MPI_Request array_of_requests[],
272 std::function< MPI_Request (
int ) > func );
284 MPI_Request array_of_requests[],
286 std::function< MPI_Request (
int ) > func );
301 stdVector< std::tuple< MPI_Request *,
MPI_Status *, std::function< MPI_Request (
int ) > > >
const & phases );
317 stdVector< std::tuple< MPI_Request *,
MPI_Status *, std::function< MPI_Request (
int ) > > >
const & phases );
320 #if !defined(GEOS_USE_MPI)
324 return tagToPointers;
339 template<
typename CONTAINER >
362 typename VALUE_T =
typename CONTAINER::value_type,
363 typename = std::enable_if_t<
364 std::is_trivially_copyable_v< VALUE_T > &&
365 std::is_same_v< decltype(std::declval< CONTAINER >().data()), VALUE_T * > &&
366 std::is_same_v< decltype(std::declval< CONTAINER >().size()),
std::size_t >
392 template<
typename T_SEND,
typename T_RECV >
411 template<
typename T_SEND,
typename T_RECV >
425 template<
typename T >
428 template<
typename T >
433 template<
typename T >
446 template<
typename T >
457 template<
typename T >
468 template<
typename SRC_CONTAINER_TYPE,
typename DST_CONTAINER_TYPE >
480 template<
typename SRC_CONTAINER_TYPE,
typename DST_CONTAINER_TYPE >
481 static void allReduce( SRC_CONTAINER_TYPE
const & src, DST_CONTAINER_TYPE & dst,
int const count,
Reduction const op, MPI_Comm
const comm );
492 template<
typename FIRST,
typename SECOND, PairReduction OP >
506 template<
typename FIRST,
typename SECOND,
typename CONTAINER, PairReduction OP >
519 template<
typename T >
520 static int reduce( T
const * sendbuf, T * recvbuf,
int count, MPI_Op op,
int root, MPI_Comm comm =
MPI_COMM_GEOS );
530 template<
typename T >
541 template<
typename T >
545 template<
typename T >
546 static int scan( T
const * sendbuf, T * recvbuf,
int count, MPI_Op op, MPI_Comm comm =
MPI_COMM_GEOS );
548 template<
typename T >
549 static int exscan( T
const * sendbuf, T * recvbuf,
int count, MPI_Op op, MPI_Comm comm =
MPI_COMM_GEOS );
559 template<
typename T >
569 template<
typename T >
584 template<
typename TS,
typename TR >
585 static int gather( TS
const *
const sendbuf,
603 template<
typename T,
typename DST_CONTAINER,
604 typename = std::enable_if_t<
605 std::is_trivially_copyable_v< T > &&
606 std::is_same_v< decltype(std::declval< DST_CONTAINER >().size()),
std::size_t > &&
607 std::is_same_v< decltype(std::declval< DST_CONTAINER >().data()), T * > > >
609 DST_CONTAINER & destValuesBuffer,
627 template<
typename TS,
typename TR >
631 const int * recvcounts,
649 template<
typename TS,
typename TR >
671 template<
typename TS,
typename TR >
673 const int * sendcounts,
689 template<
typename T >
691 int MPI_PARAM( source ),
693 MPI_Comm MPI_PARAM( comm ),
696 template<
typename T >
698 int MPI_PARAM( dest ),
700 MPI_Comm MPI_PARAM( comm ),
701 MPI_Request * MPI_PARAM( request ) );
713 template<
typename T >
719 MPI_Request * request );
730 template<
typename T >
731 static int send( T
const *
const buf,
747 template<
typename T >
748 static int iSend( T
const *
const buf,
753 MPI_Request * request );
762 template<
typename U,
typename T >
770 template<
typename T >
779 template<
typename T >
787 template<
typename T >
796 template<
typename T >
805 template<
typename FIRST,
typename SECOND >
814 template<
typename FIRST,
typename SECOND,
typename CONTAINER >
822 template<
typename T >
831 template<
typename T >
840 template<
typename FIRST,
typename SECOND >
849 template<
typename FIRST,
typename SECOND,
typename CONTAINER >
863 template<
typename T >
864 static int allReduce( T
const * sendbuf, T * recvbuf,
int count, MPI_Op op, MPI_Comm comm =
MPI_COMM_GEOS );
871 struct ManagedResources
874 std::set< MPI_Op > m_mpiOps;
877 std::set< MPI_Datatype > m_mpiTypes;
890 ManagedResources & getManagedResources();
892 template<
typename T,
typename ENABLE =
void >
893 struct MpiTypeImpl {};
895 #define ADD_MPI_TYPE_MAP( T, MPI_T ) \
896 template<> struct MpiTypeImpl< T > { static MPI_Datatype get() { return MPI_T; } }
898 ADD_MPI_TYPE_MAP(
float, MPI_FLOAT );
899 ADD_MPI_TYPE_MAP(
double, MPI_DOUBLE );
901 ADD_MPI_TYPE_MAP(
char, MPI_CHAR );
902 ADD_MPI_TYPE_MAP(
signed char, MPI_SIGNED_CHAR );
903 ADD_MPI_TYPE_MAP(
unsigned char, MPI_UNSIGNED_CHAR );
905 ADD_MPI_TYPE_MAP(
int, MPI_INT );
906 ADD_MPI_TYPE_MAP(
long int, MPI_LONG );
907 ADD_MPI_TYPE_MAP(
long long int, MPI_LONG_LONG );
909 ADD_MPI_TYPE_MAP(
unsigned int, MPI_UNSIGNED );
910 ADD_MPI_TYPE_MAP(
unsigned long int, MPI_UNSIGNED_LONG );
911 ADD_MPI_TYPE_MAP(
unsigned long long int, MPI_UNSIGNED_LONG_LONG );
913 #undef ADD_MPI_TYPE_MAP
915 template<
typename T >
916 struct MpiTypeImpl< T, std::enable_if_t< std::is_enum< T >::value > >
918 static MPI_Datatype get() {
return MpiTypeImpl< std::underlying_type_t< T > >::get(); }
922 struct MpiTypeImpl< bool * >
924 static MPI_Datatype get()
932 template<
typename T >
933 MPI_Datatype getMpiType()
935 return MpiTypeImpl< T >::get();
938 template<
typename FIRST,
typename SECOND >
939 MPI_Datatype getMpiPairType()
941 static_assert(
"no default implementation, please add a template specialization and add it in the \"testMpiWrapper\" unit test." );
944 template<> MPI_Datatype getMpiPairType< int, int >();
945 template<> MPI_Datatype getMpiPairType< long int, int >();
946 template<> MPI_Datatype getMpiPairType< long int, long int >();
947 template<> MPI_Datatype getMpiPairType< long long int, long long int >();
948 template<> MPI_Datatype getMpiPairType< float, int >();
949 template<> MPI_Datatype getMpiPairType< double, int >();
950 template<> MPI_Datatype getMpiPairType< double, long int >();
951 template<> MPI_Datatype getMpiPairType< double, long long int >();
952 template<> MPI_Datatype getMpiPairType< double, double >();
955 template<
typename FIRST,
typename SECOND, MpiWrapper::PairReduction OP >
956 MPI_Op getMpiPairReductionOp()
958 static auto const createOpHolder = [] () {
959 using PAIR_T = MpiWrapper::PairType< FIRST, SECOND >;
961 auto const customOpFunc =
962 [](
void * invec,
void * inoutvec,
int * len, MPI_Datatype * )
964 for(
int i = 0; i < *len; ++i )
966 PAIR_T & in =
static_cast< PAIR_T *
>(invec)[i];
967 PAIR_T & inout =
static_cast< PAIR_T *
>(inoutvec)[i];
970 if( std::tie( in.first, in.second ) < std::tie( inout.first, inout.second ) )
975 if( std::tie( in.first, in.second ) > std::tie( inout.first, inout.second ) )
984 internal::getManagedResources().m_mpiOps.emplace( mpiOp );
988 static MPI_Op mpiOp{ createOpHolder() };
1023 GEOS_ERROR(
"Unsupported reduction operation" );
1028 template<
typename CONTAINER,
typename VALUE_T,
typename >
1032 integer const numRanks = MpiWrapper::commSize();
1033 integer const numLocalValues =
static_cast< integer >(localBuffer.size());
1037 if( MpiWrapper::commRank() == 0 )
1039 gatherResult.counts.resize( numRanks );
1040 gatherResult.offsets.resize( numRanks );
1046 if( MpiWrapper::commRank() == 0 )
1049 for(
integer i = 0; i < numRanks; ++i )
1051 gatherResult.offsets[i] = totalSize;
1052 totalSize += gatherResult.counts[i];
1054 gatherResult.data.resize( totalSize );
1059 gatherResult.data.data(),
1060 gatherResult.counts.data(),
1061 gatherResult.offsets.data(),
1064 return gatherResult;
1067 template<
typename T_SEND,
typename T_RECV >
1070 T_RECV *
const recvbuf,
1072 MPI_Comm MPI_PARAM( comm ) )
1075 return MPI_Allgather( sendbuf, sendcount, internal::getMpiType< T_SEND >(),
1076 recvbuf, recvcount, internal::getMpiType< T_RECV >(),
1079 static_assert( std::is_same< T_SEND, T_RECV >::value,
1080 "MpiWrapper::allgather() for serial run requires send and receive buffers are of the same type" );
1082 std::copy( sendbuf, sendbuf + sendcount, recvbuf )
1087 template<
typename T_SEND,
typename T_RECV >
1090 T_RECV *
const recvbuf,
1092 int * displacements,
1093 MPI_Comm MPI_PARAM( comm ) )
1096 return MPI_Allgatherv( sendbuf, sendcount, internal::getMpiType< T_SEND >(),
1097 recvbuf, recvcounts, displacements, internal::getMpiType< T_RECV >(),
1100 static_assert( std::is_same< T_SEND, T_RECV >::value,
1101 "MpiWrapper::allgatherv() for serial run requires send and receive buffers are of the same type" );
1103 std::copy( sendbuf, sendbuf + sendcount, recvbuf )
1109 template<
typename T >
1113 int const mpiSize = commSize( comm );
1114 allValues.resize( mpiSize );
1116 MPI_Datatype
const MPI_TYPE = internal::getMpiType< T >();
1118 MPI_Allgather( &myValue, 1, MPI_TYPE, allValues.data(), 1, MPI_TYPE, comm );
1121 allValues.resize( 1 );
1122 allValues[0] = myValue;
1126 template<
typename T >
1128 array1d< T > & allValues,
1129 MPI_Comm MPI_PARAM( comm ) )
1131 int const sendSize = LvArray::integerConversion< int >( sendValues.size() );
1133 int const mpiSize = commSize( comm );
1134 allValues.resize( mpiSize * sendSize );
1135 return MPI_Allgather( sendValues.data(),
1137 internal::getMpiType< T >(),
1140 internal::getMpiType< T >(),
1144 allValues.resize( sendSize );
1147 allValues[a] = sendValues[a];
1153 template<
typename T >
1154 int MpiWrapper::allGatherv( arrayView1d< T const >
const & sendValues,
1155 array1d< T > & allValues,
1156 MPI_Comm MPI_PARAM( comm ) )
1158 int const sendSize = LvArray::integerConversion< int >( sendValues.size() );
1160 int const mpiSize = commSize( comm );
1161 array1d< int > counts;
1163 array1d< int > displs( mpiSize + 1 );
1164 std::partial_sum( counts.begin(), counts.end(), displs.begin() + 1 );
1165 allValues.resize( displs.back() );
1166 return MPI_Allgatherv( sendValues.data(),
1168 internal::getMpiType< T >(),
1172 internal::getMpiType< T >(),
1176 allValues.resize( sendSize );
1179 allValues[a] = sendValues[a];
1185 template<
typename T >
1189 MPI_Op
const MPI_PARAM( op ),
1190 MPI_Comm
const MPI_PARAM( comm ) )
1193 MPI_Datatype
const mpiType = internal::getMpiType< T >();
1194 return MPI_Allreduce( sendbuf == recvbuf ? MPI_IN_PLACE : sendbuf, recvbuf, count, mpiType, op, comm );
1196 if( sendbuf != recvbuf )
1198 memcpy( recvbuf, sendbuf, count *
sizeof( T ) );
1204 template<
typename T >
1208 MPI_Op
const MPI_PARAM( op ),
1210 MPI_Comm
const MPI_PARAM( comm ) )
1213 MPI_Datatype
const mpiType = internal::getMpiType< T >();
1214 return MPI_Reduce( sendbuf == recvbuf ? MPI_IN_PLACE : sendbuf, recvbuf, count, mpiType, op, root, comm );
1216 if( sendbuf != recvbuf )
1218 memcpy( recvbuf, sendbuf, count *
sizeof( T ) );
1224 template<
typename T >
1225 int MpiWrapper::scan( T
const *
const sendbuf,
1228 MPI_Op MPI_PARAM( op ),
1229 MPI_Comm MPI_PARAM( comm ) )
1232 return MPI_Scan( sendbuf, recvbuf, count, internal::getMpiType< T >(), op, comm );
1234 memcpy( recvbuf, sendbuf, count*
sizeof(T) );
1239 template<
typename T >
1240 int MpiWrapper::exscan( T
const *
const MPI_PARAM( sendbuf ),
1243 MPI_Op MPI_PARAM( op ),
1244 MPI_Comm MPI_PARAM( comm ) )
1247 return MPI_Exscan( sendbuf, recvbuf, count, internal::getMpiType< T >(), op, comm );
1249 memset( recvbuf, 0, count*
sizeof(T) );
1254 template<
typename T >
1256 int MPI_PARAM( count ),
1257 int MPI_PARAM( root ),
1258 MPI_Comm MPI_PARAM( comm ) )
1261 return MPI_Bcast( buffer, count, internal::getMpiType< T >(), root, comm );
1268 template<
typename T >
1269 void MpiWrapper::broadcast( T & MPI_PARAM( value ),
int MPI_PARAM( srcRank ), MPI_Comm MPI_PARAM( comm ) )
1272 MPI_Bcast( &value, 1, internal::getMpiType< T >(), srcRank, comm );
1278 void MpiWrapper::broadcast< string >(
string & MPI_PARAM( value ),
1279 int MPI_PARAM( srcRank ),
1280 MPI_Comm MPI_PARAM( comm ) )
1283 int size = LvArray::integerConversion< int >( value.size() );
1285 value.resize( size );
1286 MPI_Bcast(
const_cast< char *
>( value.data() ), size, internal::getMpiType< char >(), srcRank, comm );
1290 template<
typename TS,
typename TR >
1295 int MPI_PARAM( root ),
1296 MPI_Comm MPI_PARAM( comm ) )
1299 return MPI_Gather( sendbuf, sendcount, internal::getMpiType< TS >(),
1300 recvbuf, recvcount, internal::getMpiType< TR >(),
1303 static_assert( std::is_same< TS, TR >::value,
1304 "MpiWrapper::gather() for serial run requires send and receive buffers are of the same type" );
1305 std::size_t const sendBufferSize = sendcount *
sizeof(TS);
1306 std::size_t const recvBufferSize = recvcount *
sizeof(TR);
1307 GEOS_ERROR_IF_NE_MSG( sendBufferSize, recvBufferSize,
"size of send buffer and receive buffer are not equal" );
1308 memcpy( recvbuf, sendbuf, sendBufferSize );
1313 template<
typename T,
typename DST_CONTAINER,
typename >
1315 DST_CONTAINER & destValuesBuffer,
1317 MPI_Comm MPI_PARAM( comm ) )
1319 if( commRank() == 0 )
1321 "Receive buffer is not large enough to contain the values to receive." );
1323 return MPI_Gather( &value,
sizeof( T ), internal::getMpiType< uint8_t >(),
1324 destValuesBuffer.data(),
sizeof( T ), internal::getMpiType< uint8_t >(),
1327 memcpy( destValuesBuffer.data(), &value, sendBufferSize );
1332 template<
typename TS,
typename TR >
1336 const int * recvcounts,
1337 const int * MPI_PARAM( displs ),
1338 int MPI_PARAM( root ),
1339 MPI_Comm MPI_PARAM( comm ) )
1342 return MPI_Gatherv( sendbuf, sendcount, internal::getMpiType< TS >(),
1343 recvbuf, recvcounts, displs, internal::getMpiType< TR >(),
1346 static_assert( std::is_same< TS, TR >::value,
1347 "MpiWrapper::gather() for serial run requires send and receive buffers are of the same type" );
1348 std::size_t const sendBufferSize = sendcount *
sizeof(TS);
1349 std::size_t const recvBufferSize = recvcounts[0] *
sizeof(TR);
1350 GEOS_ERROR_IF_NE_MSG( sendBufferSize, recvBufferSize,
"size of send buffer and receive buffer are not equal" );
1351 memcpy( recvbuf, sendbuf, sendBufferSize );
1357 template<
typename TS,
typename TR >
1362 int MPI_PARAM( root ),
1363 MPI_Comm MPI_PARAM( comm ))
1366 return MPI_Scatter( sendbuf, sendcount, internal::getMpiType< TS >(),
1367 recvbuf, recvcount, internal::getMpiType< TR >(),
1370 static_assert( std::is_same< TS, TR >::value,
1371 "MpiWrapper::scatter() for serial run requires send and receive buffers are of the same type" );
1372 std::size_t const sendBufferSize = sendcount *
sizeof(TS);
1373 std::size_t const recvBufferSize = recvcount *
sizeof(TR);
1374 GEOS_ERROR_IF_NE_MSG( sendBufferSize, recvBufferSize,
"size of send buffer and receive buffer are not equal" );
1375 memcpy( recvbuf, sendbuf, sendBufferSize );
1380 template<
typename TS,
typename TR >
1382 const int * sendcounts,
1383 const int * MPI_PARAM( displs ),
1386 int MPI_PARAM( root ),
1387 MPI_Comm MPI_PARAM( comm ))
1390 return MPI_Scatterv( sendbuf, sendcounts, displs, internal::getMpiType< TS >(),
1391 recvbuf, recvcount, internal::getMpiType< TR >(),
1394 static_assert( std::is_same< TS, TR >::value,
1395 "MpiWrapper::scatterv() for serial run requires send and receive buffers are of the same type" );
1396 std::size_t const sendBufferSize = sendcounts[0] *
sizeof(TS);
1397 std::size_t const recvBufferSize = recvcount *
sizeof(TR);
1398 GEOS_ERROR_IF_NE_MSG( sendBufferSize, recvBufferSize,
"size of send buffer and receive buffer are not equal" );
1399 memcpy( recvbuf, sendbuf, sendBufferSize );
1406 template<
typename T >
1409 int MPI_PARAM( source ),
1411 MPI_Comm MPI_PARAM( comm ),
1412 MPI_Request * MPI_PARAM( request ) )
1416 "Attempting to use an MPI_Request that is still in use." );
1417 return MPI_Irecv( buf, count, internal::getMpiType< T >(), source, tag, comm, request );
1419 stdMap< int, std::pair< int, void * > > & pointerMap = getTagToPointersMap();
1420 stdMap< int, std::pair< int, void * > >::iterator iPointer = pointerMap.find( tag );
1422 if( iPointer==pointerMap.end() )
1424 pointerMap.insert( {tag, {1, buf} } );
1429 "Tag does is assigned, but pointer was not set by iSend." );
1430 memcpy( buf, iPointer->second.second, count*
sizeof(T) );
1431 pointerMap.erase( iPointer );
1437 template<
typename T >
1438 int MpiWrapper::recv( array1d< T > & buf,
1439 int MPI_PARAM( source ),
1441 MPI_Comm MPI_PARAM( comm ),
1447 MPI_Probe( source, tag, comm, &status );
1448 MPI_Get_count( &status, MPI_CHAR, &count );
1451 buf.resize( count /
sizeof( T ) );
1453 return MPI_Recv(
reinterpret_cast< char *
>( buf.data() ),
1466 template<
typename T >
1467 int MpiWrapper::iSend( arrayView1d< T >
const & buf,
1468 int MPI_PARAM( dest ),
1470 MPI_Comm MPI_PARAM( comm ),
1471 MPI_Request * MPI_PARAM( request ) )
1475 "Attempting to use an MPI_Request that is still in use." );
1476 return MPI_Isend(
reinterpret_cast< void const *
>( buf.data() ),
1477 buf.size() *
sizeof( T ),
1489 template<
typename T >
1497 return MPI_Send( buf, count, internal::getMpiType< T >(), dest, tag, comm );
1503 template<
typename T >
1504 int MpiWrapper::iSend( T
const *
const buf,
1506 int MPI_PARAM( dest ),
1508 MPI_Comm MPI_PARAM( comm ),
1509 MPI_Request * MPI_PARAM( request ) )
1513 "Attempting to use an MPI_Request that is still in use." );
1514 return MPI_Isend( buf, count, internal::getMpiType< T >(), dest, tag, comm, request );
1519 if( iPointer==pointerMap.end() )
1521 pointerMap.insert( {tag, {0,
const_cast< T *
>(buf)}
1527 "Tag does is assigned, but pointer was not set by iRecv." );
1528 memcpy( iPointer->second.second, buf, count*
sizeof(T) );
1529 pointerMap.erase( iPointer );
1535 template<
typename U,
typename T >
1541 U
const convertedValue = value;
1542 int const error = MPI_Exscan( &convertedValue, &localResult, 1, internal::getMpiType< U >(), MPI_SUM, comm );
1543 MPI_CHECK_ERROR( error );
1545 if( commRank() == 0 )
1554 template<
typename T >
1562 template<
typename T >
1569 template<
typename SRC_CONTAINER_TYPE,
typename DST_CONTAINER_TYPE >
1573 "The type in the source container must be trivially copyable." );
1575 "The type in the destination container must be trivially copyable." );
1578 "Source and destination containers must have the same value type." );
1584 template<
typename SRC_CONTAINER_TYPE,
typename DST_CONTAINER_TYPE >
1588 "The type in the source container must be trivially copyable." );
1590 "The type in the destination container must be trivially copyable." );
1593 "Source and destination containers must have the same value type." );
1595 allReduce( src.data(), dst.data(), LvArray::integerConversion< int >( src.size() ),
getMpiOp( op ), comm );
1598 template<
typename T >
1604 template<
typename T >
1610 template<
typename T >
1616 template<
typename T >
1622 template<
typename T >
1628 template<
typename T >
1635 template<
typename T >
1643 template<
typename T >
1650 template<
typename FIRST,
typename SECOND, MpiWrapper::PairReduction const OP >
1655 auto const type = internal::getMpiPairType< FIRST, SECOND >();
1656 auto const mpiOp = internal::getMpiPairReductionOp< FIRST, SECOND, OP >();
1658 MPI_Allreduce( MPI_IN_PLACE, &pair, 1, type, mpiOp, comm );
1665 template<
typename FIRST,
typename SECOND,
typename CONTAINER, MpiWrapper::PairReduction const OP >
1670 std::function< PAIR_T( PAIR_T, PAIR_T ) >
const getMin = []( PAIR_T
const & a, PAIR_T
const & b ) {
1671 return ( std::tie( a.first, a.second ) < std::tie( b.first, b.second ) ) ? a : b;
1673 std::function< PAIR_T( PAIR_T, PAIR_T ) >
const getMax = []( PAIR_T
const & a, PAIR_T
const & b ) {
1674 return ( std::tie( a.first, a.second ) > std::tie( b.first, b.second ) ) ? a : b;
1676 PAIR_T
const defaultPair{
1677 OP ==
PairReduction::Min ? std::numeric_limits< FIRST >::max() : std::numeric_limits< FIRST >::lowest(),
1678 OP ==
PairReduction::Min ? std::numeric_limits< SECOND >::max() : std::numeric_limits< SECOND >::lowest()
1681 PAIR_T pair = std::accumulate( pairs.begin(), pairs.end(), defaultPair,
1683 return allReduce< FIRST, SECOND, OP >( pair, comm );
1686 template<
typename FIRST,
typename SECOND >
1688 {
return allReduce< FIRST, SECOND, PairReduction::Min >( pair, comm ); }
1690 template<
typename FIRST,
typename SECOND,
typename CONTAINER >
1692 {
return allReduce< FIRST, SECOND, CONTAINER, PairReduction::Min >( pairs, comm ); }
1694 template<
typename FIRST,
typename SECOND >
1696 {
return allReduce< FIRST, SECOND, PairReduction::Max >( pair, comm ); }
1698 template<
typename FIRST,
typename SECOND,
typename CONTAINER >
1700 {
return allReduce< FIRST, SECOND, CONTAINER, PairReduction::Max >( pairs, comm ); }
#define GEOS_ERROR(...)
Raise a hard error and terminate the program.
#define GEOS_ERROR_IF_LT_MSG(lhs, rhs,...)
Raise a hard error if one value compares less than the other.
#define GEOS_ERROR_IF(COND,...)
Conditionally raise a hard error and terminate the program.
#define GEOS_ERROR_IF_NE_MSG(lhs, rhs,...)
Raise a hard error if two values are not equal.
#define GEOS_ERROR_IF_NE(lhs, rhs)
Raise a hard error if two values are not equal.
#define GEOS_ASSERT_GE(lhs, rhs)
Assert that one value compares greater than or equal to the other in debug builds.
#define GEOS_ASSERT_EQ(lhs, rhs)
Assert that two values compare equal in debug builds.
Lightweight non-owning wrapper over a contiguous range of elements.
constexpr T * data() const noexcept
constexpr size_type size() const noexcept
ArrayView< T, 1 > arrayView1d
Alias for 1D array view.
int MPI_COMM_GEOS
Global MPI communicator used by GEOSX.
GEOS_LOCALINDEX_TYPE localIndex
Local index type (for indexing objects within an MPI partition).
internal::StdMapWrapper< std::map< Key, T, Compare, Allocator >, USE_STD_CONTAINER_BOUNDS_CHECKING > stdMap
std::size_t size_t
Unsigned size type.
int integer
Signed integer type.
Array< T, 1 > array1d
Alias for 1D array.
std::string_view string_view
String type.
internal::StdVectorWrapper< T, Allocator, USE_STD_CONTAINER_BOUNDS_CHECKING > stdVector
Structure holding the result from all the gather operation.
static MPI_Op getMpiOp(Reduction const op)
Returns an MPI_Op associated with our strongly typed Reduction enum.
static int checkAll(int count, MPI_Request array_of_requests[], int *flag, MPI_Status array_of_statuses[])
static int allgatherv(T_SEND const *sendbuf, int sendcount, T_RECV *recvbuf, int *recvcounts, int *displacements, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Allgatherv.
static void gatherStringOnRank0(string_view str, std::function< void(string_view) > &&func)
Gather srting from all ranks to rank 0.
static int check(MPI_Request *request, int *flag, MPI_Status *status)
static int activeWaitAny(const int count, MPI_Request array_of_requests[], MPI_Status array_of_statuses[], std::function< MPI_Request(int) > func)
@ Max
Max pair first value.
@ Min
Min pair first value.
static int activeWaitSomeCompletePhase(const int participants, stdVector< std::tuple< MPI_Request *, MPI_Status *, std::function< MPI_Request(int) > > > const &phases)
static int iSend(T const *const buf, int count, int dest, int tag, MPI_Comm comm, MPI_Request *request)
Strongly typed wrapper around MPI_Isend()
static int bcast(T *buffer, int count, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Bcast.
static void allGather(T const myValue, array1d< T > &allValues, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for MPI_Allgather.
static T max(T const &value, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for a MPI_Allreduce using a MPI_MAX operation.
static int allgather(T_SEND const *sendbuf, int sendcount, T_RECV *recvbuf, int recvcount, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Allgather.
static int activeWaitSome(const int count, MPI_Request array_of_requests[], MPI_Status array_of_statuses[], std::function< MPI_Request(int) > func)
static int send(T const *const buf, int count, int dest, int tag, MPI_Comm comm)
Strongly typed wrapper around MPI_Send()
static U prefixSum(T const value, MPI_Comm comm=MPI_COMM_GEOS)
Compute exclusive prefix sum and full sum.
static int scatter(TS const *const sendbuf, int sendcount, TR *const recvbuf, int recvcount, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Scatter.
static int gather(T const &value, DST_CONTAINER &destValuesBuffer, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Gather().
static T allReduce(T const &value, Reduction const op, MPI_Comm comm=MPI_COMM_GEOS)
Convenience wrapper for the MPI_Allreduce function.
static int checkAny(int count, MPI_Request array_of_requests[], int *idx, int *flag, MPI_Status array_of_statuses[])
static int gather(TS const *const sendbuf, int sendcount, TR *const recvbuf, int recvcount, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Gather().
static int scatterv(TS const *const sendbuf, const int *sendcounts, const int *displs, TR *const recvbuf, int recvcount, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Scatterv.
static int iRecv(T *const buf, int count, int source, int tag, MPI_Comm comm, MPI_Request *request)
Strongly typed wrapper around MPI_Irecv()
static T sum(T const &value, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for a MPI_Allreduce using a MPI_SUM operation.
static int activeWaitOrderedCompletePhase(const int participants, stdVector< std::tuple< MPI_Request *, MPI_Status *, std::function< MPI_Request(int) > > > const &phases)
static T min(T const &value, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for a MPI_Allreduce using a MPI_MIN operation.
static int nodeCommSize()
Compute the number of ranks allocated on the same node.
static int gatherv(TS const *const sendbuf, int sendcount, TR *const recvbuf, const int *recvcounts, const int *displs, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Gatherv.
static void finalize()
Finalize the MPI environment and free MPI-managed resources. Please note that once called,...
static void broadcast(T &value, int srcRank=0, MPI_Comm comm=MPI_COMM_GEOS)
Convenience function for MPI_Broadcast.
static GatherResult< CONTAINER > gatherBufferRank0(CONTAINER const &localBuffer)
Gather buffers of varying sizes from all ranks to rank 0.
static int reduce(T const *sendbuf, T *recvbuf, int count, MPI_Op op, int root, MPI_Comm comm=MPI_COMM_GEOS)
Strongly typed wrapper around MPI_Reduce.
Trait to retrieve the value_type or ValueType of a type T.