MeDiPack  1.4.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-2026 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/medi).
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);
111 inline void AMPI_Wait_iter_empty(HandleBase* handle, CallbackFunc func, void* userData);
112 inline void AMPI_Wait_iterIn(HandleBase* handle, CallbackFunc func, void* userData);
113 inline void AMPI_Wait_iterOut(HandleBase* handle, CallbackFunc func, void* userData);
142
143 inline void AMPI_Wait_b(HandleBase* handle, AdjointInterface* adjointInterface) {
144 WaitHandle* h = static_cast<WaitHandle*>(handle);
145
146 h->finishFuncReverse(h->adjointHandle, adjointInterface);
147 }
148
149 inline void AMPI_Wait_d(HandleBase* handle, AdjointInterface* adjointInterface) {
150 WaitHandle* h = static_cast<WaitHandle*>(handle);
151
152 h->finishFuncForward(h->adjointHandle, adjointInterface);
153 }
154
155 inline void AMPI_Wait_iter_empty(HandleBase* handle, CallbackFunc func, void* userData) {
156 (void)handle;
157 (void)func;
158 (void)userData;
159 }
160
161 inline void AMPI_Wait_iterIn(HandleBase* handle, CallbackFunc func, void* userData) {
162 WaitHandle* h = static_cast<WaitHandle*>(handle);
163
164 h->original_funcIterateInputIds(h->adjointHandle, func, userData);
165 }
166
167 inline void performStartAction(AMPI_Request *request) {
168 if( nullptr != request->start // indicates a persistent communication request
169 && !request->isActive) { // only perform start action if the persistent communication request is not active
170 request->start(request->handle);
171 request->isActive = true;
172 }
173 }
174
175 inline void performReverseAction(AMPI_Request *request) {
176 if( nullptr != request->func // if there is a reverse action, proceed if
177 && (nullptr == request->start // either the request is not persistent
178 || request->isActive)) { // or it is active
179 request->func(request->handle);
180
181 request->deleteReverseData();
182 }
183
184 if(nullptr == request->start) {
185 // Only reset if this is a non persistent request
186 *request = AMPI_REQUEST_NULL;
187 } else {
188 request->isActive = false;
189 }
190 }
191
192 inline MPI_Request* convertToMPI(AMPI_Request* array, int count) {
193 MPI_Request* converted = new MPI_Request[count];
194
195 for(int i = 0; i < count; ++i) {
196 converted[i] = array[i].request;
197 }
198
199 return converted;
200 }
201
202#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
203 inline int AMPI_Wait(AMPI_Request *request, AMPI_Status *status) {
204 if(AMPI_REQUEST_NULL == *request) {
205 return 0;
206 }
207
208 int rStatus = MPI_Wait(&request->request, status);
209
210 performReverseAction(request);
211
212 return rStatus;
213 }
214#endif
215
216#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
217 inline int AMPI_Test(AMPI_Request *request, int* flag, AMPI_Status *status) {
218 if(AMPI_REQUEST_NULL == *request) {
219 *flag = (int)true;
220 return 0;
221 }
222
223 int rStatus = MPI_Test(&request->request, flag, status);
224
225 if(true == *flag) {
226 performReverseAction(request);
227 }
228
229 return rStatus;
230 }
231#endif
232
233#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
234 inline int AMPI_Start(AMPI_Request* request) {
235
236 if(AMPI_REQUEST_NULL == *request) {
237 return 0;
238 }
239
240
241 performStartAction(request);
242
243 return MPI_Start(&request->request);
244 }
245#endif
246
247#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
248 inline int AMPI_Startall(int count, AMPI_Request* array_of_requests) {
249 MPI_Request* array = convertToMPI(array_of_requests, count);
250
251 for(int i = 0; i < count; ++i) {
252 if(AMPI_REQUEST_NULL != array_of_requests[i]) {
253 performStartAction(&array_of_requests[i]);
254 }
255 }
256
257 int rStatus = MPI_Startall(count, array);
258
259 delete [] array;
260
261 return rStatus;
262 }
263#endif
264
265#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
266 inline int AMPI_Request_free(AMPI_Request *request) {
267 if(AMPI_REQUEST_NULL == *request) {
268 return 0;
269 }
270
271 if(nullptr != request->end && false == request->isActive) {
272 request->end(request->handle);
273 } else {
274 MEDI_EXCEPTION("Freeing a handle that is not finish with wait, waitall, etc..");
275 }
276
277 int rStatus = MPI_Request_free(&request->request);
278 *request = AMPI_REQUEST_NULL;
279
280 return rStatus;
281 }
282#endif
283
284#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
285 inline int AMPI_Waitany(int count, AMPI_Request* array_of_requests, int *index, AMPI_Status *status) {
286 MPI_Request* array = convertToMPI(array_of_requests, count);
287
288 int rStatus = MPI_Waitany(count, array, index, status);
289
290 if(MPI_UNDEFINED != *index) {
291 performReverseAction(&array_of_requests[*index]);
292 }
293
294 delete [] array;
295
296 return rStatus;
297 }
298#endif
299
300#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
301 inline int AMPI_Testany(int count, AMPI_Request* array_of_requests, int *index, int *flag, AMPI_Status *status) {
302 MPI_Request* array = convertToMPI(array_of_requests, count);
303
304 int rStatus = MPI_Testany(count, array, index, flag, status);
305
306 if(true == *flag) {
307 if(MPI_UNDEFINED != *index) {
308 performReverseAction(&array_of_requests[*index]);
309 }
310 }
311
312 delete [] array;
313
314 return rStatus;
315 }
316#endif
317
318#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
319 inline int AMPI_Waitall(int count, AMPI_Request* array_of_requests, AMPI_Status* array_of_statuses) {
320 MPI_Request* array = convertToMPI(array_of_requests, count);
321
322 int rStatus = MPI_Waitall(count, array, array_of_statuses);
323
324 for(int i = 0; i < count; ++i) {
325 if(AMPI_REQUEST_NULL != array_of_requests[i]) {
326 performReverseAction(&array_of_requests[i]);
327 }
328 }
329
330 delete [] array;
331
332 return rStatus;
333 }
334#endif
335
336#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
337 inline int AMPI_Testall(int count, AMPI_Request* array_of_requests, int *flag, AMPI_Status* array_of_statuses) {
338 MPI_Request* array = convertToMPI(array_of_requests, count);
339
340 int rStatus = MPI_Testall(count, array, flag, array_of_statuses);
341
342 if(true == *flag) {
343 for(int i = 0; i < count; ++i) {
344 if(AMPI_REQUEST_NULL != array_of_requests[i]) {
345 performReverseAction(&array_of_requests[i]);
346 }
347 }
348 }
349
350 delete [] array;
351
352 return rStatus;
353 }
354#endif
355
356#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
357 inline int AMPI_Waitsome(int incount, AMPI_Request* array_of_requests, int *outcount, int* array_of_indices, AMPI_Status* array_of_statuses) {
358 MPI_Request* array = convertToMPI(array_of_requests, incount);
359
360 int rStatus = MPI_Waitsome(incount, array, outcount, array_of_indices, array_of_statuses);
361
362 for(int i = 0; i < *outcount; ++i) {
363 int index = array_of_indices[i];
364 if(AMPI_REQUEST_NULL != array_of_requests[index]) {
365 performReverseAction(&array_of_requests[index]);
366 }
367 }
368
369 delete [] array;
370
371 return rStatus;
372 }
373#endif
374
375#if MEDI_MPI_VERSION_1_0 <= MEDI_MPI_TARGET
376 inline int AMPI_Testsome(int incount, AMPI_Request* array_of_requests, int *outcount, int* array_of_indices, AMPI_Status* array_of_statuses) {
377 MPI_Request* array = convertToMPI(array_of_requests, incount);
378
379 int rStatus = MPI_Testsome(incount, array, outcount, array_of_indices, array_of_statuses);
380
381 for(int i = 0; i < *outcount; ++i) {
382 int index = array_of_indices[i];
383 if(AMPI_REQUEST_NULL != array_of_requests[index]) {
384 performReverseAction(&array_of_requests[index]);
385 }
386 }
387
388 delete [] array;
389
390 return rStatus;
391 }
392#endif
393
394#if MEDI_MPI_VERSION_3_0 <= MEDI_MPI_TARGET
395 inline int AMPI_Ibarrier(AMPI_Comm comm, AMPI_Request *request) {
396
397 int rStatus = MPI_Ibarrier(comm, &request->request);
398 request->func = nullptr;
399
400 return rStatus;
401 }
402#endif
403}
#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
@ Wait
Definition typeDefinitions.h:42
@ Async
Definition typeDefinitions.h:41
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:376
MPI_Request * convertToMPI(AMPI_Request *array, int count)
Definition async.hpp:192
bool operator!=(const AMPI_Request &a, const AMPI_Request &b)
Definition async.hpp:86
void AMPI_Wait_iterOut(HandleBase *handle, CallbackFunc func, void *userData)
void performReverseAction(AMPI_Request *request)
Definition async.hpp:175
int AMPI_Testany(int count, AMPI_Request *array_of_requests, int *index, int *flag, MPI_Status *status)
Definition async.hpp:301
int AMPI_Startall(int count, AMPI_Request *array_of_requests)
Definition async.hpp:248
int AMPI_Waitall(int count, AMPI_Request *array_of_requests, MPI_Status *array_of_statuses)
Definition async.hpp:319
void(* ForwardFunction)(HandleBase *h, AdjointInterface *a)
Definition typeDefinitions.h:49
void AMPI_Wait_iterIn(HandleBase *handle, CallbackFunc func, void *userData)
Definition async.hpp:161
int AMPI_Start(AMPI_Request *request)
Definition async.hpp:234
void(*)(void *id, void *userData) CallbackFunc
Definition typeDefinitions.h:45
int AMPI_Test(AMPI_Request *request, int *flag, MPI_Status *status)
Definition async.hpp:217
void(* IterateIdsFunction)(HandleBase *h, CallbackFunc func, void *userData)
Definition typeDefinitions.h:51
int AMPI_Request_free(AMPI_Request *request)
Definition async.hpp:266
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:285
void AMPI_Wait_b(HandleBase *handle, AdjointInterface *adjointInterface)
Definition async.hpp:143
int AMPI_Wait(AMPI_Request *request, MPI_Status *status)
Definition async.hpp:203
int(* ContinueFunction)(HandleBase *h)
Definition typeDefinitions.h:52
int AMPI_Waitsome(int incount, AMPI_Request *array_of_requests, int *outcount, int *array_of_indices, MPI_Status *array_of_statuses)
Definition async.hpp:357
int AMPI_Ibarrier(MPI_Comm comm, AMPI_Request *request)
Definition async.hpp:395
int AMPI_Testall(int count, AMPI_Request *array_of_requests, int *flag, MPI_Status *array_of_statuses)
Definition async.hpp:337
bool operator==(const AMPI_Request &a, const AMPI_Request &b)
Definition async.hpp:82
void(* ReverseFunction)(HandleBase *h, AdjointInterface *a)
Definition typeDefinitions.h:48
void AMPI_Wait_d(HandleBase *handle, AdjointInterface *adjointInterface)
Definition async.hpp:149
void performStartAction(AMPI_Request *request)
Definition async.hpp:167
void AMPI_Wait_iter_empty(HandleBase *handle, CallbackFunc func, void *userData)
Definition async.hpp:155
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:57
IterateIdsFunction funcIterateOutputIds
Definition typeDefinitions.h:67
ManualDeleteType deleteType
Definition typeDefinitions.h:65
IterateIdsFunction funcIterateInputIds
Definition typeDefinitions.h:66
ReverseFunction funcReverse
Definition typeDefinitions.h:62
HandleBase()
Definition typeDefinitions.h:69
ForwardFunction funcForward
Definition typeDefinitions.h:63
Definition async.hpp:114
AsyncAdjointHandle * adjointHandle
Definition async.hpp:117
ForwardFunction finishFuncForward
Definition async.hpp:116
WaitHandle(ReverseFunction finishFuncReverse, ForwardFunction finishFuncForward, AsyncAdjointHandle *handle)
Definition async.hpp:121
IterateIdsFunction original_funcIterateInputIds
Definition async.hpp:119
ReverseFunction finishFuncReverse
Definition async.hpp:115