mpi_collate.h
Go to the documentation of this file.
1 /*
2 This file is part of the Ristra portage project.
3 Please see the license file at the root of this repository, or at:
4  https://github.com/laristra/portage/blob/master/LICENSE
5 */
6 
7 
8 #ifndef MPI_COLLATE_H_
9 #define MPI_COLLATE_H_
10 
11 #ifdef PORTAGE_ENABLE_MPI
12 
13 #include <algorithm>
14 #include <numeric>
15 #include <vector>
16 
17 #include <mpi.h>
18 
19 namespace Portage {
20 
21  // Collates local vectors lvec (of various lengths) into a global vector gvec
22  // on rank 0. The `gvec` vector is only defined on rank 0, and it is resized
23  // there to the proper size. On other ranks it is resized to size 1 and left
24  // undefined.
25  template <typename T>
26  void collate_type(MPI_Comm comm, const int rank, const int numpe,
27  const MPI_Datatype mpi_type,
28  std::vector<T> &lvec, std::vector<T> &gvec) {
29 
30  std::vector<int> lvec_sizes(numpe);
31  std::vector<int> displs;
32  int lvec_size = lvec.size();
33 
34  MPI_Gather(&lvec_size, 1, MPI_INT, &lvec_sizes[0], 1, MPI_INT, 0, comm);
35 
36  if (rank == 0) {
37  int const gvec_size = std::accumulate(lvec_sizes.begin(), lvec_sizes.end(),0);
38  int const lvec_size_count = lvec_sizes.size();
39 
40  gvec.resize(gvec_size);
41  displs.resize(lvec_size_count);
42 
43  int idx = 0;
44  for (int i=0; i < lvec_size_count; i++) {
45  displs[i] = idx;
46  idx += lvec_sizes[i];
47  }
48  } else {
49  // We resize to size 1, so that the expressions &gvec[0], &displs[0] below
50  // are well defined on all ranks.
51  gvec.resize(1);
52  displs.resize(1);
53  }
54  MPI_Gatherv(&lvec[0], lvec.size(), mpi_type, &gvec[0], &lvec_sizes[0],
55  &displs[0], mpi_type, 0, comm);
56  }
57 
58  inline
59  void collate(MPI_Comm comm, const int rank, const int numpe,
60  std::vector<int> &lvec, std::vector<int> &gvec) {
61  collate_type(comm, rank, numpe, MPI_INT, lvec, gvec);
62  }
63 
64  inline
65  void collate(MPI_Comm comm, const int rank, const int numpe,
66  std::vector<double> &lvec, std::vector<double> &gvec) {
67  collate_type(comm, rank, numpe, MPI_DOUBLE, lvec, gvec);
68  }
69 
70  // Returns the indices that would sort an array.
71  template <typename T>
72  void argsort(const std::vector<T> &x, std::vector<int> &idx) {
73  idx.resize(x.size());
74  std::iota(idx.begin(), idx.end(), 0);
75  std::sort(idx.begin(), idx.end(), [&x](int a, int b){ return x[a] < x[b]; });
76  }
77 
78  // Reorders a vector x using x = x[idx], where idx is a vector of indices
79  template <typename T>
80  void reorder(std::vector<T> &x, const std::vector<int> &idx) {
81  int const n = x.size();
82  std::vector<T> y(n);
83  for (int i=0; i < n; i++) y[i] = x[idx[i]];
84  x = y;
85  }
86 
87 } // namespace Portage
88 
89 #endif
90 
91 #endif // MPI_COLLATE_H_
Definition: coredriver.h:42