source: XIOS/dev/dev_trunk_omp/extern/src_ep_dev/ep_reduce.cpp @ 2129

Last change on this file since 2129 was 1745, checked in by yushan, 5 years ago

Generic_testcase: build flag --omp to enable EP with intelmpi. --omp2 to enable EP with openmpi. tested on Irene with compiler=intel17, mpi=intelmpi&openmpi, with and without EP

File size: 10.5 KB
Line 
1#ifdef _usingEP
2/*!
3   \file ep_reduce.cpp
4   \since 2 may 2016
5
6   \brief Definitions of MPI collective function: MPI_Reduce, MPI_Allreduce
7 */
8
9#include "ep_lib.hpp"
10#include <mpi.h>
11#include "ep_declaration.hpp"
12#include "ep_mpi.hpp"
13
14using namespace std;
15
16
17namespace ep_lib {
18
19  template<typename T>
20  T max_op(T a, T b)
21  {
22    return max(a,b);
23  }
24
25  template<typename T>
26  T min_op(T a, T b)
27  {
28    return min(a,b);
29  }
30
31  template<typename T>
32  T lor_op(T a, T b)
33  {
34    return a||b;
35  }
36
37  template<typename T>
38  void reduce_max(const T * buffer, T* recvbuf, int count)
39  {
40    transform(buffer, buffer+count, recvbuf, recvbuf, max_op<T>);
41  }
42
43  template<typename T>
44  void reduce_min(const T * buffer, T* recvbuf, int count)
45  {
46    transform(buffer, buffer+count, recvbuf, recvbuf, min_op<T>);
47  }
48
49  template<typename T>
50  void reduce_sum(const T * buffer, T* recvbuf, int count)
51  {
52    transform(buffer, buffer+count, recvbuf, recvbuf, std::plus<T>());
53  }
54
55  template<typename T>
56  void reduce_lor(const T * buffer, T* recvbuf, int count)
57  {
58    transform(buffer, buffer+count, recvbuf, recvbuf, lor_op<T>);
59  }
60
61  int MPI_Reduce_local(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int local_root, MPI_Comm comm)
62  {
63    assert(valid_type(datatype));
64    assert(valid_op(op));
65
66    ::MPI_Aint datasize, lb;
67    ::MPI_Type_get_extent(to_mpi_type(datatype), &lb, &datasize);
68
69    int ep_rank = comm->ep_comm_ptr->size_rank_info[0].first;
70    int ep_rank_loc = comm->ep_comm_ptr->size_rank_info[1].first;
71    int num_ep = comm->ep_comm_ptr->size_rank_info[1].second;
72
73    #pragma omp critical (_reduce)
74    comm->my_buffer->void_buffer[ep_rank_loc] = const_cast< void* >(sendbuf);
75
76    MPI_Barrier_local(comm);
77
78    if(ep_rank_loc == local_root)
79    {
80
81      memcpy(recvbuf, comm->my_buffer->void_buffer[0], datasize * count);
82
83      if(op == MPI_MAX)
84      {
85        if(datatype == MPI_INT)
86        {
87          assert(datasize == sizeof(int));
88          for(int i=1; i<num_ep; i++)
89            reduce_max<int>(static_cast<int*>(comm->my_buffer->void_buffer[i]), static_cast<int*>(recvbuf), count);
90        }
91
92        else if(datatype == MPI_FLOAT)
93        {
94          assert(datasize == sizeof(float));
95          for(int i=1; i<num_ep; i++)
96            reduce_max<float>(static_cast<float*>(comm->my_buffer->void_buffer[i]), static_cast<float*>(recvbuf), count);
97        }
98
99        else if(datatype == MPI_DOUBLE)
100        {
101          assert(datasize == sizeof(double));
102          for(int i=1; i<num_ep; i++)
103            reduce_max<double>(static_cast<double*>(comm->my_buffer->void_buffer[i]), static_cast<double*>(recvbuf), count);
104        }
105
106        else if(datatype == MPI_CHAR)
107        {
108          assert(datasize == sizeof(char));
109          for(int i=1; i<num_ep; i++)
110            reduce_max<char>(static_cast<char*>(comm->my_buffer->void_buffer[i]), static_cast<char*>(recvbuf), count);
111        }
112
113        else if(datatype == MPI_LONG)
114        {
115          assert(datasize == sizeof(long));
116          for(int i=1; i<num_ep; i++)
117            reduce_max<long>(static_cast<long*>(comm->my_buffer->void_buffer[i]), static_cast<long*>(recvbuf), count);
118        }
119
120        else if(datatype == MPI_UNSIGNED_LONG)
121        {
122          assert(datasize == sizeof(unsigned long));
123          for(int i=1; i<num_ep; i++)
124            reduce_max<unsigned long>(static_cast<unsigned long*>(comm->my_buffer->void_buffer[i]), static_cast<unsigned long*>(recvbuf), count);
125        }
126
127        else if(datatype == MPI_LONG_LONG_INT)
128        {
129          assert(datasize == sizeof(long long));
130          for(int i=1; i<num_ep; i++)
131            reduce_max<long long>(static_cast<long long*>(comm->my_buffer->void_buffer[i]), static_cast<long long*>(recvbuf), count);
132        }
133
134        else 
135        {
136          printf("datatype Error in ep_reduce : INT, FLOAT, DOUBLE, CHAR, LONG, UNSIGNED_LONG, LONG_LONG_INT\n");
137          MPI_Abort(comm, 0);
138        }
139
140      }
141
142      else if(op == MPI_MIN)
143      {
144        if(datatype ==MPI_INT)
145        {
146          assert(datasize == sizeof(int));
147          for(int i=1; i<num_ep; i++)
148            reduce_min<int>(static_cast<int*>(comm->my_buffer->void_buffer[i]), static_cast<int*>(recvbuf), count);
149        }
150
151        else if(datatype == MPI_FLOAT)
152        {
153          assert(datasize == sizeof(float));
154          for(int i=1; i<num_ep; i++)
155            reduce_min<float>(static_cast<float*>(comm->my_buffer->void_buffer[i]), static_cast<float*>(recvbuf), count);
156        }
157
158        else if(datatype == MPI_DOUBLE)
159        {
160          assert(datasize == sizeof(double));
161          for(int i=1; i<num_ep; i++)
162            reduce_min<double>(static_cast<double*>(comm->my_buffer->void_buffer[i]), static_cast<double*>(recvbuf), count);
163        }
164
165        else if(datatype == MPI_CHAR)
166        {
167          assert(datasize == sizeof(char));
168          for(int i=1; i<num_ep; i++)
169            reduce_min<char>(static_cast<char*>(comm->my_buffer->void_buffer[i]), static_cast<char*>(recvbuf), count);
170        }
171
172        else if(datatype == MPI_LONG)
173        {
174          assert(datasize == sizeof(long));
175          for(int i=1; i<num_ep; i++)
176            reduce_min<long>(static_cast<long*>(comm->my_buffer->void_buffer[i]), static_cast<long*>(recvbuf), count);
177        }
178
179        else if(datatype == MPI_UNSIGNED_LONG)
180        {
181          assert(datasize == sizeof(unsigned long));
182          for(int i=1; i<num_ep; i++)
183            reduce_min<unsigned long>(static_cast<unsigned long*>(comm->my_buffer->void_buffer[i]), static_cast<unsigned long*>(recvbuf), count);
184        }
185
186        else if(datatype == MPI_LONG_LONG_INT)
187        {
188          assert(datasize == sizeof(long long));
189          for(int i=1; i<num_ep; i++)
190            reduce_min<long long>(static_cast<long long*>(comm->my_buffer->void_buffer[i]), static_cast<long long*>(recvbuf), count);
191        }
192
193        else 
194        {
195          printf("datatype Error in ep_reduce : INT, FLOAT, DOUBLE, CHAR, LONG, UNSIGNED_LONG, LONG_LONG_INT\n");
196          MPI_Abort(comm, 0);
197        }
198
199      }
200
201
202      else if(op == MPI_SUM)
203      {
204        if(datatype==MPI_INT)
205        {
206          assert(datasize == sizeof(int));
207          for(int i=1; i<num_ep; i++)
208            reduce_sum<int>(static_cast<int*>(comm->my_buffer->void_buffer[i]), static_cast<int*>(recvbuf), count);
209        }
210
211        else if(datatype == MPI_FLOAT)
212        {
213          assert(datasize == sizeof(float));
214          for(int i=1; i<num_ep; i++)
215            reduce_sum<float>(static_cast<float*>(comm->my_buffer->void_buffer[i]), static_cast<float*>(recvbuf), count);
216        }
217
218        else if(datatype == MPI_DOUBLE)
219        {
220          assert(datasize == sizeof(double));
221          for(int i=1; i<num_ep; i++)
222            reduce_sum<double>(static_cast<double*>(comm->my_buffer->void_buffer[i]), static_cast<double*>(recvbuf), count);
223        }
224
225        else if(datatype == MPI_CHAR)
226        {
227          assert(datasize == sizeof(char));
228          for(int i=1; i<num_ep; i++)
229            reduce_sum<char>(static_cast<char*>(comm->my_buffer->void_buffer[i]), static_cast<char*>(recvbuf), count);
230        }
231
232        else if(datatype == MPI_LONG)
233        {
234          assert(datasize == sizeof(long));
235          for(int i=1; i<num_ep; i++)
236            reduce_sum<long>(static_cast<long*>(comm->my_buffer->void_buffer[i]), static_cast<long*>(recvbuf), count);
237        }
238
239        else if(datatype ==MPI_UNSIGNED_LONG)
240        {
241          assert(datasize == sizeof(unsigned long));
242          for(int i=1; i<num_ep; i++)
243            reduce_sum<unsigned long>(static_cast<unsigned long*>(comm->my_buffer->void_buffer[i]), static_cast<unsigned long*>(recvbuf), count);
244        }
245       
246        else if(datatype ==MPI_LONG_LONG_INT)
247        {
248          assert(datasize == sizeof(long long));
249          for(int i=1; i<num_ep; i++)
250            reduce_sum<long long>(static_cast<long long*>(comm->my_buffer->void_buffer[i]), static_cast<long long*>(recvbuf), count);
251        }
252
253        else 
254        {
255          printf("datatype Error in ep_reduce : INT, FLOAT, DOUBLE, CHAR, LONG, UNSIGNED_LONG, LONG_LONG_INT\n");
256          MPI_Abort(comm, 0);
257        }
258
259      }
260
261      else if(op == MPI_LOR)
262      {
263        if(datatype != MPI_INT)
264          printf("datatype Error, must be MPI_INT\n");
265        else
266        {
267          assert(datasize == sizeof(int));
268          for(int i=1; i<num_ep; i++)
269            reduce_lor<int>(static_cast<int*>(comm->my_buffer->void_buffer[i]), static_cast<int*>(recvbuf), count);
270        }
271      }
272     
273      else
274      {
275        printf("op type Error in ep_reduce : MPI_MAX, MPI_MIN, MPI_SUM, MPI_LOR\n");
276        MPI_Abort(comm, 0);
277      }
278    }
279
280    MPI_Barrier_local(comm);
281
282  }
283
284
285  int MPI_Reduce(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
286  {
287
288    if(!comm->is_ep) return ::MPI_Reduce(sendbuf, recvbuf, count, to_mpi_type(datatype), to_mpi_op(op), root, to_mpi_comm(comm->mpi_comm));
289    if(comm->is_intercomm) return MPI_Reduce_intercomm(sendbuf, recvbuf, count, datatype, op, root, comm);
290
291
292
293    int ep_rank = comm->ep_comm_ptr->size_rank_info[0].first;
294    int ep_rank_loc = comm->ep_comm_ptr->size_rank_info[1].first;
295    int mpi_rank = comm->ep_comm_ptr->size_rank_info[2].first;
296    int ep_size = comm->ep_comm_ptr->size_rank_info[0].second;
297    int num_ep = comm->ep_comm_ptr->size_rank_info[1].second;
298    int mpi_size = comm->ep_comm_ptr->size_rank_info[2].second;
299
300    int root_mpi_rank = comm->ep_rank_map->at(root).second;
301    int root_ep_loc = comm->ep_rank_map->at(root).first;
302
303    ::MPI_Aint datasize, lb;
304
305    ::MPI_Type_get_extent(*(static_cast< ::MPI_Datatype*>(datatype)), &lb, &datasize);
306
307    bool is_master = (ep_rank_loc==0 && mpi_rank != root_mpi_rank ) || ep_rank == root;
308    bool is_root = ep_rank == root;
309
310    void* local_recvbuf;
311
312    if(is_master)
313    {
314      local_recvbuf = new void*[datasize * count];
315    }
316
317    if(mpi_rank == root_mpi_rank) MPI_Reduce_local(sendbuf, local_recvbuf, count, datatype, op, root_ep_loc, comm);
318    else                          MPI_Reduce_local(sendbuf, local_recvbuf, count, datatype, op, 0, comm);
319
320
321
322    if(is_master)
323    {
324      ::MPI_Reduce(local_recvbuf, recvbuf, count, to_mpi_type(datatype), to_mpi_op(op), root_mpi_rank, to_mpi_comm(comm->mpi_comm));
325     
326    }
327
328    if(is_master)
329    {
330      delete[] local_recvbuf;
331    }
332
333    MPI_Barrier_local(comm);
334  }
335
336
337  int MPI_Reduce_intercomm(const void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm)
338  {
339    printf("MPI_Reduce_intercomm not yet implemented\n");
340    MPI_Abort(comm, 0);
341  }
342}
343
344#endif
345
346
Note: See TracBrowser for help on using the repository browser.