BioCMAMC-ST
impl_async.hpp
1#ifndef __IMPL_ASYNC_MPI_HPP__
2#define __IMPL_ASYNC_MPI_HPP__
3
4#include <common/common.hpp>
5#include <common/execinfo.hpp>
6#include <cstddef>
7#include <math.h>
8#include <mpi.h>
9#include <mpi_w/message_t.hpp>
10#include <mpi_w/mpi_types.hpp>
11#include <span>
12
14{
15 namespace
16 {
17 template <POD_t DataType>
18 int
19 _send_unsafe(MPI_Request& request,
20 DataType* buf,
21 size_t buf_size,
22 size_t dest,
23 size_t tag) noexcept
24 {
25 return MPI_Isend(buf,
26 buf_size,
28 dest,
29 tag,
30 MPI_COMM_WORLD,
31 &request);
32 }
33
34 } // namespace
35
36 inline MPI_Status
37 wait(MPI_Request& request)
38 {
39 PROFILE_SECTION("WrapMPI::wait");
40 MPI_Status status;
41 MPI_Wait(&request, &status);
42 return status;
43 }
44
45 inline void
46 wait(MPI_Request& request, MPI_Status* status)
47 {
48 MPI_Wait(&request, status);
49 }
50
51 template <POD_t DataType>
52 int
53 send(MPI_Request& request, DataType data, size_t dest, size_t tag)
54 {
55 return _send_unsafe<DataType>(request, &data, 1, dest, tag);
56 }
57
58 template <POD_t DataType>
59 int
60 send_v(MPI_Request& request,
61 std::span<const DataType> data,
62 size_t dest,
63 size_t tag,
64 bool send_size) noexcept
65 {
66 int send_status = MPI_SUCCESS;
67
68 if (send_size)
69 {
70 send_status = send<size_t>(request, data.size(), dest, tag);
71 }
72
73 if (send_status == MPI_SUCCESS)
74 {
75 send_status = _send_unsafe(request, data.data(), data.size(), dest, tag);
76 }
77
78 return send_status;
79 }
80
81 template <POD_t DataType>
82 int
83 recv_span(MPI_Request& request,
84 std::span<DataType> buf,
85 size_t src,
86 size_t tag) noexcept
87 {
88 return MPI_Irecv(buf.data(),
89 buf.size(),
91 src,
92 tag,
93 MPI_COMM_WORLD,
94 &request);
95 }
96
97 template <POD_t DataType>
98 std::optional<DataType>
99 recv(size_t src, MPI_Request& request, size_t tag) noexcept
100 {
101 DataType buf;
102
103 int recv_status = MPI_Irecv(
104 &buf, sizeof(DataType), MPI_BYTE, src, tag, MPI_COMM_WORLD, &request);
105 if (recv_status != MPI_SUCCESS)
106 {
107 return std::nullopt;
108 }
109 return buf;
110 }
111
112 template <POD_t T>
113 int
114 _broadcast_unsafe(T* data, size_t _size, size_t root, MPI_Request& request)
115 {
116 if (data == nullptr)
117 {
118 throw std::invalid_argument("Data pointer is null");
119 }
120 if (_size == 0 || _size > std::numeric_limits<size_t>::max())
121 {
122 throw std::invalid_argument("Error size");
123 }
124
125 int comm_size = 0;
126 MPI_Comm_size(MPI_COMM_WORLD, &comm_size);
127 if (root >= static_cast<size_t>(comm_size))
128 {
129 throw std::invalid_argument("Root process rank is out of range");
130 }
131
132 return MPI_Ibcast(data,
133 _size,
134 get_type<T>(),
135 static_cast<int>(root),
136 MPI_COMM_WORLD,
137 &request);
138 }
139
140 template <POD_t T>
141 int
142 broadcast_span(std::span<T> data, size_t root, MPI_Request& request)
143 {
144 return _broadcast_unsafe(data.data(), data.size(), root, request);
145 }
146
147} // namespace WrapMPI::Async
148
149#endif
Definition impl_async.hpp:14
int send_v(MPI_Request &request, std::span< const DataType > data, size_t dest, size_t tag, bool send_size) noexcept
Definition impl_async.hpp:60
int recv_span(MPI_Request &request, std::span< DataType > buf, size_t src, size_t tag) noexcept
Definition impl_async.hpp:83
int broadcast_span(std::span< T > data, size_t root, MPI_Request &request)
Definition impl_async.hpp:142
std::optional< DataType > recv(size_t src, MPI_Request &request, size_t tag) noexcept
Definition impl_async.hpp:99
int _broadcast_unsafe(T *data, size_t _size, size_t root, MPI_Request &request)
Definition impl_async.hpp:114
MPI_Status wait(MPI_Request &request)
Definition impl_async.hpp:37
int send(MPI_Request &request, DataType data, size_t dest, size_t tag)
Definition impl_async.hpp:53
constexpr MPI_Datatype get_type() noexcept
Definition mpi_types.hpp:13