Line data Source code
1 : //
2 : // Class Window
3 : // Defines an interface to perform one-sided communication.
4 : // The term RMA stands for remote memory accesss.
5 : //
6 : #include "Utility/IpplException.h"
7 :
8 : namespace ippl {
9 : namespace mpi {
10 : namespace rma {
11 :
12 : template <TargetComm Target>
13 120 : Window<Target>::~Window() {
14 120 : if (win_m != MPI_WIN_NULL) {
15 120 : MPI_Win_free(&win_m);
16 120 : win_m = MPI_WIN_NULL;
17 : }
18 120 : }
19 :
20 : template <TargetComm Target>
21 : template <std::contiguous_iterator Iter>
22 120 : bool Window<Target>::create(const Communicator& comm, Iter first, Iter last) {
23 : static_assert(isActiveTarget<Target>::value,
24 : "No active target communication window");
25 :
26 120 : if (allocated_m) {
27 0 : return false;
28 : }
29 120 : allocated_m = true;
30 :
31 120 : count_m = std::distance(first, last);
32 120 : int dispUnit = sizeof(typename Iter::value_type);
33 120 : MPI_Aint size = (MPI_Aint)count_m * dispUnit;
34 120 : MPI_Win_create(&(*first), size, dispUnit, MPI_INFO_NULL, comm, &win_m);
35 :
36 120 : return allocated_m;
37 : }
38 :
39 : template <TargetComm Target>
40 : template <std::contiguous_iterator Iter>
41 : bool Window<Target>::attach(const Communicator& comm, Iter first, Iter last) {
42 : if (attached_m) {
43 : return false;
44 : }
45 : attached_m = true;
46 :
47 : if (!allocated_m) {
48 : MPI_Win_create_dynamic(MPI_INFO_NULL, comm, &win_m);
49 : allocated_m = true;
50 : }
51 :
52 : count_m = std::distance(first, last);
53 : MPI_Aint size = (MPI_Aint)count_m * sizeof(typename Iter::value_type);
54 : MPI_Win_attach(win_m, &(*first), size);
55 :
56 : return attached_m;
57 : }
58 :
59 : template <TargetComm Target>
60 : template <std::contiguous_iterator Iter>
61 : bool Window<Target>::detach(Iter first) {
62 : if (!attached_m) {
63 : return false;
64 : }
65 : attached_m = false;
66 : MPI_Win_detach(win_m, &(*first));
67 : return true;
68 : }
69 :
70 : template <TargetComm Target>
71 336 : void Window<Target>::fence(int asrt) {
72 : static_assert(isActiveTarget<Target>::value,
73 : "No active target communication window");
74 336 : MPI_Win_fence(asrt, win_m);
75 336 : }
76 :
77 : template <TargetComm Target>
78 : template <std::contiguous_iterator Iter>
79 : void Window<Target>::put(Iter first, Iter last, int dest, unsigned int pos,
80 : Request* request) {
81 : MPI_Datatype datatype = get_mpi_datatype<typename Iter::value_type>(*first);
82 : auto count = std::distance(first, last);
83 : if (count > count_m) {
84 : throw IpplException("Window::put", "Count exceeds RMA window size.");
85 : }
86 : if (request == nullptr) {
87 : MPI_Put(&(*first), count, datatype, dest, (MPI_Aint)pos, count, datatype,
88 : win_m);
89 : } else {
90 : MPI_Rput(&(*first), count, datatype, dest, (MPI_Aint)pos, count, datatype,
91 : win_m, *request);
92 : }
93 : }
94 :
95 : template <TargetComm Target>
96 : template <typename T>
97 132 : void Window<Target>::put(const T& value, int dest, unsigned int pos, Request* request) {
98 132 : this->put(&value, dest, pos, request);
99 132 : }
100 :
101 : template <TargetComm Target>
102 : template <typename T>
103 132 : void Window<Target>::put(const T* value, int dest, unsigned int pos, Request* request) {
104 132 : MPI_Datatype datatype = get_mpi_datatype<T>(*value);
105 132 : if (request == nullptr) {
106 132 : MPI_Put(value, 1, datatype, dest, (MPI_Aint)pos, 1, datatype, win_m);
107 : } else {
108 0 : MPI_Rput(value, 1, datatype, dest, (MPI_Aint)pos, 1, datatype, win_m, *request);
109 : }
110 132 : }
111 :
112 : template <TargetComm Target>
113 : template <std::contiguous_iterator Iter>
114 : void Window<Target>::get(Iter first, Iter last, int source, unsigned int pos,
115 : Request* request) {
116 : MPI_Datatype datatype = get_mpi_datatype<typename Iter::value_type>(*first);
117 : auto count = std::distance(first, last);
118 : if (count > count_m) {
119 : throw IpplException("Window::put", "Count exceeds RMA window size.");
120 : }
121 : if (request == nullptr) {
122 : MPI_Get(&(*first), count, datatype, source, (MPI_Aint)pos, count, datatype,
123 : win_m);
124 : } else {
125 : MPI_Rget(&(*first), count, datatype, source, (MPI_Aint)pos, count, datatype,
126 : win_m, *request);
127 : }
128 : }
129 :
130 : template <TargetComm Target>
131 : template <typename T>
132 : void Window<Target>::get(T& value, int source, unsigned int pos, Request* request) {
133 : this->get(&value, source, pos, request);
134 : }
135 :
136 : template <TargetComm Target>
137 : template <typename T>
138 : void Window<Target>::get(T* value, int source, unsigned int pos, Request* request) {
139 : MPI_Datatype datatype = get_mpi_datatype<T>(*value);
140 : if (request == nullptr) {
141 : MPI_Get(value, 1, datatype, source, (MPI_Aint)pos, 1, datatype, win_m);
142 : } else {
143 : MPI_Rget(value, 1, datatype, source, (MPI_Aint)pos, 1, datatype, win_m,
144 : *request);
145 : }
146 : }
147 :
148 : /*
149 : * Passive target communication:
150 : */
151 : template <TargetComm Target>
152 : void Window<Target>::flush(int rank) {
153 : static_assert(!isActiveTarget<Target>::value,
154 : "No passive target communication window");
155 : MPI_Win_flush(rank, win_m);
156 : }
157 :
158 : template <TargetComm Target>
159 : void Window<Target>::flushall() {
160 : static_assert(!isActiveTarget<Target>::value,
161 : "No passive target communication window");
162 : MPI_Win_flush_all(win_m);
163 : }
164 :
165 : template <TargetComm Target>
166 : void Window<Target>::lock(int locktype, int rank, int asrt) {
167 : static_assert(!isActiveTarget<Target>::value,
168 : "No passive target communication window");
169 : MPI_Win_lock(locktype, rank, asrt, win_m);
170 : }
171 :
172 : template <TargetComm Target>
173 : void Window<Target>::lockall(int asrt) {
174 : static_assert(!isActiveTarget<Target>::value,
175 : "No passive target communication window");
176 : MPI_Win_lock_all(asrt, win_m);
177 : }
178 :
179 : template <TargetComm Target>
180 : void Window<Target>::unlock(int rank) {
181 : static_assert(!isActiveTarget<Target>::value,
182 : "No passive target communication window");
183 : MPI_Win_unlock(rank, win_m);
184 : }
185 :
186 : template <TargetComm Target>
187 : void Window<Target>::unlockall() {
188 : static_assert(!isActiveTarget<Target>::value,
189 : "No passive target communication window");
190 : MPI_Win_unlock_all(win_m);
191 : }
192 :
193 : } // namespace rma
194 : } // namespace mpi
195 : } // namespace ippl
|