YAC 3.13.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;
29 MPI_Datatype dup_info_dt;
30 int array_of_blocklengths[] = {1, 1, 1, 1};
31 const MPI_Aint array_of_displacements[] =
32 {(MPI_Aint)(intptr_t)(const void *)&(dummy.orig_global_id) -
33 (MPI_Aint)(intptr_t)(const void *)&dummy,
34 (MPI_Aint)(intptr_t)(const void *)&(dummy.duplicated_global_id) -
35 (MPI_Aint)(intptr_t)(const void *)&dummy,
36 (MPI_Aint)(intptr_t)(const void *)&(dummy.duplicated_orig_pos) -
37 (MPI_Aint)(intptr_t)(const void *)&dummy,
38 (MPI_Aint)(intptr_t)(const void *)&(dummy.duplicated_rank) -
39 (MPI_Aint)(intptr_t)(const void *)&dummy};
40 const MPI_Datatype array_of_types[] =
43 MPI_Type_create_struct(4, array_of_blocklengths, array_of_displacements,
44 array_of_types, &dup_info_dt), comm);
45 return yac_create_resized(dup_info_dt, sizeof(dummy), comm);
46}
47
48static MPI_Datatype get_stencil_info_mpi_datatype(MPI_Comm comm) {
49
50 struct stencil_info dummy;
51 MPI_Datatype stencil_info_dt;
52 int array_of_blocklengths[] = {1, 1, 1};
53 const MPI_Aint array_of_displacements[] =
54 {(MPI_Aint)(intptr_t)(const void *)&(dummy.tgt_global_id) -
55 (MPI_Aint)(intptr_t)(const void *)&dummy,
56 (MPI_Aint)(intptr_t)(const void *)&(dummy.idx) -
57 (MPI_Aint)(intptr_t)(const void *)&dummy,
58 (MPI_Aint)(intptr_t)(const void *)&(dummy.rank) -
59 (MPI_Aint)(intptr_t)(const void *)&dummy};
60 const MPI_Datatype array_of_types[] =
61 {yac_int_dt, YAC_MPI_SIZE_T, MPI_INT};
63 MPI_Type_create_struct(3, array_of_blocklengths, array_of_displacements,
64 array_of_types, &stencil_info_dt), comm);
65 return yac_create_resized(stencil_info_dt, sizeof(dummy), comm);
66}
67
69 const void * a, const void * b) {
70
71 return (((const struct dup_info *)a)->orig_global_id >
72 ((const struct dup_info *)b)->orig_global_id) -
73 (((const struct dup_info *)a)->orig_global_id <
74 ((const struct dup_info *)b)->orig_global_id);
75}
76
78 const void * a, const void * b) {
79
80 return (((const struct stencil_info *)a)->tgt_global_id >
81 ((const struct stencil_info *)b)->tgt_global_id) -
82 (((const struct stencil_info *)a)->tgt_global_id <
83 ((const struct stencil_info *)b)->tgt_global_id);
84}
85
86static inline int compute_bucket(yac_int value, int comm_size) {
87 return (int)(value / 128) % comm_size;
88}
89
91 struct yac_interp_weights * weights, struct yac_basic_grid * tgt_grid,
92 yac_int * tgt_orig_global_id, size_t * tgt_duplicated_idx,
93 size_t nbr_duplicated, enum yac_location location) {
94
95 char const * routine = "yac_duplicate_stencils";
96
97 yac_int * duplicated_global_ids =
98 xmalloc(nbr_duplicated * sizeof(*duplicated_global_ids));
99
101
103 (location == YAC_LOC_CELL) ||
106 "ERROR(%s): invalid location", routine)
107
108 yac_int * point_ids;
109 switch (location) {
110 default:
111 case(YAC_LOC_CELL):
112 point_ids = grid_data->cell_ids;
113 break;
114 case(YAC_LOC_CORNER):
115 point_ids = grid_data->vertex_ids;
116 break;
117 case(YAC_LOC_EDGE):
118 point_ids = grid_data->edge_ids;
119 break;
120 };
121
122 // get global ids of all duplicated target cells
123 for (size_t i = 0; i < nbr_duplicated; ++i)
124 duplicated_global_ids[i] = point_ids[tgt_duplicated_idx[i]];
125
126 // get target global ids of all local stencils
127 size_t stencil_count = yac_interp_weights_get_interp_count(weights);
128 yac_int * stencil_tgt_ids =
130
131 MPI_Comm comm = yac_interp_weights_get_comm(weights);
132 int comm_rank, comm_size;
133 yac_mpi_call(MPI_Comm_rank(comm, &comm_rank), comm);
134 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
135
136 int * int_buffer =
137 xmalloc((nbr_duplicated + stencil_count) * sizeof(*int_buffer));
138 int * dup_dist_ranks = int_buffer;
139 int * stencil_dist_ranks = int_buffer + nbr_duplicated;
140
141 // determine the bucket ranks
142 for (size_t i = 0; i < nbr_duplicated; ++i)
143 dup_dist_ranks[i] = compute_bucket(tgt_orig_global_id[i], comm_size);
144 for (size_t i = 0; i < stencil_count; ++i)
145 stencil_dist_ranks[i] = compute_bucket(stencil_tgt_ids[i], comm_size);
146
147 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
149 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
150
151 // set up counts and displs for redistribution of information about
152 // duplicated points
153 for (size_t i = 0; i < nbr_duplicated; ++i)
154 sendcounts[dup_dist_ranks[i]]++;
156 1, sendcounts, recvcounts, sdispls, rdispls, comm);
157
158 size_t dup_info_count = recvcounts[comm_size - 1] + rdispls[comm_size - 1];
159 struct dup_info * dup_info_buffer =
160 xmalloc((nbr_duplicated + dup_info_count) * sizeof(*dup_info_buffer));
161 struct dup_info * dup_send_buffer = dup_info_buffer + dup_info_count;
162 struct dup_info * dup_recv_buffer = dup_info_buffer;
163
164 // pack information about duplicated points
165 for (size_t i = 0; i < nbr_duplicated; ++i) {
166 size_t pos = sdispls[dup_dist_ranks[i]+1]++;
167 dup_send_buffer[pos].orig_global_id = tgt_orig_global_id[i];
168 dup_send_buffer[pos].duplicated_global_id = duplicated_global_ids[i];
169 dup_send_buffer[pos].duplicated_orig_pos = tgt_duplicated_idx[i];
170 dup_send_buffer[pos].duplicated_rank = comm_rank;
171 }
172
173 // redistribute information about duplicated points
174 MPI_Datatype dup_info_dt = get_dup_info_mpi_datatype(comm);
175 yac_mpi_call(MPI_Type_commit(&dup_info_dt), comm);
177 dup_send_buffer, sendcounts, sdispls,
178 dup_recv_buffer, recvcounts, rdispls,
179 sizeof(*dup_send_buffer), dup_info_dt, comm, routine, __LINE__);
180 yac_mpi_call(MPI_Type_free(&dup_info_dt), comm);
181 dup_recv_buffer =
182 xrealloc(dup_recv_buffer, dup_info_count * sizeof(*dup_recv_buffer));
183 qsort(
184 dup_recv_buffer, dup_info_count, sizeof(*dup_recv_buffer),
186
187 // set up counts and displs for redistribution of stencil information
188 memset(sendcounts, 0, (size_t)comm_size * sizeof(*sendcounts));
189 for (size_t i = 0; i < stencil_count; ++i)
190 sendcounts[stencil_dist_ranks[i]]++;
192 1, sendcounts, recvcounts, sdispls, rdispls, comm);
193
194 size_t stencil_info_count = recvcounts[comm_size - 1] + rdispls[comm_size - 1];
195 struct stencil_info * stencil_info_buffer =
196 xmalloc((stencil_count + stencil_info_count) * sizeof(*stencil_info_buffer));
197 struct stencil_info * stencil_send_buffer =
198 stencil_info_buffer + stencil_info_count;
199 struct stencil_info * stencil_recv_buffer = stencil_info_buffer;
200
201 // pack stencil information
202 for (size_t i = 0; i < stencil_count; ++i) {
203 size_t pos = sdispls[stencil_dist_ranks[i]+1]++;
204 stencil_send_buffer[pos].tgt_global_id = stencil_tgt_ids[i];
205 stencil_send_buffer[pos].idx = i;
206 stencil_send_buffer[pos].rank = comm_rank;
207 }
208 free(stencil_tgt_ids);
209
210 // redistribute stencil information
211 MPI_Datatype stencil_info_dt = get_stencil_info_mpi_datatype(comm);
212 yac_mpi_call(MPI_Type_commit(&stencil_info_dt), comm);
214 stencil_send_buffer, sendcounts, sdispls,
215 stencil_recv_buffer, recvcounts, rdispls,
216 sizeof(*stencil_send_buffer), stencil_info_dt, comm, routine, __LINE__);
217 yac_mpi_call(MPI_Type_free(&stencil_info_dt), comm);
218 stencil_recv_buffer =
219 xrealloc(
220 stencil_recv_buffer, stencil_info_count * sizeof(*stencil_recv_buffer));
221 qsort(
222 stencil_recv_buffer, stencil_info_count, sizeof(*stencil_recv_buffer),
224
225 // count number of duplicated targets for which at least one stencil exists
226 // and the number of stencils that match with a duplicated points
227 size_t dup_match_count = 0;
228 size_t stencil_match_count = 0;
229 for (size_t i = 0, j = 0; i < dup_info_count; ++i) {
230 yac_int curr_orig_global_id = dup_recv_buffer[i].orig_global_id;
231 while ((j < stencil_info_count) &&
232 (stencil_recv_buffer[j].tgt_global_id < curr_orig_global_id)) ++j;
233 if ((j < stencil_info_count) &&
234 (stencil_recv_buffer[j].tgt_global_id == curr_orig_global_id))
235 ++dup_match_count;
236 size_t k = j;
237 while ((k < stencil_info_count) &&
238 (stencil_recv_buffer[k].tgt_global_id == curr_orig_global_id)) {
239 ++k;
240 ++stencil_match_count;
241 }
242 }
243
244 struct remote_points dup_remote_points;
245 dup_remote_points.data =
246 xmalloc(dup_match_count * sizeof(*(dup_remote_points.data)));
247 dup_remote_points.count = dup_match_count;
248 size_t * num_stencils_per_tgt =
249 xmalloc(stencil_match_count * sizeof(*num_stencils_per_tgt));
250 size_t * stencil_indices =
251 xmalloc(stencil_match_count * sizeof(*stencil_indices));
252 int * stencil_ranks =
253 xmalloc(stencil_match_count * sizeof(*stencil_ranks));
254 double * w = xmalloc(stencil_match_count * sizeof(*w));
255
256 // match duplicated targets with stencils
257 dup_match_count = 0;
258 stencil_match_count = 0;
259 for (size_t i = 0, j = 0; i < dup_info_count; ++i) {
260 yac_int curr_orig_global_id = dup_recv_buffer[i].orig_global_id;
261
262 // search for a matching stencil
263 while ((j < stencil_info_count) &&
264 (stencil_recv_buffer[j].tgt_global_id < curr_orig_global_id)) ++j;
265
266 // if we found a matching stencil
267 if ((j < stencil_info_count) &&
268 (stencil_recv_buffer[j].tgt_global_id == curr_orig_global_id)) {
269
270 size_t curr_num_stencils_per_tgt = 0;
271
272 // for the current duplicated point -> get all matching stencils
273 size_t k = j;
274 while ((k < stencil_info_count) &&
275 (stencil_recv_buffer[k].tgt_global_id == curr_orig_global_id)) {
276 stencil_indices[stencil_match_count] = stencil_recv_buffer[k].idx;
277 stencil_ranks[stencil_match_count] = stencil_recv_buffer[k].rank;
278 w[stencil_match_count] = 1.0;
279 ++k;
280 ++stencil_match_count;
281 ++curr_num_stencils_per_tgt;
282 }
283
284 dup_remote_points.data[dup_match_count].global_id =
285 dup_recv_buffer[i].duplicated_global_id;
286 dup_remote_points.data[dup_match_count].data.count = 1;
287 dup_remote_points.data[dup_match_count].data.data.single.rank =
288 dup_recv_buffer[i].duplicated_rank;
289 dup_remote_points.data[dup_match_count].data.data.single.orig_pos =
290 (uint64_t)(dup_recv_buffer[i].duplicated_orig_pos);
291 num_stencils_per_tgt[dup_match_count] = curr_num_stencils_per_tgt;
292 ++dup_match_count;
293 }
294 }
295
296 // duplicate stencils
298 weights, &dup_remote_points, num_stencils_per_tgt,
299 stencil_indices, stencil_ranks, w);
300
301 // clean up
302 free(w);
303 free(stencil_ranks);
304 free(stencil_indices);
305 free(num_stencils_per_tgt);
306 free(stencil_recv_buffer);
307 free(dup_remote_points.data);
308 free(dup_recv_buffer);
309 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
310 free(int_buffer);
311 free(duplicated_global_ids);
312}
313
315 struct yac_interp_weights * weights, struct yac_basic_grid * tgt_grid,
316 yac_int * tgt_orig_global_id, size_t * tgt_duplicated_idx,
317 size_t nbr_duplicated, int location) {
318
320 weights, tgt_grid, tgt_orig_global_id, tgt_duplicated_idx,
321 nbr_duplicated, yac_get_location(location));
322}
struct yac_basic_grid_data * yac_basic_grid_get_data(struct yac_basic_grid *grid)
Definition basic_grid.c:140
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 @34::@35 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
struct remote_point_info single
union remote_point_infos::@59 data
yac_int global_id
struct remote_point_infos data
structure containing the information (global id and location)
struct remote_point * data
int const * location
#define YAC_ASSERT_F(exp, format,...)
Definition yac_assert.h:19
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:578
void yac_free_comm_buffers(size_t *sendcounts, size_t *recvcounts, size_t *sdispls, size_t *rdispls)
Definition yac_mpi.c:634
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:603
MPI_Datatype yac_create_resized(MPI_Datatype dt, size_t new_size, MPI_Comm comm)
Definition yac_mpi.c:557
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:132
#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