1 /*============================================================================
2 * \file Definition of a block distribution.
3 *============================================================================*/
4
5 /*
6 This file is part of Code_Saturne, a general-purpose CFD tool.
7
8 Copyright (C) 1998-2021 EDF S.A.
9
10 This program is free software; you can redistribute it and/or modify it under
11 the terms of the GNU General Public License as published by the Free Software
12 Foundation; either version 2 of the License, or (at your option) any later
13 version.
14
15 This program is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 details.
19
20 You should have received a copy of the GNU General Public License along with
21 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
22 Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25 /*----------------------------------------------------------------------------*/
26
27 #include "cs_defs.h"
28
29 /*----------------------------------------------------------------------------
30 * Standard C library headers
31 *----------------------------------------------------------------------------*/
32
33 #include <assert.h>
34 #include <errno.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38
39 /*----------------------------------------------------------------------------
40 * Local headers
41 *----------------------------------------------------------------------------*/
42
43 #include "bft_mem.h"
44 #include "bft_error.h"
45
46 /*----------------------------------------------------------------------------
47 * Header for the current file
48 *----------------------------------------------------------------------------*/
49
50 #include "cs_block_dist.h"
51
52 /*----------------------------------------------------------------------------*/
53
54 BEGIN_C_DECLS
55
56 /*! \cond DOXYGEN_SHOULD_SKIP_THIS */
57
58 /*=============================================================================
59 * Macro definitions
60 *============================================================================*/
61
62 /*=============================================================================
63 * Local type definitions
64 *============================================================================*/
65
66 /*============================================================================
67 * Local function defintions
68 *============================================================================*/
69
70 /*! (DOXYGEN_SHOULD_SKIP_THIS) \endcond */
71
72 /*============================================================================
73 * Public function definitions
74 *============================================================================*/
75
76 /*----------------------------------------------------------------------------*/
77 /*!
78 * \brief Compute block size and rank info for use with a block distribution.
79 *
80 * \param[in] rank_id id of local rank (ignored in serial mode)
81 * \param[in] n_ranks number of associated ranks
82 * \param[in] min_rank_step minimum rank step between blocks
83 * \param[in] min_block_size minimum number of entities per block
84 * \param[in] n_g_ents total number of associated entities
85 *
86 * \return block size and range info structure
87 */
88 /*----------------------------------------------------------------------------*/
89
90 cs_block_dist_info_t
cs_block_dist_compute_sizes(int rank_id,int n_ranks,int min_rank_step,cs_lnum_t min_block_size,cs_gnum_t n_g_ents)91 cs_block_dist_compute_sizes(int rank_id,
92 int n_ranks,
93 int min_rank_step,
94 cs_lnum_t min_block_size,
95 cs_gnum_t n_g_ents)
96 {
97 int _rank_id = rank_id;
98 cs_gnum_t _min_block_size = 1;
99 cs_gnum_t _block_size = 0;
100 cs_gnum_t _n_ranks = n_ranks;
101
102 cs_block_dist_info_t bi;
103
104 /* Special case: only 1 rank */
105
106 if (n_ranks == 1) {
107
108 bi.gnum_range[0] = 1;
109 bi.gnum_range[1] = n_g_ents + 1;
110 bi.n_ranks = 1;
111 bi.rank_step = 1;
112 bi.block_size = n_g_ents;
113
114 return bi;
115 }
116
117 /* Determine rank stepping if necessary */
118
119 assert(rank_id > -1);
120
121 bi.rank_step = 1;
122
123 if (min_block_size > 1)
124 _min_block_size = min_block_size;
125
126 if (bi.rank_step < min_rank_step) {
127 bi.rank_step = min_rank_step;
128 _n_ranks = n_ranks / bi.rank_step;
129 }
130 while ( n_g_ents/_n_ranks < _min_block_size
131 && _n_ranks > 1
132 && bi.rank_step < n_ranks) {
133 bi.rank_step *= 2;
134 _n_ranks = n_ranks / bi.rank_step;
135 }
136 if (n_ranks % bi.rank_step)
137 _n_ranks += 1;
138 if (bi.rank_step > n_ranks) {
139 bi.rank_step = n_ranks;
140 _n_ranks = 1;
141 }
142
143 if (rank_id % bi.rank_step == 0)
144 _rank_id = rank_id/bi.rank_step; /* non-empty block */
145 else
146 _rank_id = - (rank_id/bi.rank_step + 1); /* empty block on this rank */
147
148 /* Now determine block size and local range */
149
150 _block_size = n_g_ents / _n_ranks;
151
152 if (n_g_ents % _n_ranks)
153 _block_size += 1;
154
155 if (_rank_id > -1) {
156 int i;
157 for (i = 0; i < 2; i++) {
158 cs_gnum_t _g_rank = _rank_id + i;
159 bi.gnum_range[i] = _g_rank*_block_size + 1;
160 if (bi.gnum_range[i] > n_g_ents + 1)
161 bi.gnum_range[i] = n_g_ents + 1;
162 }
163 }
164 else {
165 int i;
166 cs_gnum_t _g_rank = -_rank_id;
167 for (i = 0; i < 2; i++) {
168 bi.gnum_range[i] = _g_rank*_block_size + 1;
169 if (bi.gnum_range[i] > n_g_ents + 1)
170 bi.gnum_range[i] = n_g_ents + 1;
171 }
172 }
173
174 bi.n_ranks = _n_ranks;
175 bi.block_size = _block_size;
176
177 return bi;
178 }
179
180 /*----------------------------------------------------------------------------*/
181 /*!
182 * \brief Compute block size and rank info for use with a block distribution
183 * for a new global number of entities with a given number of active
184 * ranks.
185 *
186 * \param[in] rank_id id of local rank (ignored in serial mode)
187 * \param[in] n_ranks number of associated ranks
188 * \param[in] n_block_ranks number of ranks associated with a block
189 * \param[in] n_g_ents total number of associated entities
190 *
191 * \return block size and range info structure
192 */
193 /*----------------------------------------------------------------------------*/
194
195 cs_block_dist_info_t
cs_block_dist_compute_sizes_nr(int rank_id,int n_ranks,int n_block_ranks,cs_gnum_t n_g_ents)196 cs_block_dist_compute_sizes_nr(int rank_id,
197 int n_ranks,
198 int n_block_ranks,
199 cs_gnum_t n_g_ents)
200 {
201 int _rank_id = rank_id;
202
203 cs_gnum_t _block_size = 0;
204 cs_gnum_t _n_ranks = n_ranks;
205
206 cs_block_dist_info_t bi;
207
208 /* Special case: only 1 rank */
209
210 if (n_ranks == 1) {
211
212 bi.gnum_range[0] = 1;
213 bi.gnum_range[1] = n_g_ents + 1;
214 bi.n_ranks = 1;
215 bi.rank_step = 1;
216 bi.block_size = n_g_ents;
217
218 return bi;
219 }
220
221 /* Determine rank stepping if necessary */
222
223 assert(rank_id > -1);
224
225 _block_size = 0;
226 _n_ranks = n_block_ranks;
227 bi.rank_step = n_ranks / n_block_ranks;
228
229 if (n_block_ranks < 1 || bi.rank_step > n_ranks) {
230 bi.rank_step = n_ranks;
231 _n_ranks = 1;
232 }
233 else if (bi.rank_step < 1) {
234 bi.rank_step = 1;
235 _n_ranks = n_ranks;
236 }
237
238 if (rank_id % bi.rank_step == 0)
239 _rank_id = rank_id/bi.rank_step; /* non-empty block */
240 else
241 _rank_id = - (rank_id/bi.rank_step + 1); /* empty block on this rank */
242
243 /* Now determine block size and local range */
244
245 _block_size = n_g_ents / _n_ranks;
246
247 if (n_g_ents % _n_ranks)
248 _block_size += 1;
249
250 if (_rank_id > -1) {
251 int i;
252 for (i = 0; i < 2; i++) {
253 cs_gnum_t _g_rank = _rank_id + i;
254 bi.gnum_range[i] = _g_rank*_block_size + 1;
255 if (bi.gnum_range[i] > n_g_ents + 1)
256 bi.gnum_range[i] = n_g_ents + 1;
257 }
258 }
259 else {
260 int i;
261 cs_gnum_t _g_rank = -_rank_id;
262 for (i = 0; i < 2; i++) {
263 bi.gnum_range[i] = _g_rank*_block_size + 1;
264 if (bi.gnum_range[i] > n_g_ents + 1)
265 bi.gnum_range[i] = n_g_ents + 1;
266 }
267 }
268
269 bi.n_ranks = _n_ranks;
270 bi.block_size = _block_size;
271
272 return bi;
273 }
274
275 /*----------------------------------------------------------------------------*/
276
277 END_C_DECLS
278