COMBINATORIAL_BLAS  1.6
MPIOp.h
Go to the documentation of this file.
1 #ifndef _MPI_OP_H
2 #define _MPI_OP_H
3 
4 #include <iostream>
5 #include <typeinfo>
6 #include <map>
7 #include <functional>
8 #include <mpi.h>
9 #include <stdint.h>
10 #include "Operations.h"
11 #include "MPIType.h" // type_info_compare definition
12 
13 namespace combblas {
14 
16 {
17 private:
18  typedef std::map<std::type_info const*, MPI_Op, type_info_compare> stored_map_type;
19  stored_map_type map;
20 
21 public:
22  void clear()
23  {
24  int is_finalized=0;
25  MPI_Finalized(&is_finalized);
26  if (! is_finalized ) // do not free after call to MPI_FInalize
27  {
28  // ignore errors in the destructor
29  for (stored_map_type::iterator it=map.begin(); it != map.end(); ++it)
30  {
31  MPI_Op_free(&(it->second));
32  }
33  }
34  }
36  {
37  clear();
38  }
39  MPI_Op get(const std::type_info* t)
40  {
41  stored_map_type::iterator pos = map.find(t);
42  if (pos != map.end())
43  return pos->second;
44  else
45  return MPI_OP_NULL;
46  }
47 
48  void set(const std::type_info* t, MPI_Op datatype)
49  {
50 #ifdef NOTGNU
51  if (map.find(t) != map.end()) map.erase(t);
52  map.insert(std::make_pair(t, datatype));
53 #else
54  map[t] = datatype;
55 #endif
56  }
57 };
58 
59 extern MPIOpCache mpioc; // global variable
60 
61 
62 // MPIOp: A class that has a static op() function that takes no arguments and returns the corresponding MPI_Op
63 // if and only if the given Op has a mapping to a valid MPI_Op
64 // No concepts checking for the applicability of Op on the datatype T at the moment
65 // In the future, this can be implemented via metafunction forwarding using mpl::or_ and mpl::bool_
66 
67 template <typename Op, typename T, typename Enable = void>
68 struct MPIOp
69 {
70  static void funcmpi(void * invec, void * inoutvec, int * len, MPI_Datatype *datatype)
71  {
72  Op myop; // you need to create the object instance
73  T * pinvec = static_cast<T*>(invec);
74  T * pinoutvec = static_cast<T*>(inoutvec);
75  for (int i = 0; i < *len; i++)
76  {
77  pinoutvec[i] = myop(pinvec[i], pinoutvec[i]);
78  }
79  }
80  static MPI_Op op()
81  {
82  std::type_info const* t = &typeid(Op);
83  MPI_Op foundop = mpioc.get(t);
84 
85  if (foundop == MPI_OP_NULL)
86  {
87  MPI_Op_create(funcmpi, false, &foundop);
88 
89  int myrank;
90  MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
91  if(myrank == 0)
92  std::cout << "Creating a new MPI Op for " << t->name() << std::endl;
93 
94  mpioc.set(t, foundop);
95  }
96  return foundop;
97  }
98 };
99 
100 template<typename T> struct MPIOp< maximum<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_MAX; } };
101 template<typename T> struct MPIOp< minimum<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_MIN; } };
102 template<typename T> struct MPIOp< std::plus<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_SUM; } };
103 template<typename T> struct MPIOp< std::multiplies<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_PROD; } };
104 template<typename T> struct MPIOp< std::logical_and<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_LAND; } };
105 template<typename T> struct MPIOp< std::logical_or<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_LOR; } };
106 template<typename T> struct MPIOp< logical_xor<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_LXOR; } };
107 template<typename T> struct MPIOp< bitwise_and<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_BAND; } };
108 template<typename T> struct MPIOp< bitwise_or<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_BOR; } };
109 template<typename T> struct MPIOp< bitwise_xor<T>,T,typename std::enable_if<std::is_pod<T>::value, void>::type > { static MPI_Op op() { return MPI_BXOR; } };
110 
111 }
112 
113 #endif
Compute the minimum of two values.
Definition: Operations.h:172
Compute the bitwise AND of two integral values.
Definition: Operations.h:233
Compute the maximum of two values.
Definition: Operations.h:154
void set(const std::type_info *t, MPI_Op datatype)
Definition: MPIOp.h:48
MPI_Op get(const std::type_info *t)
Definition: MPIOp.h:39
Compute the bitwise OR of two integral values.
Definition: Operations.h:251
static MPI_Op op()
Definition: MPIOp.h:80
Compute the bitwise exclusive OR of two integral values.
Definition: Operations.h:286
Compute the logical exclusive OR of two integral values.
Definition: Operations.h:268
MPIOpCache mpioc
Definition: MPIOp.cpp:7
Definition: CCGrid.h:4
static void funcmpi(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype)
Definition: MPIOp.h:70