PaStiX Handbook  6.3.2
bvec_smpi_comm.c
Go to the documentation of this file.
1 /**
2  *
3  * @file bvec_smpi_comm.c
4  *
5  * Functions to communicate data between the processes when the right
6  * hand side permutation is done on distributed architectures.
7  *
8  * @copyright 2004-2023 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
9  * Univ. Bordeaux. All rights reserved.
10  *
11  * @version 6.3.2
12  * @author Alycia Lisito
13  * @date 2023-07-21
14  * @generated from /builds/solverstack/pastix/bcsc/bvec_zmpi_comm.c, normal z -> s, Wed Dec 13 12:09:46 2023
15  *
16  * This file implements the communication functions used in bvec_slapmr
17  * when MPI is used in replicated or distributed mode.
18  *
19  **/
20 #include "common.h"
21 #include <math.h>
22 #include "lapacke.h"
23 #include "bcsc/bcsc.h"
24 #include "bcsc/bvec.h"
25 #include "bcsc/bcsc_s.h"
26 #include "order/order_internal.h"
27 #include "cblas.h"
28 #include "blend/solver.h"
29 
30 #if defined( PASTIX_WITH_MPI )
31 /**
32  *******************************************************************************
33  *
34  * @ingroup bcsc_internal
35  *
36  * @brief Copies the received data in the right hand side b in the replicated
37  * case.
38  *
39  *******************************************************************************
40  *
41  * @param[in] pastix_data
42  * The pastix_data structure.
43  *
44  * @param[in] nrhs
45  * The number of columns in the right hand side b.
46  *
47  * @param[inout] b
48  * On entry the right hand side b not fully filled.
49  * At exit b is updated with the remote values.
50  *
51  * @param[in] ldb
52  * The leading dimension of b.
53  *
54  * @param[in] indexes
55  * The indexes array received.
56  *
57  * @param[in] values
58  * The values array received.
59  *
60  * @param[in] size_idx
61  * The size of indexes.
62  *
63  * @param[in] size_val
64  * The size of values.
65  *
66  *******************************************************************************
67  *
68  * @retval PASTIX_SUCCESS
69  *
70  *******************************************************************************/
71 static inline int
72 bvec_shandle_recv_backward_rep( pastix_data_t *pastix_data,
73  pastix_int_t nrhs,
74  float *b,
75  pastix_int_t ldb,
76  pastix_int_t *indexes,
77  float *values,
78  pastix_int_t size_idx,
79  pastix_int_t size_val )
80 {
81  const spmatrix_t *spm = pastix_data->csc;
82  pastix_int_t dof = spm->dof;
83  pastix_int_t *dofs = spm->dofs;
84  pastix_int_t ldval = size_val / nrhs ;
85  pastix_int_t ig, ige, idx, j, dofi, cnt;
86 
87  /* Checks if ldval is not rounded (there is no error on size_val). */
88  assert( nrhs * ldval == size_val );
89 
90  cnt = 0;
91  for ( idx = 0; idx < size_idx; idx++, indexes++, cnt += dofi ) {
92  ig = indexes[ 0 ];
93  ige = ( dof > 0 ) ? ig * dof : dofs[ig];
94  dofi = ( dof > 0 ) ? dof : dofs[ig+1] - dofs[ig];
95 
96  for ( j = 0; j < nrhs; j++ ) {
97  memcpy( b + ige + j * ldb, values + cnt + j * ldval, dofi * sizeof(float) );
98  }
99  }
100  return PASTIX_SUCCESS;
101 }
102 
103 /**
104  *******************************************************************************
105  *
106  * @ingroup bcsc_internal
107  *
108  * @brief Exchanges the data and copies the received data in the right hand
109  * side b in the replicated case.
110  *
111  *******************************************************************************
112  *
113  * @param[in] pastix_data
114  * The pastix_data structure.
115  *
116  * @param[in] nrhs
117  * The number of columns in the right hand side b.
118  *
119  * @param[inout] b
120  * The right hand side b ldb-by-nrhs.
121  *
122  * @param[in] ldb
123  * The leading dimension of b.
124  *
125  * @param[inout] rhs_comm
126  * The rhs_comm of the permuted right hand side initialised on entry,
127  * rhs_comm with the data exchanged at exit.
128  *
129  *******************************************************************************
130  *
131  * @retval PASTIX_SUCCESS
132  *
133  *******************************************************************************/
134 int
135 bvec_sexchange_data_rep( pastix_data_t *pastix_data,
136  pastix_int_t nrhs,
137  float *b,
138  pastix_int_t ldb,
139  pastix_rhs_t Pb )
140 {
141  bvec_handle_comm_t *rhs_comm = Pb->rhs_comm;
142  bvec_proc_comm_t *data_comm = rhs_comm->data_comm;
143  pastix_int_t clustnbr = rhs_comm->clustnbr;
144  pastix_int_t clustnum = rhs_comm->clustnum;
145  pastix_int_t *idx_buf = NULL;
146  float *val_buf = NULL;
147  bvec_data_amount_t *sends;
148  bvec_data_amount_t *recvs;
149  pastix_int_t c;
150 
151  /* Allocates the receiving indexes and values buffers. */
152  if ( rhs_comm->max_idx > 0 ) {
153  MALLOC_INTERN( idx_buf, rhs_comm->max_idx, pastix_int_t );
154  MALLOC_INTERN( val_buf, rhs_comm->max_val, float );
155  }
156 
157  for ( c = 0; c < clustnbr; c++ ) {
158  data_comm = rhs_comm->data_comm + c;
159  sends = &( data_comm->nsends );
160  recvs = &( data_comm->nrecvs );
161 
162  if ( c == clustnum ) {
163  /* Posts the emissions of the indexes and values. */
164  if ( sends->idxcnt > 0 ) {
165  MPI_Bcast( data_comm->send_idxbuf, sends->idxcnt, PASTIX_MPI_INT,
166  c, rhs_comm->comm );
167  MPI_Bcast( Pb->b, sends->valcnt, PASTIX_MPI_FLOAT,
168  c, rhs_comm->comm );
169  }
170  continue;
171  }
172 
173  /* Posts the receptions of the indexes and values. */
174  if ( ( rhs_comm->max_idx > 0 ) && ( recvs->idxcnt > 0 ) ) {
175  MPI_Bcast( idx_buf, recvs->idxcnt, PASTIX_MPI_INT, c, rhs_comm->comm );
176  MPI_Bcast( val_buf, recvs->valcnt, PASTIX_MPI_FLOAT, c, rhs_comm->comm );
177 
178  assert( recvs->idxcnt <= recvs->valcnt );
179  bvec_shandle_recv_backward_rep( pastix_data, nrhs, b, ldb, idx_buf, val_buf,
180  recvs->idxcnt, recvs->valcnt );
181  }
182  }
183 
184  /* Frees the receiving indexes and values buffers. */
185  if ( rhs_comm->max_idx > 0 ) {
186  memFree_null( idx_buf );
187  memFree_null( val_buf );
188  }
189 
190  return PASTIX_SUCCESS;
191 }
192 
193 /**
194  *******************************************************************************
195  *
196  * @ingroup bcsc
197  *
198  * @brief Allocates the sending buffers in rhs_comm->data_comm. These buffer
199  * are filled with the sending values.
200  *
201  *******************************************************************************
202  *
203  * @param[inout] rhs_comm
204  * On entry the rhs_comm of the permuted right hand side initialized.
205  * At exit the arrays of rhs_comm->data_comm->send are allocated.
206  *
207  *******************************************************************************
208  *
209  * @retval PASTIX_SUCCESS
210  *
211  *******************************************************************************/
212 int
213 bvec_sallocate_buf_dst( bvec_handle_comm_t *rhs_comm )
214 {
215  bvec_proc_comm_t *data_comm = NULL;
216  bvec_data_amount_t *sends = NULL;
217  pastix_int_t clustnbr = rhs_comm->clustnbr;
218  pastix_int_t clustnum = rhs_comm->clustnum;
219  pastix_int_t c;
220 
221  /* Sends the same amout of data to all process. */
222  for ( c = 0; c < clustnbr; c ++ ) {
223 
224  data_comm = rhs_comm->data_comm + c;
225  sends = &( data_comm->nsends );
226 
227  if ( c == clustnum ) {
228  continue;
229  }
230 
231  MALLOC_INTERN( data_comm->send_idxbuf, sends->idxcnt, pastix_int_t );
232  MALLOC_INTERN( data_comm->send_valbuf, sends->valcnt, float );
233 
234  }
235 
236  return PASTIX_SUCCESS;
237 }
238 
239 /**
240  *******************************************************************************
241  *
242  * @ingroup bcsc_internal
243  *
244  * @brief Copies the received data in the right hand side pb in the distributed
245  * case.
246  *
247  *******************************************************************************
248  *
249  * @param[in] pastix_data
250  * The pastix_data structure.
251  *
252  * @param[in] nrhs
253  * The number of columns in the right hand side pb.
254  *
255  * @param[inout] pb
256  * On entry the right hand side pb not fully filled.
257  * At exit pb is updated with the remote values.
258  *
259  * @param[in] ldpb
260  * The leading dimension of pb.
261  *
262  * @param[in] indexes
263  * The indexes array received.
264  *
265  * @param[in] values
266  * The values array received.
267  *
268  * @param[in] size_idx
269  * The size of indexes.
270  *
271  *******************************************************************************
272  *
273  * @retval PASTIX_SUCCESS
274  *
275  *******************************************************************************/
276 static inline int
277 bvec_shandle_recv_forward_dst( pastix_data_t *pastix_data,
278  pastix_int_t nrhs,
279  float *pb,
280  pastix_int_t ldpb,
281  const pastix_int_t *indexes,
282  const float *values,
283  pastix_int_t size_idx )
284 {
285  const spmatrix_t *spm = pastix_data->csc;
286  pastix_int_t dof = spm->dof;
287  pastix_int_t *dofs = spm->dofs;
288  pastix_int_t ig, ilpe, idx, j, dofi;
289 
290  for ( idx = 0; idx < size_idx; idx++, indexes++ ) {
291  ig = indexes[ 0 ];
292  ilpe = bvec_glob2Ploc( pastix_data, ig );
293  assert( ilpe >= 0 );
294  dofi = ( dof > 0 ) ? dof : dofs[ig+1] - dofs[ig];
295 
296  for ( j = 0; j < nrhs; j++, values += dofi ) {
297  memcpy( pb + ilpe + j * ldpb, values, dofi * sizeof(float) );
298  }
299  }
300  return PASTIX_SUCCESS;
301 }
302 
303 /**
304  *******************************************************************************
305  *
306  * @ingroup bcsc_internal
307  *
308  * @brief Copies the received data in the right hand side b in the distributed
309  * case.
310  *
311  *******************************************************************************
312  *
313  * @param[in] pastix_data
314  * The pastix_data structure.
315  *
316  * @param[in] nrhs
317  * The number of columns in the right hand side b.
318  *
319  * @param[inout] b
320  * On entry the right hand side b not fully filled.
321  * At exit b is updated with the remote values.
322  *
323  * @param[in] ldb
324  * The leading dimension of b.
325  *
326  * @param[in] glob2loc
327  * The glob2loc array associated to the user spm stored in pastix_data.
328  *
329  * @param[in] indexes
330  * The indexes array received.
331  *
332  * @param[in] values
333  * The values array received.
334  *
335  * @param[in] size_idx
336  * The size of indexes.
337  *
338  *******************************************************************************
339  *
340  * @retval PASTIX_SUCCESS
341  *
342  *******************************************************************************/
343 static inline int
344 bvec_shandle_recv_backward_dst( pastix_data_t *pastix_data,
345  pastix_int_t nrhs,
346  float *b,
347  pastix_int_t ldb,
348  const pastix_int_t *glob2loc,
349  const pastix_int_t *indexes,
350  const float *values,
351  pastix_int_t size_idx )
352 {
353  const spmatrix_t *spm = pastix_data->csc;
354  pastix_int_t dof = spm->dof;
355  pastix_int_t igp, ile, idx, j, dofi;
356 
357  dofi = dof; /* vdof incorrect */
358  for ( idx = 0; idx < size_idx; idx++, indexes++ ) {
359  igp = indexes[ 0 ];
360  ile = bvec_Pglob2loc( pastix_data, glob2loc, igp );
361  assert( ile >= 0 );
362 
363  for ( j = 0; j < nrhs; j++, values += dofi ) {
364  memcpy( b + ile + j * ldb, values, dofi * sizeof(float) );
365  }
366  }
367  return PASTIX_SUCCESS;
368 }
369 
370 /**
371  *******************************************************************************
372  *
373  * @ingroup bcsc_internal
374  *
375  * @brief Copies the received data in the right hand side b or pb in the
376  * distributed case.
377  *
378  *******************************************************************************
379  *
380  * @param[in] pastix_data
381  * The pastix_data structure.
382  *
383  * @param[in] dir
384  * The direction of the permutation.
385  * If PastixDirForward, b is permuted into Pb.
386  * If PastixDirBackward, Pb is permuted into b.
387  *
388  * @param[in] nrhs
389  * The number of columns in the right hand sides b and pb.
390  *
391  * @param[inout] b
392  * If dir == PastixDirForward:
393  * On entry the right hand side b not fully filled.
394  * At exit b is updated with the remote values.
395  * If dir == PastixDirBackward:
396  * b is not modified.
397  *
398  * @param[in] ldb
399  * The leading dimension of b.
400  *
401  * @param[inout] Pb
402  * If dir == PastixDirForward:
403  * On entry the structure of the permuted right hand side pb
404  * not fully filled.
405  * At exit pb is updated with the remote values.
406  * If dir == PastixDirBackward:
407  * Pb is not modified.
408  *
409  * @param[in] glob2loc
410  * The glob2loc array associated to the user spm stored in pastix_data.
411  *
412  * @param[in] indexes
413  * The indexes array received.
414  *
415  * @param[in] values
416  * The values array received.
417  *
418  * @param[in] size_idx
419  * The size of indexes.
420  *
421  *******************************************************************************
422  *
423  * @retval PASTIX_SUCCESS
424  *
425  *******************************************************************************/
426 static inline int
427 bvec_shandle_recv_dst( pastix_data_t *pastix_data,
428  pastix_dir_t dir,
429  pastix_int_t nrhs,
430  float *b,
431  pastix_int_t ldb,
432  pastix_rhs_t Pb,
433  const pastix_int_t *glob2loc,
434  const pastix_int_t *indexes,
435  const float *values,
436  pastix_int_t size_idx )
437 {
438  if ( dir == PastixDirForward ) {
439  bvec_shandle_recv_forward_dst( pastix_data, nrhs, Pb->b, Pb->ld, indexes, values, size_idx );
440  }
441  else {
442  bvec_shandle_recv_backward_dst( pastix_data, nrhs, b, ldb, glob2loc, indexes, values, size_idx );
443  }
444 
445  return PASTIX_SUCCESS;
446 }
447 
448 /**
449  *******************************************************************************
450  *
451  * @ingroup bcsc_internal
452  *
453  * @brief Exchanges the data and copies the received data in the right hand
454  * side b or pb in the distributed case.
455  *
456  *******************************************************************************
457  *
458  * @param[in] pastix_data
459  * The pastix_data structure.
460  *
461  * @param[in] dir
462  * The direction of the permutation.
463  * If PastixDirForward, b is permuted into Pb.
464  * If PastixDirBackward, Pb is permuted into b.
465  *
466  * @param[in] nrhs
467  * The number of columns in the right hand side b.
468  *
469  * @param[inout] b
470  * If dir == PastixDirForward:
471  * On entry the right hand side b not fully filled.
472  * At exit b is updated with the remote values.
473  * If dir == PastixDirBackward:
474  * b is not modified.
475  *
476  * @param[in] ldb
477  * The leading dimension of b.
478  *
479  * @param[inout] Pb
480  * If dir == PastixDirForward:
481  * On entry the structure of the permuted right hand side pb
482  * not fully filled.
483  * At exit pb is updated with the remote values.
484  * If dir == PastixDirBackward:
485  * Pb is not modified.
486  *
487  * @param[in] glob2loc
488  * The glob2loc array associated to the user spm stored in pastix_data.
489  *
490  *******************************************************************************
491  *
492  * @retval PASTIX_SUCCESS
493  *
494  *******************************************************************************/
495 int
496 bvec_sexchange_data_dst( pastix_data_t *pastix_data,
497  pastix_dir_t dir,
498  pastix_int_t nrhs,
499  float *b,
500  pastix_int_t ldb,
501  pastix_rhs_t Pb,
502  const pastix_int_t *glob2loc )
503 {
504  bvec_handle_comm_t *rhs_comm = Pb->rhs_comm;
505  bvec_proc_comm_t *data_comm = rhs_comm->data_comm;
506  pastix_int_t clustnbr = rhs_comm->clustnbr;
507  pastix_int_t clustnum = rhs_comm->clustnum;
508  pastix_int_t *idx_buf = NULL;
509  float *val_buf = NULL;
510  bvec_proc_comm_t *data_send = NULL;
511  bvec_proc_comm_t *data_recv = NULL;
512  pastix_int_t counter_req = 0;
513  MPI_Status statuses[(clustnbr-1)*2];
514  MPI_Request requests[(clustnbr-1)*2];
515  bvec_data_amount_t *sends, *recvs;
516  pastix_int_t c_send, c_recv, k;
517 
518  /* Allocates the receiving indexes and values buffers. */
519  if ( rhs_comm->max_idx > 0 ) {
520  MALLOC_INTERN( idx_buf, rhs_comm->max_idx, pastix_int_t );
521  MALLOC_INTERN( val_buf, rhs_comm->max_val, float );
522  }
523 
524  c_send = (clustnum+1) % clustnbr;
525  for ( k = 0; k < clustnbr-1; k++ ) {
526  data_send = data_comm + c_send;
527  sends = &( data_send->nsends );
528 
529  if ( c_send == clustnum ) {
530  continue;
531  }
532 
533  /* Posts the emissions of the indexes. */
534  if ( sends->idxcnt > 0 ) {
535  MPI_Isend( data_send->send_idxbuf, sends->idxcnt, PASTIX_MPI_INT, c_send,
536  PastixTagIndexes, rhs_comm->comm, &requests[counter_req++] );
537  MPI_Isend( data_send->send_valbuf, sends->valcnt, PASTIX_MPI_FLOAT, c_send,
538  PastixTagValues, rhs_comm->comm, &requests[counter_req++] );
539  }
540  c_send = (c_send+1) % clustnbr;
541  }
542 
543  c_recv = (clustnum-1+clustnbr) % clustnbr;
544  for ( k = 0; k < clustnbr-1; k++ ) {
545  data_recv = data_comm + c_recv;
546  recvs = &( data_recv->nrecvs );
547  /* Posts the receptions of the indexes and values. */
548  if ( ( rhs_comm->max_idx > 0 ) && ( recvs->idxcnt > 0 ) ) {
549  MPI_Recv( idx_buf, recvs->idxcnt, PASTIX_MPI_INT, c_recv, PastixTagIndexes,
550  rhs_comm->comm, MPI_STATUS_IGNORE );
551  MPI_Recv( val_buf, recvs->valcnt, PASTIX_MPI_FLOAT, c_recv, PastixTagValues,
552  rhs_comm->comm, MPI_STATUS_IGNORE );
553 
554  assert( recvs->idxcnt <= recvs->valcnt );
555  bvec_shandle_recv_dst( pastix_data, dir, nrhs, b, ldb, Pb, glob2loc,
556  idx_buf, val_buf, recvs->idxcnt );
557  }
558  c_recv = (c_recv-1+clustnbr) % clustnbr;
559  }
560 
561  MPI_Waitall( counter_req, requests, statuses );
562 
563  /* Frees the receiving indexes and values buffers. */
564  if ( rhs_comm->max_idx > 0 ) {
565  memFree_null( idx_buf );
566  memFree_null( val_buf );
567  }
568 
569  return PASTIX_SUCCESS;
570 }
571 #endif
BEGIN_C_DECLS typedef int pastix_int_t
Definition: datatypes.h:51
pastix_int_t max_idx
Definition: bvec.h:71
pastix_int_t valcnt
Definition: bvec.h:42
pastix_int_t max_val
Definition: bvec.h:72
pastix_int_t idxcnt
Definition: bvec.h:41
pastix_int_t * send_idxbuf
Definition: bvec.h:52
bvec_data_amount_t nrecvs
Definition: bvec.h:51
bvec_data_amount_t nsends
Definition: bvec.h:50
pastix_int_t clustnbr
Definition: bvec.h:67
void * send_valbuf
Definition: bvec.h:53
pastix_int_t clustnum
Definition: bvec.h:68
PASTIX_Comm comm
Definition: bvec.h:69
bvec_proc_comm_t data_comm[1]
Definition: bvec.h:73
Information about the amount of data exchanged to permute the pivots.
Definition: bvec.h:38
Structure to manage communications with distributed rhs.
Definition: bvec.h:66
Informations of the data exchanged with other processes.
Definition: bvec.h:49
enum pastix_dir_e pastix_dir_t
Direction.
@ PastixDirForward
Definition: api.h:513
@ PASTIX_SUCCESS
Definition: api.h:367
pastix_int_t ld
Definition: pastixdata.h:155
bvec_handle_comm_t * rhs_comm
Definition: pastixdata.h:158
const spmatrix_t * csc
Definition: pastixdata.h:89
Main PaStiX data structure.
Definition: pastixdata.h:67
Main PaStiX RHS structure.
Definition: pastixdata.h:150