MeDiPack  1.3.0
A Message Differentiation Package
SciComp TU Kaiserslautern
Loading...
Searching...
No Matches
async.hpp
Go to the documentation of this file.
1/*
2 * MeDiPack, a Message Differentiation Package
3 *
4 * Copyright (C) 2015-2024 Chair for Scientific Computing (SciComp), University of Kaiserslautern-Landau
5 * Homepage: http://scicomp.rptu.de
6 * Contact: Prof. Nicolas R. Gauger (codi@scicomp.uni-kl.de)
7 *
8 * Lead developers: Max Sagebaum (SciComp, University of Kaiserslautern-Landau)
9 *
10 * This file is part of MeDiPack (http://scicomp.rptu.de/software/codi).
11 *
12 * MeDiPack is free software: you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation, either
15 * version 3 of the License, or (at your option) any later version.
16 *
17 * MeDiPack is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 *
21 * See the GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU
23 * Lesser General Public License along with MeDiPack.
24 * If not, see <http://www.gnu.org/licenses/>.
25 *
26 * Authors: Max Sagebaum, Tim Albring (SciComp, University of Kaiserslautern-Landau)
27 */
28
29#pragma once
30
31#include "ampiMisc.h"
32
34#include "../exceptions.hpp"
35
39namespace medi {
40
41 typedef void (*DeleteReverseData)(void* data);
42
43 struct AsyncHandle;
44
45 struct AMPI_Request {
46 MPI_Request request;
49
50 // Required for init requests
51 // note that request activity tracking is only performed for persistent communication
55
56 // required for reverse communication that needs to create data
59
61 request(MPI_REQUEST_NULL),
62 handle(NULL),
63 func(NULL),
64 start(NULL),
65 end(NULL),
66 isActive(false),
67 reverseData(NULL),
68 deleteDataFunc(NULL){}
69
70 inline void setReverseData(void* data, DeleteReverseData func) {
71 this->reverseData = data;
72 this->deleteDataFunc = func;
73 }
74
75 inline void deleteReverseData() {
76 if(NULL != reverseData) {
77 this->deleteDataFunc(this->reverseData);
78 }
79 }
80 };
81
82 inline bool operator ==(const AMPI_Request& a, const AMPI_Request& b) {
83 return a.request == b.request;
84 }
85
86 inline bool operator !=(const AMPI_Request& a, const AMPI_Request& b) {
87 return a.request != b.request;
88 }
89
90 extern const AMPI_Request AMPI_REQUEST_NULL;
91
100
101 struct AsyncHandle : public HandleBase {
102
104
107 };
108
109 inline void AMPI_Wait_b(HandleBase* handle, AdjointInterface* adjointInterface);
110 inline void AMPI_Wait_d(HandleBase* handle, AdjointInterface* adjointInterface);
129
130 inline void AMPI_Wait_b(HandleBase* handle, AdjointInterface* adjointInterface) {
131 WaitHandle* h = static_cast<WaitHandle*>(handle);
132
133 h->finishFuncReverse(h->adjointHandle, adjointInterface);
134 }
135
136 inline void AMPI_Wait_d(HandleBase* handle, AdjointInterface* adjointInterface) {
137 WaitHandle* h = static_cast<WaitHandle*>(handle);
138
139 h->finishFuncForward(h->adjointHandle, adjointInterface);
140 }
141
142 inline void performStartAction(AMPI_Request *request) {
143 if( nullptr != request->start // indicates a persistent communication request
144 && !request->isActive) { // only perform start action if the persistent communication request is not active
145 request->start(request->handle);
146 request->isActive = true;
147 }
148 }
149
150 inline void performReverseAction(AMPI_Request *request) {
151 if( nullptr != request->func // if there is a reverse action, proceed if
152 && (nullptr == request->start // either the request is not persistent
153 || request->isActive)) { // or it is active
154 request->func(request->handle);
155
156 request->deleteReverseData();
157 }
158
159 if(nullptr == request->start) {
160 // Only reset if this is a non persistent request
161 *request = AMPI_REQUEST_NULL;
162 } else {
163 request->isActive = false;
164 }
165 }
166
167 inline MPI_Request* convertToMPI(AMPI_Request* array, int count) {
168 MPI_Request* converted = new MPI_Request[count];
169
170 for(int i = 0; i < count; ++i) {
171 converted[i] = array[i].request;
172 }
173
174 return converted;
175 }
176
177#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
178 inline int AMPI_Wait(AMPI_Request *request, AMPI_Status *status) {
179 if(AMPI_REQUEST_NULL == *request) {
180 return 0;
181 }
182
183 int rStatus = MPI_Wait(&request->request, status);
184
185 performReverseAction(request);
186
187 return rStatus;
188 }
189#endif
190
191#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
192 inline int AMPI_Test(AMPI_Request *request, int* flag, AMPI_Status *status) {
193 if(AMPI_REQUEST_NULL == *request) {
194 *flag = (int)true;
195 return 0;
196 }
197
198 int rStatus = MPI_Test(&request->request, flag, status);
199
200 if(true == *flag) {
201 performReverseAction(request);
202 }
203
204 return rStatus;
205 }
206#endif
207
208#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
209 inline int AMPI_Start(AMPI_Request* request) {
210
211 if(AMPI_REQUEST_NULL == *request) {
212 return 0;
213 }
214
215
216 performStartAction(request);
217
218 return MPI_Start(&request->request);
219 }
220#endif
221
222#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
223 inline int AMPI_Startall(int count, AMPI_Request* array_of_requests) {
224 MPI_Request* array = convertToMPI(array_of_requests, count);
225
226 for(int i = 0; i < count; ++i) {
227 if(AMPI_REQUEST_NULL != array_of_requests[i]) {
228 performStartAction(&array_of_requests[i]);
229 }
230 }
231
232 int rStatus = MPI_Startall(count, array);
233
234 delete [] array;
235
236 return rStatus;
237 }
238#endif
239
240#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
241 inline int AMPI_Request_free(AMPI_Request *request) {
242 if(AMPI_REQUEST_NULL == *request) {
243 return 0;
244 }
245
246 if(nullptr != request->end && false == request->isActive) {
247 request->end(request->handle);
248 } else {
249 MEDI_EXCEPTION("Freeing a handle that is not finish with wait, waitall, etc..");
250 }
251
252 int rStatus = MPI_Request_free(&request->request);
253 *request = AMPI_REQUEST_NULL;
254
255 return rStatus;
256 }
257#endif
258
259#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
260 inline int AMPI_Waitany(int count, AMPI_Request* array_of_requests, int *index, AMPI_Status *status) {
261 MPI_Request* array = convertToMPI(array_of_requests, count);
262
263 int rStatus = MPI_Waitany(count, array, index, status);
264
265 if(MPI_UNDEFINED != *index) {
266 performReverseAction(&array_of_requests[*index]);
267 }
268
269 delete [] array;
270
271 return rStatus;
272 }
273#endif
274
275#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
276 inline int AMPI_Testany(int count, AMPI_Request* array_of_requests, int *index, int *flag, AMPI_Status *status) {
277 MPI_Request* array = convertToMPI(array_of_requests, count);
278
279 int rStatus = MPI_Testany(count, array, index, flag, status);
280
281 if(true == *flag) {
282 if(MPI_UNDEFINED != *index) {
283 performReverseAction(&array_of_requests[*index]);
284 }
285 }
286
287 delete [] array;
288
289 return rStatus;
290 }
291#endif
292
293#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
294 inline int AMPI_Waitall(int count, AMPI_Request* array_of_requests, AMPI_Status* array_of_statuses) {
295 MPI_Request* array = convertToMPI(array_of_requests, count);
296
297 int rStatus = MPI_Waitall(count, array, array_of_statuses);
298
299 for(int i = 0; i < count; ++i) {
300 if(AMPI_REQUEST_NULL != array_of_requests[i]) {
301 performReverseAction(&array_of_requests[i]);
302 }
303 }
304
305 delete [] array;
306
307 return rStatus;
308 }
309#endif
310
311#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
312 inline int AMPI_Testall(int count, AMPI_Request* array_of_requests, int *flag, AMPI_Status* array_of_statuses) {
313 MPI_Request* array = convertToMPI(array_of_requests, count);
314
315 int rStatus = MPI_Testall(count, array, flag, array_of_statuses);
316
317 if(true == *flag) {
318 for(int i = 0; i < count; ++i) {
319 if(AMPI_REQUEST_NULL != array_of_requests[i]) {
320 performReverseAction(&array_of_requests[i]);
321 }
322 }
323 }
324
325 delete [] array;
326
327 return rStatus;
328 }
329#endif
330
331#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
332 inline int AMPI_Waitsome(int incount, AMPI_Request* array_of_requests, int *outcount, int* array_of_indices, AMPI_Status* array_of_statuses) {
333 MPI_Request* array = convertToMPI(array_of_requests, incount);
334
335 int rStatus = MPI_Waitsome(incount, array, outcount, array_of_indices, array_of_statuses);
336
337 for(int i = 0; i < *outcount; ++i) {
338 int index = array_of_indices[i];
339 if(AMPI_REQUEST_NULL != array_of_requests[index]) {
340 performReverseAction(&array_of_requests[index]);
341 }
342 }
343
344 delete [] array;
345
346 return rStatus;
347 }
348#endif
349
350#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
351 inline int AMPI_Testsome(int incount, AMPI_Request* array_of_requests, int *outcount, int* array_of_indices, AMPI_Status* array_of_statuses) {
352 MPI_Request* array = convertToMPI(array_of_requests, incount);
353
354 int rStatus = MPI_Testsome(incount, array, outcount, array_of_indices, array_of_statuses);
355
356 for(int i = 0; i < *outcount; ++i) {
357 int index = array_of_indices[i];
358 if(AMPI_REQUEST_NULL != array_of_requests[index]) {
359 performReverseAction(&array_of_requests[index]);
360 }
361 }
362
363 delete [] array;
364
365 return rStatus;
366 }
367#endif
368
369#if MEDI_MPI_VERSION_3_0 <= MEDI_MPI_TARGET
370 inline int AMPI_Ibarrier(AMPI_Comm comm, AMPI_Request *request) {
371
372 int rStatus = MPI_Ibarrier(comm, &request->request);
373 request->func = nullptr;
374
375 return rStatus;
376 }
377#endif
378}
#define AMPI_Status
Definition ampiDefinitions.h:772
#define AMPI_Comm
Definition ampiDefinitions.h:778
Definition adjointInterface.hpp:40
#define MEDI_EXCEPTION(...)
Generates an exception.
Definition exceptions.hpp:44
Global namespace for MeDiPack - Message Differentiation Package.
Definition adjointInterface.hpp:37
void(* DeleteReverseData)(void *data)
Definition async.hpp:41
int AMPI_Testsome(int incount, AMPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses)
Definition async.hpp:351
MPI_Request * convertToMPI(AMPI_Request *array, int count)
Definition async.hpp:167
bool operator!=(const AMPI_Request &a, const AMPI_Request &b)
Definition async.hpp:86
void performReverseAction(AMPI_Request *request)
Definition async.hpp:150
int AMPI_Testany(int count, AMPI_Request *array_of_requests, int *index, int *flag, MPI_Status *status)
Definition async.hpp:276
int AMPI_Startall(int count, AMPI_Request *array_of_requests)
Definition async.hpp:223
int AMPI_Waitall(int count, AMPI_Request *array_of_requests, MPI_Status *array_of_statuses)
Definition async.hpp:294
void(* ForwardFunction)(HandleBase *h, AdjointInterface *a)
Definition typeDefinitions.h:46
int AMPI_Start(AMPI_Request *request)
Definition async.hpp:209
int AMPI_Test(AMPI_Request *request, int *flag, MPI_Status *status)
Definition async.hpp:192
int AMPI_Request_free(AMPI_Request *request)
Definition async.hpp:241
const AMPI_Request AMPI_REQUEST_NULL
Definition async.cpp:35
int AMPI_Waitany(int count, AMPI_Request *array_of_requests, int *index, MPI_Status *status)
Definition async.hpp:260
void AMPI_Wait_b(HandleBase *handle, AdjointInterface *adjointInterface)
Definition async.hpp:130
int AMPI_Wait(AMPI_Request *request, MPI_Status *status)
Definition async.hpp:178
int(* ContinueFunction)(HandleBase *h)
Definition typeDefinitions.h:48
int AMPI_Waitsome(int incount, AMPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses)
Definition async.hpp:332
int AMPI_Ibarrier(MPI_Comm comm, AMPI_Request *request)
Definition async.hpp:370
int AMPI_Testall(int count, AMPI_Request *array_of_requests, int *flag, MPI_Status *array_of_statuses)
Definition async.hpp:312
bool operator==(const AMPI_Request &a, const AMPI_Request &b)
Definition async.hpp:82
void(* ReverseFunction)(HandleBase *h, AdjointInterface *a)
Definition typeDefinitions.h:45
void AMPI_Wait_d(HandleBase *handle, AdjointInterface *adjointInterface)
Definition async.hpp:136
void performStartAction(AMPI_Request *request)
Definition async.hpp:142
Definition async.hpp:45
AsyncHandle * handle
Definition async.hpp:47
DeleteReverseData deleteDataFunc
Definition async.hpp:58
AMPI_Request()
Definition async.hpp:60
void deleteReverseData()
Definition async.hpp:75
void * reverseData
Definition async.hpp:57
ContinueFunction start
Definition async.hpp:52
ContinueFunction end
Definition async.hpp:53
MPI_Request request
Definition async.hpp:46
ContinueFunction func
Definition async.hpp:48
void setReverseData(void *data, DeleteReverseData func)
Definition async.hpp:70
bool isActive
Definition async.hpp:54
Definition async.hpp:92
AMPI_Request requestReverse
Definition async.hpp:95
AsyncAdjointHandle()
Definition async.hpp:97
struct WaitHandle * waitHandle
Definition async.hpp:94
Definition async.hpp:101
AsyncAdjointHandle * toolHandle
Definition async.hpp:103
AsyncHandle()
Definition async.hpp:105
Definition typeDefinitions.h:53
ManualDeleteType deleteType
Definition typeDefinitions.h:57
ReverseFunction funcReverse
Definition typeDefinitions.h:54
ForwardFunction funcForward
Definition typeDefinitions.h:55
Definition async.hpp:111
AsyncAdjointHandle * adjointHandle
Definition async.hpp:114
ForwardFunction finishFuncForward
Definition async.hpp:113
WaitHandle(ReverseFunction finishFuncReverse, ForwardFunction finishFuncForward, AsyncAdjointHandle *handle)
Definition async.hpp:116
ReverseFunction finishFuncReverse
Definition async.hpp:112