Yet Another eXchange Tool 0.11.3
Loading...
Searching...
No Matches
xt_request_msgs_ebuf.c
Go to the documentation of this file.
1
12/*
13 * Keywords:
14 * Maintainer: Jörg Behrens <behrens@dkrz.de>
15 * Moritz Hanke <hanke@dkrz.de>
16 * Thomas Jahns <jahns@dkrz.de>
17 * URL: https://dkrz-sw.gitlab-pages.dkrz.de/yaxt/
18 *
19 * Redistribution and use in source and binary forms, with or without
20 * modification, are permitted provided that the following conditions are
21 * met:
22 *
23 * Redistributions of source code must retain the above copyright notice,
24 * this list of conditions and the following disclaimer.
25 *
26 * Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
29 *
30 * Neither the name of the DKRZ GmbH nor the names of its contributors
31 * may be used to endorse or promote products derived from this software
32 * without specific prior written permission.
33 *
34 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
35 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
36 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
37 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
38 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
39 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
40 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
41 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
42 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
43 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
44 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
45 */
46#ifdef HAVE_CONFIG_H
47#include <config.h>
48#endif
49
50#include <assert.h>
51#include <stdlib.h>
52#include <string.h>
53
54#include <mpi.h>
55#ifdef _OPENMP
56#include <omp.h>
57#endif
58
59#include "core/ppm_xfuncs.h"
60#include "xt/xt_mpi.h"
61
64#include "xt_config_internal.h"
65#include "xt_mpi_internal.h"
66#include "xt_request_internal.h"
67
68static void xt_request_msgs_ebuf_wait(Xt_request request);
69static int xt_request_msgs_ebuf_test(Xt_request request);
70
71#ifdef _OPENMP
72static void
73xt_request_msgs_ebuf_wait_omp(Xt_request request);
74static int
75xt_request_msgs_ebuf_test_omp(Xt_request request);
76#endif
77
83#ifdef _OPENMP
84 , request_msgs_ebuf_auto_omp_vtable = {
85 .wait = xt_request_msgs_ebuf_wait_omp,
86 .test = xt_request_msgs_ebuf_test_omp,
87};
88#endif
89;
90
92
97 void (*finalizer)(Xt_request, void *);
99 MPI_Request requests[];
100};
101
102#define no_finalizer ((void (*)(Xt_request, void *))0)
103
106 MPI_Comm comm,
107 size_t extra_buf_size,
108 Xt_config config)
109{
110 size_t hdr_size = sizeof(struct Xt_request_msgs_ebuf_),
111 bufr_size = (size_t)n_requests * sizeof(MPI_Request)
112 + (size_t)n_requests * sizeof(int);
113 /* round allocation up to next multiple of sizeof (void *) to place
114 * beginning of user requested extra buffer */
115 size_t ofs = ((hdr_size + bufr_size + sizeof (void *) - 1)
116 & -sizeof(void *));
117 Xt_request_msgs_ebuf request = xmalloc(ofs + extra_buf_size);
118#ifndef _OPENMP
119 (void)config;
120#else
121 int mthread_mode = xt_config_get_redist_mthread_mode(config);
122 if (mthread_mode == XT_MT_OPENMP)
123 request->vtable = &request_msgs_ebuf_auto_omp_vtable;
124 else
125#endif
127 request->comm = comm;
128 request->n_requests = n_requests;
129 request->finalizer = no_finalizer;
130 request->extra_buf_ofs = ofs;
131 return (Xt_request)request;
132}
133
134static inline void *
136{
137 size_t ofs = request_msgs_ebuf->extra_buf_ofs;
138 return (unsigned char *)request_msgs_ebuf + ofs;
139}
140
143 size_t extra_buf_size,
145 void *data,
147 MPI_Comm comm) {
148 return xt_request_msgs_ebuf_custom_new(n_requests, extra_buf_size, init, data,
149 finalize, comm, &xt_default_config);
150}
151
154 size_t extra_buf_size,
156 void *data,
159 Xt_config config)
160{
161 assert(n_requests >= 0);
164 n_requests, comm, extra_buf_size, config);
166 init((Xt_request)request, request->requests, extra_buf(request),
167 data, comm);
168 return (Xt_request)request;
169}
170
171static void
173{
174 if (request_msgs_ebuf->finalizer != no_finalizer)
175 request_msgs_ebuf->finalizer((Xt_request)request_msgs_ebuf,
176 extra_buf(request_msgs_ebuf));
177 free(request_msgs_ebuf);
178}
179
181
182 Xt_request_msgs_ebuf request_msgs_ebuf = (Xt_request_msgs_ebuf)request;
183
184/* unfortunately GCC 11 cannot handle the literal constants used for
185 * MPI_STATUSES_IGNORE by MPICH */
186#if __GNUC__ >= 11 && __GNUC__ <= 13 && defined MPICH
187#pragma GCC diagnostic push
188#pragma GCC diagnostic ignored "-Wstringop-overread"
189#pragma GCC diagnostic ignored "-Wstringop-overflow"
190#endif
191 xt_mpi_call(MPI_Waitall(request_msgs_ebuf->n_requests,
192 request_msgs_ebuf->requests, MPI_STATUSES_IGNORE),
193 request_msgs_ebuf->comm);
194#if __GNUC__ >= 11 && __GNUC__ <= 13 && defined MPICH
195#pragma GCC diagnostic pop
196#endif
197 finish_requests(request_msgs_ebuf);
198}
199
201
202 Xt_request_msgs_ebuf request_msgs_ebuf = (Xt_request_msgs_ebuf)request;
203
204 int flag =
205 xt_mpi_test_some(&(request_msgs_ebuf->n_requests),
206 request_msgs_ebuf->requests,
207 (int *)(request_msgs_ebuf->requests
208 + request_msgs_ebuf->n_requests),
209 request_msgs_ebuf->comm);
210
211 if (flag)
212 finish_requests(request_msgs_ebuf);
213
214 return flag;
215}
216
217MPI_Request *
219{
220 Xt_request_msgs_ebuf request_msgs_ebuf = (Xt_request_msgs_ebuf)request;
221#ifndef _OPENMP
222 assert(request->vtable == &request_msgs_ebuf_vtable);
223#else
224 assert(request->vtable == &request_msgs_ebuf_vtable
225 || request->vtable == &request_msgs_ebuf_auto_omp_vtable);
226#endif
227 return request_msgs_ebuf->requests;
228}
229
232{
233 Xt_request_msgs_ebuf request_msgs_ebuf = (Xt_request_msgs_ebuf)request;
234#ifndef _OPENMP
235 assert(request->vtable == &request_msgs_ebuf_vtable);
236#else
237 assert(request->vtable == &request_msgs_ebuf_vtable
238 || request->vtable == &request_msgs_ebuf_auto_omp_vtable);
239#endif
240 return request_msgs_ebuf->comm;
241}
242
243void
246{
247 Xt_request_msgs_ebuf request_msgs_ebuf = (Xt_request_msgs_ebuf)request;
248#ifndef _OPENMP
249 assert(request->vtable == &request_msgs_ebuf_vtable);
250#else
251 assert(request->vtable == &request_msgs_ebuf_vtable
252 || request->vtable == &request_msgs_ebuf_auto_omp_vtable);
253#endif
254 request_msgs_ebuf->finalizer = finalizer;
255}
256
257void *
259{
260 Xt_request_msgs_ebuf request_msgs_ebuf = (Xt_request_msgs_ebuf)request;
261#ifndef _OPENMP
262 assert(request->vtable == &request_msgs_ebuf_vtable);
263#else
264 assert(request->vtable == &request_msgs_ebuf_vtable
265 || request->vtable == &request_msgs_ebuf_auto_omp_vtable);
266#endif
267 return extra_buf(request_msgs_ebuf);
268}
269
270
271#ifdef _OPENMP
272static void
273finish_requests_mt(Xt_request_msgs_ebuf request_msgs_ebuf)
274{
275 if (request_msgs_ebuf->finalizer != no_finalizer)
276 request_msgs_ebuf->finalizer((Xt_request)request_msgs_ebuf,
277 extra_buf(request_msgs_ebuf));
278#pragma omp barrier
279#pragma omp master
280 free(request_msgs_ebuf);
281}
282
283static void
284xt_request_msgs_ebuf_wait_omp(Xt_request request)
285{
286#pragma omp parallel
287 {
288 Xt_request_msgs_ebuf request_msgs = (Xt_request_msgs_ebuf)request;
289 int num_threads = omp_get_num_threads(),
290 tid = omp_get_thread_num();
291 int nreq = request_msgs->n_requests,
292 start_req = (nreq * tid) / num_threads,
293 nreq_ = (nreq * (tid+1)) / num_threads - start_req;
294
295/* unfortunately GCC 11 cannot handle the literal constants used for
296 * MPI_STATUSES_IGNORE by MPICH */
297#if __GNUC__ >= 11 && __GNUC__ <= 13 && defined MPICH
298#pragma GCC diagnostic push
299#pragma GCC diagnostic ignored "-Wstringop-overread"
300#pragma GCC diagnostic ignored "-Wstringop-overflow"
301#endif
302 xt_mpi_call(MPI_Waitall(nreq_, request_msgs->requests+start_req,
303 MPI_STATUSES_IGNORE), request_msgs->comm);
304#if __GNUC__ >= 11 && __GNUC__ <= 13 && defined MPICH
305#pragma GCC diagnostic pop
306#endif
307#pragma omp barrier
308 finish_requests_mt(request_msgs);
309 }
310}
311
312static int
313xt_request_msgs_ebuf_test_omp(Xt_request request)
314{
315 bool flag = true;
316#pragma omp parallel
317 {
318 Xt_request_msgs_ebuf request_msgs = (Xt_request_msgs_ebuf)request;
319
320 int *ops_completed_buffer
321 = (int *)(request_msgs->requests + request_msgs->n_requests);
322 bool flag_
323 = xt_mpi_test_some_mt(&request_msgs->n_requests,
324 request_msgs->requests,
325 ops_completed_buffer,
326 request_msgs->comm);
327#pragma omp master
328 flag = flag_;
329#pragma omp barrier
330 if (flag_)
331 finish_requests_mt(request_msgs);
332 }
333
334 return flag;
335}
336#endif
337
338/*
339 * Local Variables:
340 * c-basic-offset: 2
341 * coding: utf-8
342 * indent-tabs-mode: nil
343 * show-trailing-whitespace: t
344 * require-trailing-newline: t
345 * End:
346 */
int MPI_Comm
Definition core.h:64
add versions of standard API functions not returning on error
#define xmalloc(size)
Definition ppm_xfuncs.h:70
const struct Xt_request_vtable * vtable
const struct Xt_request_vtable * vtable
void(* finalizer)(Xt_request, void *)
struct Xt_config_ xt_default_config
Definition xt_config.c:204
@ XT_MT_OPENMP
Definition xt_config.h:142
int xt_config_get_redist_mthread_mode(Xt_config config)
Definition xt_config.c:340
implementation of configuration object
bool xt_mpi_test_some(int *restrict num_req, MPI_Request *restrict req, int *restrict ops_completed, MPI_Comm comm)
Definition xt_mpi.c:415
utility routines for MPI
#define xt_mpi_call(call, comm)
Definition xt_mpi.h:68
struct Xt_request_ * Xt_request
Definition xt_request.h:51
Provide non-public declarations common to all requests.
void xt_request_msgs_ebuf_set_finalizer(Xt_request request, Xt_request_msgs_ebuf_finalizer finalizer)
static int xt_request_msgs_ebuf_test(Xt_request request)
static void finish_requests(Xt_request_msgs_ebuf request_msgs_ebuf)
MPI_Comm xt_request_msgs_ebuf_get_comm(Xt_request request)
struct Xt_request_msgs_ebuf_ * Xt_request_msgs_ebuf
static const struct Xt_request_vtable request_msgs_ebuf_vtable
Xt_request xt_request_msgs_ebuf_custom_new(int n_requests, size_t extra_buf_size, Xt_fill_ebuf_requests init, void *data, Xt_request_msgs_ebuf_finalizer finalize, MPI_Comm comm, Xt_config config)
Xt_request xt_request_msgs_ebuf_alloc(int n_requests, MPI_Comm comm, size_t extra_buf_size, Xt_config config)
#define no_finalizer
static void * extra_buf(Xt_request_msgs_ebuf request_msgs_ebuf)
static void xt_request_msgs_ebuf_wait(Xt_request request)
Xt_request xt_request_msgs_ebuf_new(int n_requests, size_t extra_buf_size, Xt_fill_ebuf_requests init, void *data, Xt_request_msgs_ebuf_finalizer finalize, MPI_Comm comm)
MPI_Request * xt_request_msgs_ebuf_get_req_ptr(Xt_request request)
void * xt_request_msgs_ebuf_get_extra_buf(Xt_request request)
functions to create collection of request handles augmented with user-defined buffer
void(* Xt_request_msgs_ebuf_finalizer)(Xt_request request_msgs, void *ebuf)
void(* Xt_fill_ebuf_requests)(Xt_request requests_msgs, MPI_Request *requests, void *ebuf, void *data, MPI_Comm comm)
internal interfaces for xt_request_msgs_ebuf