19 #ifndef TIMPI_OP_FUNCTION_H 20 #define TIMPI_OP_FUNCTION_H 22 #include "timpi/timpi_config.h" 32 #endif // TIMPI_HAVE_MPI 35 #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 36 # include <boost/multiprecision/float128.hpp> 41 #include <type_traits> 47 #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 48 # ifdef TIMPI_HAVE_MPI 49 # define TIMPI_MPI_QUAD_BINARY(funcname) \ 51 timpi_mpi_quad_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 53 const int size = *len; \ 55 TIMPI_DEFAULT_SCALAR_TYPE *in = static_cast<TIMPI_DEFAULT_SCALAR_TYPE*>(a); \ 56 TIMPI_DEFAULT_SCALAR_TYPE *inout = static_cast<TIMPI_DEFAULT_SCALAR_TYPE*>(b); \ 57 for (int i=0; i != size; ++i) \ 58 inout[i] = std::funcname(in[i],inout[i]); \ 61 # define TIMPI_MPI_QUAD_LOCATOR(funcname) \ 63 timpi_mpi_quad_##funcname##_location(void * a, void * b, int * len, MPI_Datatype *) \ 65 const int size = *len; \ 67 typedef std::pair<TIMPI_DEFAULT_SCALAR_TYPE, int> dtype; \ 69 dtype *in = static_cast<dtype*>(a); \ 70 dtype *inout = static_cast<dtype*>(b); \ 71 for (int i=0; i != size; ++i) \ 73 TIMPI_DEFAULT_SCALAR_TYPE old_inout = inout[i].first; \ 74 inout[i].first = std::funcname(in[i].first,inout[i].first); \ 75 if (old_inout != inout[i].first) \ 76 inout[i].second = in[i].second; \ 81 # define TIMPI_MPI_QUAD_BINARY_FUNCTOR(funcname) \ 83 timpi_mpi_quad_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 85 const int size = *len; \ 87 TIMPI_DEFAULT_SCALAR_TYPE *in = static_cast<TIMPI_DEFAULT_SCALAR_TYPE*>(a); \ 88 TIMPI_DEFAULT_SCALAR_TYPE *inout = static_cast<TIMPI_DEFAULT_SCALAR_TYPE*>(b); \ 89 for (int i=0; i != size; ++i) \ 90 inout[i] = std::funcname<TIMPI_DEFAULT_SCALAR_TYPE>()(in[i],inout[i]); \ 94 TIMPI_MPI_QUAD_BINARY(max)
95 TIMPI_MPI_QUAD_BINARY(min)
96 TIMPI_MPI_QUAD_LOCATOR(max)
97 TIMPI_MPI_QUAD_LOCATOR(min)
98 TIMPI_MPI_QUAD_BINARY_FUNCTOR(plus)
99 TIMPI_MPI_QUAD_BINARY_FUNCTOR(multiplies)
101 # endif // TIMPI_HAVE_MPI 102 #endif // TIMPI_DEFAULT_QUADRUPLE_PRECISION 109 struct opfunction_dependent_false : std::false_type
119 template <
typename T>
123 static_assert(opfunction_dependent_false<T>::value,
124 "Only specializations of OpFunction may be used, did you forget to include a header file (e.g. parallel_algebra.h)?");
155 #ifdef TIMPI_HAVE_MPI 157 #define TIMPI_PARALLEL_INTEGER_OPS(cxxtype) \ 159 class OpFunction<cxxtype> \ 162 static MPI_Op max() { return MPI_MAX; } \ 163 static MPI_Op min() { return MPI_MIN; } \ 164 static MPI_Op sum() { return MPI_SUM; } \ 165 static MPI_Op product() { return MPI_PROD; } \ 166 static MPI_Op logical_and() { return MPI_LAND; } \ 167 static MPI_Op bitwise_and() { return MPI_BAND; } \ 168 static MPI_Op logical_or() { return MPI_LOR; } \ 169 static MPI_Op bitwise_or() { return MPI_BOR; } \ 170 static MPI_Op logical_xor() { return MPI_LXOR; } \ 171 static MPI_Op bitwise_xor() { return MPI_BXOR; } \ 172 static MPI_Op max_location() { return MPI_MAXLOC; } \ 173 static MPI_Op min_location() { return MPI_MINLOC; } \ 176 #define TIMPI_PARALLEL_FLOAT_OPS(cxxtype) \ 178 class OpFunction<cxxtype> \ 181 static MPI_Op max() { return MPI_MAX; } \ 182 static MPI_Op min() { return MPI_MIN; } \ 183 static MPI_Op sum() { return MPI_SUM; } \ 184 static MPI_Op product() { return MPI_PROD; } \ 185 static MPI_Op max_location() { return MPI_MAXLOC; } \ 186 static MPI_Op min_location() { return MPI_MINLOC; } \ 191 #define TIMPI_PARALLEL_INTEGER_OPS(cxxtype) \ 193 class OpFunction<cxxtype> \ 197 #define TIMPI_PARALLEL_FLOAT_OPS(cxxtype) \ 199 class OpFunction<cxxtype> \ 221 #ifdef TIMPI_HAVE_MPI 226 ManageOp(MPI_User_function * func,
int commute, MPI_Op * op)
229 timpi_call_mpi(MPI_Op_create(func, commute,
_op));
240 #define TIMPI_MPI_OPFUNCTION(mpiname, funcname) \ 241 static MPI_Op mpiname() { \ 242 static MPI_Op TIMPI_MPI_##mpiname = MPI_OP_NULL; \ 243 if (TIMPI_MPI_##mpiname == MPI_OP_NULL) \ 245 (std::make_unique<ManageOp>(timpi_mpi_##funcname, true, &TIMPI_MPI_##mpiname)); \ 246 return TIMPI_MPI_##mpiname; \ 249 #ifdef TIMPI_DEFAULT_QUADRUPLE_PRECISION 250 # ifdef TIMPI_HAVE_MPI 255 TIMPI_MPI_OPFUNCTION(max, quad_max)
256 TIMPI_MPI_OPFUNCTION(min, quad_min)
257 TIMPI_MPI_OPFUNCTION(sum, quad_plus)
258 TIMPI_MPI_OPFUNCTION(product, quad_multiplies)
260 TIMPI_MPI_OPFUNCTION(max_location, quad_max_location)
261 TIMPI_MPI_OPFUNCTION(min_location, quad_min_location)
267 #endif // TIMPI_DEFAULT_QUADRUPLE_PRECISION 269 #ifdef TIMPI_HAVE_MPI 271 # define TIMPI_MPI_PAIR_BINARY(funcname) \ 273 timpi_mpi_pair_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 275 const int size = *len; \ 277 const std::pair<T,U> * in = static_cast<std::pair<T,U> *>(a); \ 278 std::pair<T,U> * inout = static_cast<std::pair<T,U> *>(b); \ 279 for (int i=0; i != size; ++i) \ 281 inout[i].first = std::funcname(in[i].first,inout[i].first); \ 282 inout[i].second = std::funcname(in[i].second,inout[i].second); \ 286 # define TIMPI_MPI_PAIR_LOCATOR(funcname) \ 288 timpi_mpi_pair_##funcname##_location(void * a, void * b, int * len, MPI_Datatype *) \ 290 const int size = *len; \ 292 typedef std::pair<std::pair<T,U>, int> dtype; \ 294 dtype *in = static_cast<dtype*>(a); \ 295 dtype *inout = static_cast<dtype*>(b); \ 296 for (int i=0; i != size; ++i) \ 298 std::pair<T,U> old_inout = inout[i].first; \ 299 inout[i].first.first = std::funcname(in[i].first.first, inout[i].first.first); \ 300 inout[i].first.second = std::funcname(in[i].first.second,inout[i].first.second); \ 301 if (old_inout != inout[i].first) \ 302 inout[i].second = in[i].second; \ 307 # define TIMPI_MPI_PAIR_BINARY_FUNCTOR(funcname) \ 309 timpi_mpi_pair_##funcname(void * a, void * b, int * len, MPI_Datatype *) \ 311 const int size = *len; \ 313 const std::pair<T,U> * in = static_cast<std::pair<T,U> *>(a); \ 314 std::pair<T,U> * inout = static_cast<std::pair<T,U> *>(b); \ 315 for (int i=0; i != size; ++i) \ 317 inout[i].first = std::funcname<T>()(in[i].first, inout[i].first); \ 318 inout[i].second = std::funcname<T>()(in[i].second,inout[i].second); \ 323 template<
typename T,
typename U>
326 TIMPI_MPI_PAIR_BINARY(max)
327 TIMPI_MPI_PAIR_BINARY(min)
328 TIMPI_MPI_PAIR_LOCATOR(max)
329 TIMPI_MPI_PAIR_LOCATOR(min)
330 TIMPI_MPI_PAIR_BINARY_FUNCTOR(plus)
331 TIMPI_MPI_PAIR_BINARY_FUNCTOR(multiplies)
334 TIMPI_MPI_OPFUNCTION(max, pair_max)
335 TIMPI_MPI_OPFUNCTION(min, pair_min)
336 TIMPI_MPI_OPFUNCTION(sum, pair_plus)
337 TIMPI_MPI_OPFUNCTION(product, pair_multiplies)
339 TIMPI_MPI_OPFUNCTION(max_location, pair_max_location)
340 TIMPI_MPI_OPFUNCTION(min_location, pair_min_location)
342 # else // TIMPI_HAVE_MPI 343 template<
typename T,
typename U>
349 #endif // TIMPI_OP_FUNCTION_H
ManageOp(MPI_User_function *func, int commute, MPI_Op *op)
virtual ~ManageOp() override
TIMPI_PARALLEL_FLOAT_OPS(float)
The SemiPermanent "class" is basically just a place for a destructor vtable.
TIMPI_PARALLEL_INTEGER_OPS(char)
Templated class to provide the appropriate MPI reduction operations for use with built-in C types or ...