mpi.hpp
1 
5 #pragma once
6 
7 #include <cstdlib>
8 #include <memory>
9 #include <vector>
10 
11 #include <mpi.h>
12 
13 #include <rmm/device_buffer.hpp>
14 
15 #include <rapidsmpf/communicator/communicator.hpp>
16 #include <rapidsmpf/error.hpp>
17 #include <rapidsmpf/progress_thread.hpp>
18 
19 namespace rapidsmpf {
20 
25 namespace mpi {
26 
33 void init(int* argc, char*** argv);
34 
41 
50 #define RAPIDSMPF_MPI(call) \
51  rapidsmpf::mpi::detail::check_mpi_error((call), __FILE__, __LINE__)
52 
53 namespace detail {
61 void check_mpi_error(int error_code, char const* file, int line);
62 } // namespace detail
63 } // namespace mpi
64 
73 class MPI final : public Communicator {
74  public:
81  class Future : public Communicator::Future {
82  friend class MPI;
83 
84  public:
91  Future(MPI_Request req, std::unique_ptr<Buffer> data_buffer)
92  : req_{req}, data_buffer_{std::move(data_buffer)} {}
93 
104  MPI_Request req, std::unique_ptr<std::vector<std::uint8_t>> synced_host_data
105  )
106  : req_{std::move(req)}, synced_host_data_{std::move(synced_host_data)} {}
107 
108  ~Future() noexcept override = default;
109 
110  private:
111  MPI_Request req_;
112  // TODO: these buffers are mutually exclusive and looks similar to
113  // Buffer::storage_.
114  std::unique_ptr<Buffer> data_buffer_;
115  // Dedicated storage for host data that is valid at the time of construction.
116  std::unique_ptr<std::vector<std::uint8_t>> synced_host_data_;
117  };
118 
128  MPI(MPI_Comm comm,
129  std::shared_ptr<ProgressThread> progress_thread,
130  std::shared_ptr<Logger> logger);
131 
132  ~MPI() noexcept override = default;
133 
137  [[nodiscard]] Rank rank() const override {
138  return rank_;
139  }
140 
144  [[nodiscard]] Rank nranks() const override {
145  return nranks_;
146  }
147 
153  [[nodiscard]] std::unique_ptr<Communicator::Future> send(
154  std::unique_ptr<std::vector<std::uint8_t>> msg, Rank rank, Tag tag
155  ) override;
156 
157  // clang-format off
163  // clang-format on
164  [[nodiscard]] std::unique_ptr<Communicator::Future> send(
165  std::unique_ptr<Buffer> msg, Rank rank, Tag tag
166  ) override;
167 
173  [[nodiscard]] std::unique_ptr<Communicator::Future> recv(
174  Rank rank, Tag tag, std::unique_ptr<Buffer> recv_buffer
175  ) override;
176 
177  // clang-format off
183  // clang-format on
184  [[nodiscard]] std::unique_ptr<Communicator::Future> recv_sync_host_data(
185  Rank rank, Tag tag, std::unique_ptr<std::vector<std::uint8_t>> synced_buffer
186  ) override;
187 
191  [[nodiscard]] std::pair<std::unique_ptr<std::vector<std::uint8_t>>, Rank> recv_any(
192  Tag tag
193  ) override;
194 
198  [[nodiscard]] std::unique_ptr<std::vector<std::uint8_t>> recv_from(
199  Rank src, Tag tag
200  ) override;
204  std::pair<
205  std::vector<std::unique_ptr<Communicator::Future>>,
206  std::vector<std::size_t>>
207  test_some(std::vector<std::unique_ptr<Communicator::Future>>& future_vector) override;
208 
209  // clang-format off
213  // clang-format on
214  std::vector<std::size_t> test_some(
215  std::unordered_map<std::size_t, std::unique_ptr<Communicator::Future>> const&
216  future_map
217  ) override;
218 
220  bool test(std::unique_ptr<Communicator::Future>& future) override;
222  std::vector<std::unique_ptr<Buffer>> wait_all(
223  std::vector<std::unique_ptr<Communicator::Future>>&& futures
224  ) override;
225 
229  [[nodiscard]] std::unique_ptr<Buffer> wait(
230  std::unique_ptr<Communicator::Future> future
231  ) override;
232 
236  [[nodiscard]] std::unique_ptr<Buffer> release_data(
237  std::unique_ptr<Communicator::Future> future
238  ) override;
239 
243  [[nodiscard]] std::unique_ptr<std::vector<std::uint8_t>> release_sync_host_data(
244  std::unique_ptr<Communicator::Future> future
245  ) override;
246 
250  [[nodiscard]] std::shared_ptr<Logger> const& logger() override {
251  return logger_;
252  }
253 
257  [[nodiscard]] std::shared_ptr<ProgressThread> const&
258  progress_thread() const override {
259  return progress_thread_;
260  }
261 
265  [[nodiscard]] std::string str() const override;
266 
267  private:
268  MPI_Comm comm_;
269  Rank rank_;
270  Rank nranks_;
271  std::shared_ptr<Logger> logger_;
272  std::shared_ptr<ProgressThread> progress_thread_;
273 };
274 
275 
276 } // namespace rapidsmpf
Buffer representing device or host memory.
Definition: buffer.hpp:47
Abstract base class for asynchronous operation within the communicator.
Abstract base class for a communication mechanism between nodes.
A logger base class for handling different levels of log messages.
Definition: logger.hpp:37
Represents the future result of an MPI operation.
Definition: mpi.hpp:81
Future(MPI_Request req, std::unique_ptr< std::vector< std::uint8_t >> synced_host_data)
Construct a Future from synchronized host data.
Definition: mpi.hpp:103
Future(MPI_Request req, std::unique_ptr< Buffer > data_buffer)
Construct a Future from a data buffer.
Definition: mpi.hpp:91
MPI communicator class that implements the Communicator interface.
Definition: mpi.hpp:73
std::unique_ptr< Communicator::Future > send(std::unique_ptr< std::vector< std::uint8_t >> msg, Rank rank, Tag tag) override
Sends a host message to a specific rank.
std::vector< std::size_t > test_some(std::unordered_map< std::size_t, std::unique_ptr< Communicator::Future >> const &future_map) override
Tests for completion of multiple futures in a map.
std::unique_ptr< std::vector< std::uint8_t > > recv_from(Rank src, Tag tag) override
Receives a message from a specific rank (blocking).
std::vector< std::unique_ptr< Buffer > > wait_all(std::vector< std::unique_ptr< Communicator::Future >> &&futures) override
Wait for completion of all futures and return their data buffers.
std::unique_ptr< Buffer > wait(std::unique_ptr< Communicator::Future > future) override
Wait for a future to complete and return the data buffer.
std::pair< std::vector< std::unique_ptr< Communicator::Future > >, std::vector< std::size_t > > test_some(std::vector< std::unique_ptr< Communicator::Future >> &future_vector) override
Tests for completion of multiple futures.
std::shared_ptr< ProgressThread > const & progress_thread() const override
Retrieves the progress thread associated with this communicator.
Definition: mpi.hpp:258
std::unique_ptr< Communicator::Future > send(std::unique_ptr< Buffer > msg, Rank rank, Tag tag) override
Sends a message (device or host) to a specific rank. Use release_data to obtain the data buffer again...
bool test(std::unique_ptr< Communicator::Future > &future) override
Test for completion of a single future.
std::unique_ptr< Communicator::Future > recv_sync_host_data(Rank rank, Tag tag, std::unique_ptr< std::vector< std::uint8_t >> synced_buffer) override
Receives a message from a specific rank to an allocated (synchronized) host buffer....
Rank nranks() const override
Retrieves the total number of ranks.
Definition: mpi.hpp:144
std::unique_ptr< std::vector< std::uint8_t > > release_sync_host_data(std::unique_ptr< Communicator::Future > future) override
Retrieves synchronized host data associated with a completed future. When the future is completed,...
Rank rank() const override
Retrieves the rank of the current node.
Definition: mpi.hpp:137
std::pair< std::unique_ptr< std::vector< std::uint8_t > >, Rank > recv_any(Tag tag) override
Receives a message from any rank (blocking).
std::string str() const override
Provides a string representation of the communicator.
std::unique_ptr< Communicator::Future > recv(Rank rank, Tag tag, std::unique_ptr< Buffer > recv_buffer) override
Receives a message from a specific rank to a buffer. Use release_data to extract the data out of the ...
std::unique_ptr< Buffer > release_data(std::unique_ptr< Communicator::Future > future) override
Retrieves data associated with a completed future.
std::shared_ptr< Logger > const & logger() override
Retrieves the logger associated with this communicator.
Definition: mpi.hpp:250
A progress thread that can execute arbitrary functions.
A tag used for identifying messages in a communication operation.
void init(int *argc, char ***argv)
Helper to initialize MPI with threading support.
bool is_initialized()
Check if MPI is initialized.
RAPIDS Multi-Processor interfaces.
Definition: backend.hpp:14
std::int32_t Rank
The rank of a node (e.g. the rank of a MPI process), or world size (total number of ranks).