YAC 3.13.0
Yet Another Coupler
Loading...
Searching...
No Matches
yac_xmap.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#ifdef HAVE_CONFIG_H
6#include "config.h"
7#endif
8
9#include <mpi.h>
10
11#include "yac_xmap.h"
12#include "ppm/ppm_xfuncs.h"
13#include "yac_assert.h"
14#include "yac_mpi_internal.h"
15
17 int count;
20 int rank;
21};
22
23struct yac_xmap_ {
24 MPI_Comm comm;
28};
29
31 int const * transfer_pos, size_t num_transfer_pos) {
32
33 int count = 0;
34 int * blocklengths = xmalloc(num_transfer_pos * sizeof(*blocklengths));
35 int * displacements = xmalloc(num_transfer_pos * sizeof(*displacements));
36
37 int prev_transfer_pos = transfer_pos[0];
38 for (size_t i = 0; i < num_transfer_pos; ++i) {
39 int curr_transfer_pos = transfer_pos[i];
40 if (curr_transfer_pos != prev_transfer_pos + 1) {
41 blocklengths[count] = 1;
42 displacements[count] = curr_transfer_pos;
44 count != INT_MAX,
45 "ERROR(parse_transfer_pos): number of elements exceeds INT_MAX");
46 ++count;
47 } else {
48 blocklengths[count-1]++;
49 }
50 prev_transfer_pos = curr_transfer_pos;
51 }
52
53 return
54 (struct yac_xmap_msg)
55 {.count = count,
56 .array_of_blocklengths =
57 xrealloc(blocklengths, (size_t)count * sizeof(*blocklengths)),
58 .array_of_displacements =
59 xrealloc(displacements, (size_t)count * sizeof(*displacements)),
60 .rank = -1};
61}
62
64 struct remote_point_infos * point_infos, size_t count, MPI_Comm comm) {
65
66 int comm_size;
67 yac_mpi_call(MPI_Comm_size(comm, &comm_size), comm);
68
69 size_t * sendcounts, * recvcounts, * sdispls, * rdispls;
71 1, &sendcounts, &recvcounts, &sdispls, &rdispls, comm);
72
73 for (size_t i = 0; i < count; ++i) {
74 struct remote_point_info * curr_info =
75 (point_infos[i].count > 1)?
76 (point_infos[i].data.multi):
77 (&(point_infos[i].data.single));
78 sendcounts[curr_info->rank]++;
79 }
80
82 1, sendcounts, recvcounts, sdispls, rdispls, comm);
83 size_t num_src_msg = 0, num_dst_msg = 0;
84 for (int i = 0; i < comm_size; ++i) {
85 num_src_msg += (recvcounts[i] > 0);
86 num_dst_msg += (sendcounts[i] > 0);
87 }
88
89 size_t recv_count =
90 rdispls[comm_size-1] + recvcounts[comm_size-1];
91
92 int * pos_buffer =
93 xmalloc((recv_count + 2 * count) * sizeof(*pos_buffer));
94 int * src_pos_buffer = pos_buffer;
95 int * dst_pos_buffer = pos_buffer + recv_count;
96 int * send_pos_buffer = pos_buffer + recv_count + count;
97
98 // pack send buffer
99 for (size_t i = 0; i < count; ++i) {
100 struct remote_point_info * curr_info =
101 (point_infos[i].count > 1)?
102 (point_infos[i].data.multi):
103 (&(point_infos[i].data.single));
104 size_t pos = sdispls[curr_info->rank+1]++;
105 dst_pos_buffer[pos] = i;
106 send_pos_buffer[pos] = (int)(curr_info->orig_pos);
107 }
108
109 // redistribute positions of requested data
110 yac_alltoallv_int_p2p(
111 send_pos_buffer, sendcounts, sdispls,
112 src_pos_buffer, recvcounts, rdispls, comm,
113 "yac_xmap_from_point_infos", __LINE__);
114
115 yac_xmap xmap =
116 xmalloc(
117 sizeof(*xmap) +
118 ((size_t)(num_src_msg + num_dst_msg)) * sizeof(xmap->msgs[0]));
119
120 xmap->comm = comm;
121 xmap->num_send_msg = num_src_msg;
122 xmap->num_recv_msg = num_dst_msg;
123 struct yac_xmap_msg * send_msgs = xmap->msgs;
124 struct yac_xmap_msg * recv_msgs = &(xmap->msgs[num_src_msg]);
125
126 // set transfer_pos pointers and transfer_pos counts in com_pos's
127 num_src_msg = 0;
128 num_dst_msg = 0;
129 for (int i = 0; i < comm_size; ++i) {
130 if (recvcounts[i] > 0) {
131 send_msgs[num_src_msg] =
132 parse_transfer_pos(src_pos_buffer, recvcounts[i]);
133 send_msgs[num_src_msg].rank = i;
134 src_pos_buffer += recvcounts[i];
135 ++num_src_msg;
136 }
137 if (sendcounts[i] > 0) {
138 recv_msgs[num_dst_msg] =
139 parse_transfer_pos(dst_pos_buffer, sendcounts[i]);
140 recv_msgs[num_dst_msg].rank = i;
141 dst_pos_buffer += sendcounts[i];
142 ++num_dst_msg;
143 }
144 }
145 yac_free_comm_buffers(sendcounts, recvcounts, sdispls, rdispls);
146
147 free(pos_buffer);
148
149 return xmap;
150}
151
153 struct Xt_redist_msg * msgs, size_t count, MPI_Comm comm) {
154 for (size_t i = 0; i < count; ++i) {
155 MPI_Datatype * dt = &(msgs[i].datatype);
156 if (*dt != MPI_DATATYPE_NULL) yac_mpi_call(MPI_Type_free(dt), comm);
157 }
158 free(msgs);
159}
160
161Xt_redist yac_xmap_generate_redist(yac_xmap xmap, MPI_Datatype base_type) {
162
163 size_t total_num_msg = (size_t)(xmap->num_send_msg + xmap->num_recv_msg);
164
165 struct Xt_redist_msg * msgs_buffer =
166 xmalloc(total_num_msg * sizeof(*msgs_buffer));
167
168 for (size_t i = 0; i < total_num_msg; ++i) {
169
170 MPI_Datatype msg_datatype;
172 MPI_Type_indexed(
173 xmap->msgs[i].count,
175 xmap->msgs[i].array_of_displacements, base_type, &msg_datatype),
176 xmap->comm);
177 xt_mpi_call(MPI_Type_commit(&msg_datatype), xmap->comm);
178
179 msgs_buffer[i].rank = xmap->msgs[i].rank;
180 msgs_buffer[i].datatype = msg_datatype;
181 }
182
183 Xt_config redist_config = xt_config_new();
184
185 Xt_redist redist =
186 xt_redist_single_array_base_custom_new(
187 xmap->num_send_msg, xmap->num_recv_msg,
188 msgs_buffer, msgs_buffer + xmap->num_send_msg, xmap->comm, redist_config);
189
190 xt_config_delete(redist_config);
191 xt_redist_msg_free(msgs_buffer, total_num_msg, xmap->comm);
192
193 return redist;
194}
195
197
198 for (int i = 0; i < (xmap->num_send_msg + xmap->num_recv_msg); ++i) {
199 free((void*)(xmap->msgs[i].array_of_blocklengths));
200 free((void*)(xmap->msgs[i].array_of_displacements));
201 }
202 free(xmap);
203}
#define YAC_ASSERT(exp, msg)
add versions of standard API functions not returning on error
#define xrealloc(ptr, size)
Definition ppm_xfuncs.h:67
#define xmalloc(size)
Definition ppm_xfuncs.h:66
single location information of a point
location information about a point that is located on one or
struct remote_point_info single
union remote_point_infos::@59 data
int num_send_msg
Definition yac_xmap.c:25
MPI_Comm comm
Definition yac_xmap.c:24
int num_recv_msg
Definition yac_xmap.c:26
struct yac_xmap_msg msgs[]
Definition yac_xmap.c:27
const int * array_of_blocklengths
Definition yac_xmap.c:18
const int * array_of_displacements
Definition yac_xmap.c:19
double * data
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
#define yac_mpi_call(call, comm)
yac_xmap yac_xmap_from_point_infos(struct remote_point_infos *point_infos, size_t count, MPI_Comm comm)
Definition yac_xmap.c:63
static struct yac_xmap_msg parse_transfer_pos(int const *transfer_pos, size_t num_transfer_pos)
Definition yac_xmap.c:30
void yac_xmap_delete(yac_xmap xmap)
Definition yac_xmap.c:196
static void xt_redist_msg_free(struct Xt_redist_msg *msgs, size_t count, MPI_Comm comm)
Definition yac_xmap.c:152
Xt_redist yac_xmap_generate_redist(yac_xmap xmap, MPI_Datatype base_type)
Definition yac_xmap.c:161