OOPS
oops/mpi/mpi.h
Go to the documentation of this file.
1 /*
2  * (C) Copyright 2013 ECMWF.
3  *
4  * This software is licensed under the terms of the Apache Licence Version 2.0
5  * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
6  * In applying this licence, ECMWF does not waive the privileges and immunities
7  * granted to it by virtue of its status as an intergovernmental organisation
8  * nor does it submit to any jurisdiction.
9  */
10 
11 #pragma once
12 
13 #include <Eigen/Dense>
14 
15 #include <vector>
16 
17 #include "eckit/exception/Exceptions.h"
18 #include "eckit/mpi/Comm.h"
19 
20 namespace oops {
21 namespace mpi {
22 
23 // ------------------------------------------------------------------------------------------------
24 
25 /// Default communicator with all MPI tasks (ie MPI_COMM_WORLD)
26 const eckit::mpi::Comm & world();
27 
28 /// Default communicator with each MPI task by itself
29 const eckit::mpi::Comm & myself();
30 
31 // ------------------------------------------------------------------------------------------------
32 
33 /// Extend eckit Comm for Serializable oops objects
34 
35 template <typename SERIALIZABLE>
36 void send(const eckit::mpi::Comm & comm, const SERIALIZABLE & sendobj,
37  const int dest, const int tag) {
38  std::vector<double> sendbuf;
39  sendobj.serialize(sendbuf);
40  comm.send(sendbuf.data(), sendbuf.size(), dest, tag);
41 }
42 
43 // ------------------------------------------------------------------------------------------------
44 
45 template <typename SERIALIZABLE>
46 void receive(const eckit::mpi::Comm & comm, SERIALIZABLE & recvobj,
47  const int source, const int tag) {
48  size_t sz = recvobj.serialSize();
49  std::vector<double> recvbuf(sz);
50  eckit::mpi::Status status = comm.receive(recvbuf.data(), sz, source, tag);
51  size_t ii = 0;
52  recvobj.deserialize(recvbuf, ii);
53  ASSERT(ii == sz);
54 }
55 
56 // ------------------------------------------------------------------------------------------------
57 
58 void gather(const eckit::mpi::Comm & comm, const std::vector<double> & send,
59  std::vector<double> & recv, const size_t root);
60 
61 // ------------------------------------------------------------------------------------------------
62 
63 template <typename SERIALIZABLE>
64 void gather(const eckit::mpi::Comm & comm, const std::vector<SERIALIZABLE> & send,
65  std::vector<SERIALIZABLE> & recv, const size_t root) {
66  if (comm.size() > 1) {
67  std::vector<double> sendbuf;
68  std::vector<double> recvbuf;
69 
70  for (const SERIALIZABLE & jsend : send) jsend.serialize(sendbuf);
71 
72  gather(comm, sendbuf, recvbuf, root);
73 
74  if (comm.rank() == root) {
75  size_t indx = 0;
76  for (SERIALIZABLE & jrecv : recv) jrecv.deserialize(recvbuf, indx);
77  }
78  } else {
79  recv = send;
80  }
81 }
82 
83 // ------------------------------------------------------------------------------------------------
84 // allGather for eigen vectors
85 // ------------------------------------------------------------------------------------------------
86 void allGather(const eckit::mpi::Comm & comm,
87  const Eigen::VectorXd &, std::vector<Eigen::VectorXd> &);
88 
89 /// \brief A wrapper around the MPI *all gather* operation for serializable types.
90 ///
91 /// The *all gather* operation gathers data from all tasks and delivers the combined data to all
92 /// tasks. This wrapper performs that operation for collections of non-primitive types that
93 /// nevertheless support the OOPS serialization interface, i.e. provide the functions
94 ///
95 /// void serialize(std::vector<double> &vect) const;
96 /// void deserialize(const std::vector<double> &vect, size_t &current);
97 ///
98 /// An example of such a type is util::DateTime.
99 ///
100 /// \param comm
101 /// Communicator.
102 /// \param first, last
103 /// Range of values to be delivered from this task to all other tasks.
104 /// \param recvbuf
105 /// Output iterator to the beginning of the range to receive the combined data from all tasks.
106 template <typename CIter, typename Iter>
107 void allGathervUsingSerialize(const eckit::mpi::Comm &comm, CIter first, CIter last,
108  Iter recvbuf) {
109  std::vector<double> serializedLocalData;
110  for (CIter it = first; it != last; ++it)
111  it->serialize(serializedLocalData);
112 
113  eckit::mpi::Buffer<double> buffer(comm.size());
114  comm.allGatherv(serializedLocalData.begin(), serializedLocalData.end(), buffer);
115 
116  size_t numDeserializedDoubles = 0;
117  for (Iter it = recvbuf; numDeserializedDoubles != buffer.buffer.size(); ++it)
118  it->deserialize(buffer.buffer, numDeserializedDoubles);
119 }
120 
121 // ------------------------------------------------------------------------------------------------
122 
123 } // namespace mpi
124 } // namespace oops
oops
The namespace for the main oops code.
Definition: ErrorCovarianceL95.cc:22
run_time_test.status
string status
Definition: run_time_test.py:42
oops::mpi::allGather
void allGather(const eckit::mpi::Comm &comm, const Eigen::VectorXd &sendbuf, std::vector< Eigen::VectorXd > &recvbuf)
Definition: oops/mpi/mpi.cc:58
oops::mpi::myself
const eckit::mpi::Comm & myself()
Default communicator with each MPI task by itself.
Definition: oops/mpi/mpi.cc:28
oops::mpi::allGathervUsingSerialize
void allGathervUsingSerialize(const eckit::mpi::Comm &comm, CIter first, CIter last, Iter recvbuf)
A wrapper around the MPI all gather operation for serializable types.
Definition: oops/mpi/mpi.h:107
oops::mpi::send
void send(const eckit::mpi::Comm &comm, const SERIALIZABLE &sendobj, const int dest, const int tag)
Extend eckit Comm for Serializable oops objects.
Definition: oops/mpi/mpi.h:36
L95Browser.dest
dest
Definition: L95Browser.py:65
oops::mpi::gather
void gather(const eckit::mpi::Comm &comm, const std::vector< double > &send, std::vector< double > &recv, const size_t root)
Definition: oops/mpi/mpi.cc:34
oops::mpi::world
const eckit::mpi::Comm & world()
Default communicator with all MPI tasks (ie MPI_COMM_WORLD)
Definition: oops/mpi/mpi.cc:22
oops::mpi::receive
void receive(const eckit::mpi::Comm &comm, SERIALIZABLE &recvobj, const int source, const int tag)
Definition: oops/mpi/mpi.h:46