Loading...
Searching...
No Matches
mpi.hpp
Go to the documentation of this file.
1
2#pragma once
3#include <iostream>
4#include <mpi.h>
5
6namespace terra::mpi {
7
8using MPIRank = int;
9
10inline MPIRank rank()
11{
13 MPI_Comm_rank( MPI_COMM_WORLD, &rank );
14 return rank;
15}
16
17inline int num_processes()
18{
19 int num_processes;
20 MPI_Comm_size( MPI_COMM_WORLD, &num_processes );
21 return num_processes;
22}
23
24inline void barrier()
25{
26 MPI_Barrier(MPI_COMM_WORLD);
27}
28
29namespace detail {
31{
32 public:
33 MPIContext( const MPIContext& ) = delete;
34 MPIContext& operator=( const MPIContext& ) = delete;
35 MPIContext( MPIContext&& ) = delete;
37
38 /// Initialize MPI once. Safe to call only once.
39 static void initialize( int* argc, char*** argv ) { instance( argc, argv ); }
40
41 /// Query whether MPI is initialized
42 static bool is_initialized()
43 {
44 int flag = 0;
45 MPI_Initialized( &flag );
46 return flag != 0;
47 }
48
49 /// Query whether MPI is finalized
50 static bool is_finalized()
51 {
52 int flag = 0;
53 MPI_Finalized( &flag );
54 return flag != 0;
55 }
56
57 private:
58 bool mpi_initialized_ = false;
59
60 // private constructor
61 MPIContext( int* argc, char*** argv )
62 {
63 if ( is_initialized() )
64 {
65 throw std::runtime_error( "MPI already initialized!" );
66 }
67
68 int err = MPI_Init( argc, argv );
69 if ( err != MPI_SUCCESS )
70 {
71 char errstr[MPI_MAX_ERROR_STRING];
72 int len = 0;
73 MPI_Error_string( err, errstr, &len );
74 throw std::runtime_error( std::string( "MPI_Init failed: " ) + std::string( errstr, len ) );
75 }
76
77 mpi_initialized_ = true;
78
79 MPI_Comm_set_errhandler( MPI_COMM_WORLD, MPI_ERRORS_RETURN );
80 }
81
82 // private destructor
83 ~MPIContext()
84 {
85 if ( mpi_initialized_ && !is_finalized() )
86 {
87 int err = MPI_Finalize();
88 if ( err != MPI_SUCCESS )
89 {
90 char errstr[MPI_MAX_ERROR_STRING];
91 int len = 0;
92 MPI_Error_string( err, errstr, &len );
93 std::cerr << "[MPI] MPI_Finalize failed: " << std::string( errstr, len ) << std::endl;
94 }
95 }
96 }
97
98 // singleton instance accessor
99 static MPIContext& instance( int* argc = nullptr, char*** argv = nullptr )
100 {
101 static MPIContext guard( argc, argv );
102 return guard;
103 }
104};
105
106} // namespace detail
107
108inline std::string mpi_error_string( int err )
109{
110 char errstr[MPI_MAX_ERROR_STRING];
111 int len = 0;
112 MPI_Error_string( err, errstr, &len );
113 return { errstr, static_cast< size_t >( len ) };
114}
115
116template < typename T >
117MPI_Datatype mpi_datatype()
118{
119 static_assert( sizeof( T ) == 0, "No MPI datatype mapping for this type." );
120 return MPI_DATATYPE_NULL;
121}
122
123template <>
124inline MPI_Datatype mpi_datatype< char >()
125{
126 return MPI_CHAR;
127}
128
129template <>
130inline MPI_Datatype mpi_datatype< signed char >()
131{
132 return MPI_SIGNED_CHAR;
133}
134
135template <>
136inline MPI_Datatype mpi_datatype< unsigned char >()
137{
138 return MPI_UNSIGNED_CHAR;
139}
140
141template <>
142inline MPI_Datatype mpi_datatype< int >()
143{
144 return MPI_INT;
145}
146
147template <>
148inline MPI_Datatype mpi_datatype< unsigned int >()
149{
150 return MPI_UNSIGNED;
151}
152
153template <>
154inline MPI_Datatype mpi_datatype< short >()
155{
156 return MPI_SHORT;
157}
158
159template <>
161{
162 return MPI_UNSIGNED_SHORT;
163}
164
165template <>
166inline MPI_Datatype mpi_datatype< long >()
167{
168 return MPI_LONG;
169}
170
171template <>
172inline MPI_Datatype mpi_datatype< unsigned long >()
173{
174 return MPI_UNSIGNED_LONG;
175}
176
177template <>
178inline MPI_Datatype mpi_datatype< long long >()
179{
180 return MPI_LONG_LONG;
181}
182
183template <>
185{
186 return MPI_UNSIGNED_LONG_LONG;
187}
188
189template <>
190inline MPI_Datatype mpi_datatype< float >()
191{
192 return MPI_FLOAT;
193}
194
195template <>
196inline MPI_Datatype mpi_datatype< double >()
197{
198 return MPI_DOUBLE;
199}
200
201template <>
202inline MPI_Datatype mpi_datatype< long double >()
203{
204 return MPI_LONG_DOUBLE;
205}
206
207template <>
208inline MPI_Datatype mpi_datatype< bool >()
209{
210 return MPI_CXX_BOOL;
211}
212
213} // namespace terra::mpi
Definition mpi.hpp:31
MPIContext(const MPIContext &)=delete
static bool is_finalized()
Query whether MPI is finalized.
Definition mpi.hpp:50
MPIContext(MPIContext &&)=delete
static void initialize(int *argc, char ***argv)
Initialize MPI once. Safe to call only once.
Definition mpi.hpp:39
static bool is_initialized()
Query whether MPI is initialized.
Definition mpi.hpp:42
MPIContext & operator=(MPIContext &&)=delete
MPIContext & operator=(const MPIContext &)=delete
Definition mpi.hpp:6
MPI_Datatype mpi_datatype< unsigned long long >()
Definition mpi.hpp:184
MPI_Datatype mpi_datatype< float >()
Definition mpi.hpp:190
std::string mpi_error_string(int err)
Definition mpi.hpp:108
MPI_Datatype mpi_datatype< char >()
Definition mpi.hpp:124
MPI_Datatype mpi_datatype< unsigned long >()
Definition mpi.hpp:172
MPI_Datatype mpi_datatype< short >()
Definition mpi.hpp:154
MPI_Datatype mpi_datatype< unsigned char >()
Definition mpi.hpp:136
void barrier()
Definition mpi.hpp:24
int num_processes()
Definition mpi.hpp:17
MPI_Datatype mpi_datatype< unsigned int >()
Definition mpi.hpp:148
int MPIRank
Definition mpi.hpp:8
MPI_Datatype mpi_datatype< bool >()
Definition mpi.hpp:208
MPI_Datatype mpi_datatype< double >()
Definition mpi.hpp:196
MPI_Datatype mpi_datatype< long long >()
Definition mpi.hpp:178
MPI_Datatype mpi_datatype< int >()
Definition mpi.hpp:142
MPI_Datatype mpi_datatype< unsigned short >()
Definition mpi.hpp:160
MPI_Datatype mpi_datatype< long double >()
Definition mpi.hpp:202
MPIRank rank()
Definition mpi.hpp:10
MPI_Datatype mpi_datatype()
Definition mpi.hpp:117
MPI_Datatype mpi_datatype< signed char >()
Definition mpi.hpp:130
MPI_Datatype mpi_datatype< long >()
Definition mpi.hpp:166