YAC 3.21.0
Yet Another Coupler
Loading...
Searching...
No Matches
duplicate_stencils.c
Go to the documentation of this file.
1// Copyright (c) 2024 The YAC Authors
2//
3// SPDX-License-Identifier: BSD-3-Clause
4
5#include <string.h>
6#include <mpi.h>
7
9#include "grids/basic_grid.h"
10#include "utils_common.h"
11#include "yac_mpi_internal.h"
12
19
20struct stencil_info {
22 size_t idx;
23 int rank;
24};
25
26static MPI_Datatype get_dup_info_mpi_datatype(MPI_Comm comm) {
27
28 struct dup_info dummy = {0};
29 MPI_Datatype dup_info_dt;
30 enum {NUM_MEMBERS = 4};
31 int array_of_blocklengths[NUM_MEMBERS] = {1, 1, 1, 1};
32 MPI_Aint array_of_displacements[NUM_MEMBERS];
33 {
34 MPI_Aint base_addr;
35 yac_mpi_call(MPI_Get_address(&dummy, &base_addr), comm);
37 MPI_Get_address(
38 &(dummy.orig_global_id),
39 &array_of_displacements[0]), comm);
40 array_of_displacements[0] -= base_addr;
42 MPI_Get_address(
43 &(dummy.duplicated_global_id),
44 &array_of_displacements[1]), comm);
45 array_of_displacements[1] -= base_addr;
47 MPI_Get_address(
48 &(dummy.duplicated_orig_pos),
49 &array_of_displacements[2]), comm);
50 array_of_displacements[2] -= base_addr;
52 MPI_Get_address(
53 &(dummy.duplicated_rank),
54 &array_of_displacements[3]), comm);
55 array_of_displacements[3] -= base_addr;
56 }
57 const MPI_Datatype array_of_types[NUM_MEMBERS] =
60 MPI_Type_create_struct(
61 NUM_MEMBERS, array_of_blocklengths, array_of_displacements,
62 array_of_types, &dup_info_dt), comm);
63 return yac_create_resized(dup_info_dt, sizeof(dummy), comm);
64}
65
66static MPI_Datatype get_stencil_info_mpi_datatype(MPI_Comm comm) {
67
68 struct stencil_info dummy = {0};
69 MPI_Datatype stencil_info_dt;
70 enum {NUM_MEMBERS = 3};
71 int array_of_blocklengths[NUM_MEMBERS] = {1, 1, 1};
72 MPI_Aint array_of_displacements[NUM_MEMBERS];
73 {
74 MPI_Aint base_addr;
75 yac_mpi_call(MPI_Get_address(&dummy, &base_addr), comm);
77 MPI_Get_address(
78 &(dummy.tgt_global_id), &array_of_displacements[0]), comm);
79 array_of_displacements[0] -= base_addr;
81 MPI_Get_address(
82 &(dummy.idx), &array_of_displacements[1]), comm);
83 array_of_displacements[1] -= base_addr;
85 MPI_Get_address(
86 &(dummy.rank), &array_of_displacements[2]), comm);
87 array_of_displacements[2] -= base_addr;
88 }
89 const MPI_Datatype array_of_types[NUM_MEMBERS] =
90 {yac_int_dt, YAC_MPI_SIZE_T, MPI_INT};
92 MPI_Type_create_struct(
93 NUM_MEMBERS, array_of_blocklengths, array_of_displacements,
94 array_of_types, &stencil_info_dt), comm);
95 return yac_create_resized(stencil_info_dt, sizeof(dummy), comm);
96}
97
99 const void * a, const void * b) {
100
101 return (((const struct dup_info *)a)->orig_global_id >
102 ((const struct dup_info *)b)->orig_global_id) -
103 (((const struct dup_info *)a)->orig_global_id <
104 ((const struct dup_info *)b)->orig_global_id);
105}
106
108 const void * a, const void * b) {
109
110 return (((const struct stencil_info *)a)->tgt_global_id >
111 ((const struct stencil_info *)b)->tgt_global_id) -
112 (((const struct stencil_info *)a)->tgt_global_id <
113 ((const struct stencil_info *)b)->tgt_global_id);
114}
115
116static inline int compute_bucket(yac_int value, int comm_size) {
117 return (int)(value / 128) % comm_size;
118}
119
121 struct yac_interp_weights * weights, struct yac_basic_grid * tgt_grid,
122 yac_int * tgt_orig_global_id, size_t * tgt_duplicated_idx,
123 size_t nbr_duplicated, enum yac_location location) {
124
125 char const * routine = "yac_duplicate_stencils";
126
127 yac_int * duplicated_global_ids =
128 xmalloc(nbr_duplicated * sizeof(*duplicated_global_ids));
129
131
133 (location == YAC_LOC_CELL) ||
135 (location == YAC_LOC_EDGE), "invalid location")
136
137 yac_int * point_ids;
138 switch (location) {
139 default:
140 case(YAC_LOC_CELL):
141 point_ids = grid_data->cell_ids;
142 break;
143 case(YAC_LOC_CORNER):
144 point_ids = grid_data->vertex_ids;
145 break;
146 case(YAC_LOC_EDGE):
147 point_ids = grid_data->edge_ids;
148 break;
149 };
150
151 // get global ids of all duplicated target cells
152 for (size_t i = 0; i < nbr_duplicated; ++i)
153 duplicated_global_ids[i] = point_ids[tgt_duplicated_idx[i]];
154
155 // get target global ids of all local stencils
156 size_t stencil_count = yac_interp_weights_get_interp_count(weights);
157 yac_int * stencil_tgt_ids =
159
160 MPI_Comm comm = yac_interp_weights_get_comm(weights);
161 int comm_rank, comm_size;
162 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
163 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
164
165 int * int_buffer =
166 xmalloc((nbr_duplicated + stencil_count) * sizeof(*int_buffer));
167 int * dup_dist_ranks = int_buffer;
168 int * stencil_dist_ranks = int_buffer + nbr_duplicated;
169
170 // determine the bucket ranks
171 for (size_t i = 0; i < nbr_duplicated; ++i)
172 dup_dist_ranks[i] = compute_bucket(tgt_orig_global_id[i], comm_size);
173 for (size_t i = 0; i < stencil_count; ++i)
174 stencil_dist_ranks[i] = compute_bucket(stencil_tgt_ids[i], comm_size);
175
176 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
178 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
179
180 // set up counts and displs for redistribution of information about
181 // duplicated points
182 for (size_t i = 0; i < nbr_duplicated; ++i)
183 sendcounts[dup_dist_ranks[i]]++;
185 1, sendcounts, recvcounts, sdispls, rdispls, comm);
186
187 size_t dup_info_count = recvcounts[comm_size - 1] + rdispls[comm_size - 1];
188 struct dup_info * dup_info_buffer =
189 xmalloc((nbr_duplicated + dup_info_count) * sizeof(*dup_info_buffer));
190 struct dup_info * dup_send_buffer = dup_info_buffer + dup_info_count;
191 struct dup_info * dup_recv_buffer = dup_info_buffer;
192
193 // pack information about duplicated points
194 for (size_t i = 0; i < nbr_duplicated; ++i) {
195 size_t pos = sdispls[dup_dist_ranks[i]+1]++;
196 dup_send_buffer[pos].orig_global_id = tgt_orig_global_id[i];
197 dup_send_buffer[pos].duplicated_global_id = duplicated_global_ids[i];
198 dup_send_buffer[pos].duplicated_orig_pos = tgt_duplicated_idx[i];
199 dup_send_buffer[pos].duplicated_rank = comm_rank;
200 }
201
202 // redistribute information about duplicated points
203 MPI_Datatype dup_info_dt = get_dup_info_mpi_datatype(comm);
204 yac_mpi_call(MPI_Type_commit(&dup_info_dt), comm);
206 dup_send_buffer, sendcounts, sdispls,
207 dup_recv_buffer, recvcounts, rdispls,
208 sizeof(*dup_send_buffer), dup_info_dt, comm, routine, __LINE__);
209 yac_mpi_call(MPI_Type_free(&dup_info_dt), comm);
210 dup_recv_buffer =
211 xrealloc(dup_recv_buffer, dup_info_count * sizeof(*dup_recv_buffer));
212 qsort(
213 dup_recv_buffer, dup_info_count, sizeof(*dup_recv_buffer),
215
216 // set up counts and displs for redistribution of stencil information
217 memset(sendcounts, 0, (size_t)comm_size * sizeof(*sendcounts));
218 for (size_t i = 0; i < stencil_count; ++i)
219 sendcounts[stencil_dist_ranks[i]]++;
221 1, sendcounts, recvcounts, sdispls, rdispls, comm);
222
223 size_t stencil_info_count = recvcounts[comm_size - 1] + rdispls[comm_size - 1];
224 struct stencil_info * stencil_info_buffer =
225 xmalloc((stencil_count + stencil_info_count) * sizeof(*stencil_info_buffer));
226 struct stencil_info * stencil_send_buffer =
227 stencil_info_buffer + stencil_info_count;
228 struct stencil_info * stencil_recv_buffer = stencil_info_buffer;
229
230 // pack stencil information
231 for (size_t i = 0; i < stencil_count; ++i) {
232 size_t pos = sdispls[stencil_dist_ranks[i]+1]++;
233 stencil_send_buffer[pos].tgt_global_id = stencil_tgt_ids[i];
234 stencil_send_buffer[pos].idx = i;
235 stencil_send_buffer[pos].rank = comm_rank;
236 }
237 free(stencil_tgt_ids);
238
239 // redistribute stencil information
240 MPI_Datatype stencil_info_dt = get_stencil_info_mpi_datatype(comm);
241 yac_mpi_call(MPI_Type_commit(&stencil_info_dt), comm);
243 stencil_send_buffer, sendcounts, sdispls,
244 stencil_recv_buffer, recvcounts, rdispls,
245 sizeof(*stencil_send_buffer), stencil_info_dt, comm, routine, __LINE__);
246 yac_mpi_call(MPI_Type_free(&stencil_info_dt), comm);
247 stencil_recv_buffer =
248 xrealloc(
249 stencil_recv_buffer, stencil_info_count * sizeof(*stencil_recv_buffer));
250 qsort(
251 stencil_recv_buffer, stencil_info_count, sizeof(*stencil_recv_buffer),
253
254 // count number of duplicated targets for which at least one stencil exists
255 // and the number of stencils that match with a duplicated points
256 size_t dup_match_count = 0;
257 size_t stencil_match_count = 0;
258 for (size_t i = 0, j = 0; i < dup_info_count; ++i) {
259 yac_int curr_orig_global_id = dup_recv_buffer[i].orig_global_id;
260 while ((j < stencil_info_count) &&
261 (stencil_recv_buffer[j].tgt_global_id < curr_orig_global_id)) ++j;
262 if ((j < stencil_info_count) &&
263 (stencil_recv_buffer[j].tgt_global_id == curr_orig_global_id))
264 ++dup_match_count;
265 size_t k = j;
266 while ((k < stencil_info_count) &&
267 (stencil_recv_buffer[k].tgt_global_id == curr_orig_global_id)) {
268 ++k;
269 ++stencil_match_count;
270 }
271 }
272
273 struct remote_points dup_remote_points;
274 dup_remote_points.data =
275 xmalloc(dup_match_count * sizeof(*(dup_remote_points.data)));
276 dup_remote_points.count = dup_match_count;
277 size_t * num_stencils_per_tgt =
278 xmalloc(stencil_match_count * sizeof(*num_stencils_per_tgt));
279 size_t * stencil_indices =
280 xmalloc(stencil_match_count * sizeof(*stencil_indices));
281 int * stencil_ranks =
282 xmalloc(stencil_match_count * sizeof(*stencil_ranks));
283 double * w = xmalloc(stencil_match_count * sizeof(*w));
284
285 // match duplicated targets with stencils
286 dup_match_count = 0;
287 stencil_match_count = 0;
288 for (size_t i = 0, j = 0; i < dup_info_count; ++i) {
289 yac_int curr_orig_global_id = dup_recv_buffer[i].orig_global_id;
290
291 // search for a matching stencil
292 while ((j < stencil_info_count) &&
293 (stencil_recv_buffer[j].tgt_global_id < curr_orig_global_id)) ++j;
294
295 // if we found a matching stencil
296 if ((j < stencil_info_count) &&
297 (stencil_recv_buffer[j].tgt_global_id == curr_orig_global_id)) {
298
299 size_t curr_num_stencils_per_tgt = 0;
300
301 // for the current duplicated point -> get all matching stencils
302 size_t k = j;
303 while ((k < stencil_info_count) &&
304 (stencil_recv_buffer[k].tgt_global_id == curr_orig_global_id)) {
305 stencil_indices[stencil_match_count] = stencil_recv_buffer[k].idx;
306 stencil_ranks[stencil_match_count] = stencil_recv_buffer[k].rank;
307 w[stencil_match_count] = 1.0;
308 ++k;
309 ++stencil_match_count;
310 ++curr_num_stencils_per_tgt;
311 }
312
313 dup_remote_points.data[dup_match_count].global_id =
314 dup_recv_buffer[i].duplicated_global_id;
315 dup_remote_points.data[dup_match_count].data.count = 1;
316 dup_remote_points.data[dup_match_count].data.data.single.rank =
317 dup_recv_buffer[i].duplicated_rank;
318 dup_remote_points.data[dup_match_count].data.data.single.orig_pos =
319 (uint64_t)(dup_recv_buffer[i].duplicated_orig_pos);
320 num_stencils_per_tgt[dup_match_count] = curr_num_stencils_per_tgt;
321 ++dup_match_count;
322 }
323 }
324
325 // duplicate stencils
327 weights, &dup_remote_points, num_stencils_per_tgt,
328 stencil_indices, stencil_ranks, w);
329
330 // clean up
331 free(w);
332 free(stencil_ranks);
333 free(stencil_indices);
334 free(num_stencils_per_tgt);
335 free(stencil_recv_buffer);
336 free(dup_remote_points.data);
337 free(dup_recv_buffer);
338 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
339 free(int_buffer);
340 free(duplicated_global_ids);
341}
342
344 struct yac_interp_weights * weights, struct yac_basic_grid * tgt_grid,
345 yac_int * tgt_orig_global_id, size_t * tgt_duplicated_idx,
346 size_t nbr_duplicated, int location) {
347
349 weights, tgt_grid, tgt_orig_global_id, tgt_duplicated_idx,
350 nbr_duplicated, yac_get_location(location));
351}
#define YAC_ASSERT(exp, msg)
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:137
static MPI_Datatype get_stencil_info_mpi_datatype(MPI_Comm comm)
static MPI_Datatype get_dup_info_mpi_datatype(MPI_Comm comm)
static int compute_bucket(yac_int value, int comm_size)
static int compare_stencil_info_tgt_global_id(const void *a, const void *b)
void yac_duplicate_stencils(struct yac_interp_weights *weights, struct yac_basic_grid *tgt_grid, yac_int *tgt_orig_global_id, size_t *tgt_duplicated_idx, size_t nbr_duplicated, enum yac_location location)
void yac_duplicate_stencils_f2c(struct yac_interp_weights *weights, struct yac_basic_grid *tgt_grid, yac_int *tgt_orig_global_id, size_t *tgt_duplicated_idx, size_t nbr_duplicated, int location)
static int compare_dup_info_orig_global_ids(const void *a, const void *b)
struct @23::@24 value
void yac_interp_weights_wcopy_weights(struct yac_interp_weights *weights, struct remote_points *tgts, size_t *num_stencils_per_tgt, size_t *stencil_indices, int *stencil_ranks, double *w)
yac_int * yac_interp_weights_get_interp_tgt(struct yac_interp_weights *weights)
MPI_Comm yac_interp_weights_get_comm(struct yac_interp_weights *weights)
size_t yac_interp_weights_get_interp_count(struct yac_interp_weights *weights)
enum yac_location yac_get_location(int const location)
Definition location.c:45
yac_location
Definition location.h:12
@ YAC_LOC_CORNER
Definition location.h:15
@ YAC_LOC_EDGE
Definition location.h:16
@ YAC_LOC_CELL
Definition location.h:14
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xmalloc(size)
Definition ppm_xfuncs.h:66
size_t duplicated_orig_pos
yac_int duplicated_global_id
yac_int orig_global_id
union remote_point_infos::@53 data
struct remote_point_info single
yac_int global_id
struct remote_point_infos data
structure containing the information (global id and location)
struct remote_point * data
int const * location
void yac_generate_alltoallv_args(int count, size_t const *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls, MPI_Comm comm)
Definition yac_mpi.c:583
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:639
void yac_get_comm_buffers(int count, size_t **sendcounts, size_t **recvcounts, size_t **sdispls, size_t **rdispls, MPI_Comm comm)
Definition yac_mpi.c:608
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:562
void yac_alltoallv_p2p(void const *send_buffer, size_t const *sendcounts, size_t const *sdispls, void *recv_buffer, size_t const *recvcounts, size_t const *rdispls, size_t dt_size, MPI_Datatype dt, MPI_Comm comm, char const *caller, int line)
Definition yac_mpi.c:129
#define yac_mpi_call(call, comm)
#define YAC_MPI_SIZE_T
YAC_INT yac_int
Definition yac_types.h:15
#define yac_int_dt
Definition yac_types.h:18