Yet Another eXchange Tool 0.11.1
Loading...
Searching...
No Matches
xt_xmap_all2all.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 <stdlib.h>
51#include <stdio.h>
52#include <string.h>
53#include <assert.h>
54#include <limits.h>
55
56#include <mpi.h>
57
58#include "xt/xt_idxlist.h"
59#include "xt/xt_idxvec.h"
60#include "xt/xt_xmap.h"
61#include "xt/xt_mpi.h"
62#include "xt_mpi_internal.h"
63#include "core/core.h"
64#include "core/ppm_xfuncs.h"
65#include "xt/xt_xmap_all2all.h"
67#include "xt_config_internal.h"
68#include "xt_idxlist_internal.h"
69#include "instr.h"
70
71static void exchange_idxlists(struct Xt_com_list **src_intersections,
72 size_t *num_src_intersections,
73 struct Xt_com_list **dst_intersections,
74 size_t *num_dst_intersections,
75 int * stripify,
76 Xt_idxlist src_idxlist_local,
77 Xt_idxlist dst_idxlist_local,
78 MPI_Comm comm, Xt_config config)
79{
80
81 /*
82 Note: The meaning of source (src) and destination (dst) points can already be understood by
83 looking at the serial case, where it is just a transformation of sequences of integers
84 (called indices). The starting state (source sequence) is transformed into an end state
85 (dst sequence). The transformation does not have to be bijective. For each position dpos of
86 the dst sequence we have at least one position spos in the src sequence with:
87 dst(dpos) = src(spos)
88 */
89
90 int comm_size, rank, is_inter;
91 xt_mpi_call(MPI_Comm_rank(comm, &rank), comm);
92 xt_mpi_call(MPI_Comm_test_inter(comm, &is_inter), comm);
93 int (*get_comm_size)(MPI_Comm, int *)
94 = is_inter ? MPI_Comm_remote_size : MPI_Comm_size;
95 xt_mpi_call(get_comm_size(comm, &comm_size), comm);
96
97 // allocate memory for intersections
98 struct Xt_com_list *dsti = xmalloc((size_t)comm_size * sizeof (*dsti));
99 struct Xt_com_list *srci = xmalloc((size_t)comm_size * sizeof (*srci));
100
101 // compute size of local index lists
102 size_t src_pack_size = xt_idxlist_get_pack_size(src_idxlist_local, comm);
103 size_t dst_pack_size = xt_idxlist_get_pack_size(dst_idxlist_local, comm);
104 size_t size_sum = src_pack_size + dst_pack_size;
105
106 if (size_sum >= INT_MAX || size_sum < src_pack_size
107 || size_sum < dst_pack_size)
108 die("local src+dst index lists are too large");
109
110 int send_buffer_size = (int)size_sum;
111
112 // exchange buffer sizes
113 int *restrict pack_sizes
114 = xmalloc((size_t)comm_size * sizeof(*pack_sizes) * 2);
115
116 xt_mpi_call(MPI_Allgather(&send_buffer_size, 1, MPI_INT,
117 pack_sizes, 1, MPI_INT, comm), comm);
118
119 int *restrict displ = pack_sizes + comm_size;
120 unsigned recv_buffer_size = 0, size_overflow = 0;
121 for (size_t i = 0; i < (size_t)comm_size; ++i) {
122 displ[i] = (int)recv_buffer_size;
123 recv_buffer_size += (unsigned)pack_sizes[i];
124 size_overflow |= recv_buffer_size & (1U << (sizeof(int) * CHAR_BIT - 1));
125 }
126 if (size_overflow)
127 die("accumulated buffer sizes too big,"
128 " use distributed directory (xt_xmap_dist_dir_new)!");
129 void *recv_buffer = xmalloc((size_t)recv_buffer_size + size_sum),
130 *send_buffer = (unsigned char *)recv_buffer + (size_t)recv_buffer_size;
131 // pack local index lists
132 {
133 int position = 0;
134 xt_idxlist_pack(src_idxlist_local, send_buffer, send_buffer_size,
135 &position, comm);
136 xt_idxlist_pack(dst_idxlist_local, send_buffer, send_buffer_size,
137 &position, comm);
138 }
139 // exchange buffers
140 xt_mpi_call(MPI_Allgatherv(send_buffer, send_buffer_size, MPI_PACKED,
141 recv_buffer, pack_sizes, displ, MPI_PACKED,
142 comm), comm);
143
144 size_t dst_isect_count = 0, src_isect_count = 0;
145 int large_list_seen = 0;
146 // compute intersections
147 for (int i = 0; i < comm_size; ++i) {
148
149 int position = 0;
150 // unpack buffers unless local
151 Xt_idxlist src, dst;
152 if (is_inter || i != rank) {
153 src = xt_idxlist_unpack((unsigned char *)recv_buffer + displ[i],
154 pack_sizes[i], &position, comm);
155 dst = xt_idxlist_unpack((unsigned char *)recv_buffer + displ[i],
156 pack_sizes[i], &position, comm);
157 } else {
158 src = src_idxlist_local;
159 dst = dst_idxlist_local;
160 }
161 large_list_seen = large_list_seen
162 || (xt_idxlist_get_num_indices(src) > config->idxv_cnv_size)
163 || (xt_idxlist_get_num_indices(dst) > config->idxv_cnv_size);
164 Xt_idxlist intersect
165 = xt_idxlist_get_intersection_custom(src, dst_idxlist_local, config);
166 if (xt_idxlist_get_num_indices(intersect) > 0) {
167
168 dsti[dst_isect_count].list = intersect;
169 dsti[dst_isect_count].rank = i;
170 ++dst_isect_count;
171 }
172 else
173 xt_idxlist_delete(intersect);
174
175 intersect
176 = xt_idxlist_get_intersection_custom(src_idxlist_local, dst, config);
177 if (xt_idxlist_get_num_indices(intersect) > 0) {
178
179 srci[src_isect_count].list = intersect;
180 srci[src_isect_count].rank = i;
181 ++src_isect_count;
182 }
183 else
184 xt_idxlist_delete(intersect);
185 if (is_inter || i != rank) {
188 }
189 }
190
191 *stripify = large_list_seen;
192
193 free(recv_buffer);
194 free(pack_sizes);
195
196 /* minimize memory use of tables */
197 *num_src_intersections = src_isect_count;
198 srci = xrealloc(srci, src_isect_count * sizeof (**src_intersections));
199 *src_intersections = srci;
200
201 *num_dst_intersections = dst_isect_count;
202 dsti = xrealloc(dsti, dst_isect_count * sizeof (**dst_intersections));
203 *dst_intersections = dsti;
204}
205
208 MPI_Comm comm)
209{
210 return xt_xmap_all2all_custom_new(src_idxlist, dst_idxlist,
211 comm, &xt_default_config);
212}
213
216 MPI_Comm comm, Xt_config config) {
217 INSTR_DEF(t_xt_xmap_all2all_new,"xt_xmap_all2all_new")
218 INSTR_START(t_xt_xmap_all2all_new);
219
220 // ensure that yaxt is initialized
221 assert(xt_initialized());
222
223 int tag_offset;
224 MPI_Comm newcomm = xt_mpi_comm_smart_dup(comm, &tag_offset);
225
226 struct Xt_com_list * src_intersections = NULL, * dst_intersections = NULL;
227 size_t num_src_intersections, num_dst_intersections;
228
229 int stripify;
230 // exchange index lists between all processes in comm
231 exchange_idxlists(&src_intersections, &num_src_intersections,
232 &dst_intersections, &num_dst_intersections,
233 &stripify, src_idxlist, dst_idxlist, newcomm,
234 config);
235
236 Xt_xmap (*xmap_new)(int num_src_intersections,
237 const struct Xt_com_list *src_com,
238 int num_dst_intersections,
239 const struct Xt_com_list *dst_com,
240 Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist,
241 MPI_Comm comm)
243
244 Xt_xmap xmap = xmap_new((int)num_src_intersections, src_intersections,
245 (int)num_dst_intersections, dst_intersections,
246 src_idxlist, dst_idxlist, newcomm);
247
248 xt_mpi_comm_smart_dedup(&newcomm, tag_offset);
249 for (size_t i = 0; i < num_src_intersections; ++i)
250 if (src_intersections[i].list != NULL)
251 xt_idxlist_delete(src_intersections[i].list);
252 for (size_t i = 0; i < num_dst_intersections; ++i)
253 if (dst_intersections[i].list != NULL)
254 xt_idxlist_delete(dst_intersections[i].list);
255 free(src_intersections);
256 free(dst_intersections);
257 INSTR_STOP(t_xt_xmap_all2all_new);
258 return xmap;
259}
260
261/*
262 * Local Variables:
263 * c-basic-offset: 2
264 * coding: utf-8
265 * indent-tabs-mode: nil
266 * show-trailing-whitespace: t
267 * require-trailing-newline: t
268 * End:
269 */
int MPI_Comm
Definition core.h:64
#define die(msg)
Definition core.h:131
#define INSTR_STOP(T)
Definition instr.h:69
#define INSTR_DEF(T, S)
Definition instr.h:66
#define INSTR_START(T)
Definition instr.h:68
add versions of standard API functions not returning on error
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:71
#define xmalloc(size)
Definition ppm_xfuncs.h:70
Xt_idxlist list
Definition xt_core.h:154
struct Xt_config_ xt_default_config
Definition xt_config.c:203
implementation of configuration object
int xt_initialized(void)
struct Xt_xmap_ * Xt_xmap
Definition xt_core.h:85
index list declaration
Xt_idxlist xt_idxlist_unpack(void *buffer, int buffer_size, int *position, MPI_Comm comm)
void xt_idxlist_pack(Xt_idxlist idxlist, void *buffer, int buffer_size, int *position, MPI_Comm comm)
Definition xt_idxlist.c:86
size_t xt_idxlist_get_pack_size(Xt_idxlist idxlist, MPI_Comm comm)
Definition xt_idxlist.c:80
Xt_idxlist xt_idxlist_get_intersection_custom(Xt_idxlist idxlist_src, Xt_idxlist idxlist_dst, Xt_config config)
void xt_idxlist_delete(Xt_idxlist idxlist)
Definition xt_idxlist.c:75
Provide non-public declarations common to all index lists.
#define xt_idxlist_get_num_indices(idxlist)
MPI_Comm xt_mpi_comm_smart_dup(MPI_Comm comm, int *tag_offset)
Definition xt_mpi.c:333
void xt_mpi_comm_smart_dedup(MPI_Comm *comm, int tag_offset)
Definition xt_mpi.c:386
utility routines for MPI
#define xt_mpi_call(call, comm)
Definition xt_mpi.h:68
exchange map declarations
static void exchange_idxlists(struct Xt_com_list **src_intersections, size_t *num_src_intersections, struct Xt_com_list **dst_intersections, size_t *num_dst_intersections, int *stripify, Xt_idxlist src_idxlist_local, Xt_idxlist dst_idxlist_local, MPI_Comm comm, Xt_config config)
Xt_xmap xt_xmap_all2all_new(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
Xt_xmap xt_xmap_all2all_custom_new(Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm, Xt_config config)
Xt_xmap xt_xmap_intersection_ext_new(int num_src_intersections, const struct Xt_com_list src_com[num_src_intersections], int num_dst_intersections, const struct Xt_com_list dst_com[num_dst_intersections], Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)
Xt_xmap xt_xmap_intersection_new(int num_src_intersections, const struct Xt_com_list src_com[num_src_intersections], int num_dst_intersections, const struct Xt_com_list dst_com[num_dst_intersections], Xt_idxlist src_idxlist, Xt_idxlist dst_idxlist, MPI_Comm comm)