PaStiX Handbook  6.3.2
extracblk.c
Go to the documentation of this file.
1 /**
2  *
3  * @file extracblk.c
4  *
5  * PaStiX analyse headers for extra symbolic structure functions.
6  *
7  * @copyright 1998-2023 Bordeaux INP, CNRS (LaBRI UMR 5800), Inria,
8  * Univ. Bordeaux. All rights reserved.
9  *
10  * @version 6.3.2
11  * @author Mathieu Faverge
12  * @author Gregoire Pichon
13  * @date 2023-08-28
14  *
15  * @addtogroup blend_dev_split
16  * @{
17  *
18  **/
19 #include "common.h"
20 #include "symbol/symbol.h"
21 #include "cost.h"
22 #include "elimintree.h"
23 #include "cand.h"
24 #include "extracblk.h"
25 
26 /**
27  *******************************************************************************
28  *
29  * @brief Allocate the extracblk structure.
30  *
31  *******************************************************************************
32  *
33  * @param[inout] extracblk
34  * Allocate memory space to store extra cblk when they are created. The
35  * initial number is the one given at extraCblkInit().
36  *
37  *******************************************************************************/
38 static inline void
40 {
41  pastix_int_t i;
42 
43  MALLOC_INTERN( extracblk->sptcblk, extracblk->cblknbr, pastix_int_t );
44  MALLOC_INTERN( extracblk->sptcbnb, extracblk->cblknbr, pastix_int_t );
45 
46  /*
47  * Unsplitted cblk will keep sptcblk to -1 and sptcbnb to 1
48  * Splitted cblk will have sptcbnb to the number of cblk replacing the original one,
49  * and sptcblk will contain the cblktab index of the first generated cblk
50  */
51  for(i=0; i<extracblk->cblknbr;i++)
52  {
53  extracblk->sptcblk[i] = -1;
54  extracblk->sptcbnb[i] = 1;
55  }
56 
57  /* We choose an arbitrary size for initial allocation of bloktab and cblktab (5%) */
58  extracblk->sizcblk = ( extracblk->cblknbr + 20 ) / 20;
59  MALLOC_INTERN( extracblk->cblktab, extracblk->cblknbr, symbol_cblk_t );
60 
61  return;
62 }
63 
64 /**
65  *******************************************************************************
66  *
67  * @brief Increment the number of extra cblk that can be stored.
68  *
69  * If there is not enough space, the structure is reallocated to a larger space.
70  *
71  *******************************************************************************
72  *
73  * @param[inout] extracblk
74  * Allocate memory space to store extra cblk when they are created. The
75  * initial number is the one given at extraCblkInit().
76  *
77  *******************************************************************************
78  *
79  * @return the current index for the next cblk added to the structure.
80  *
81  *******************************************************************************/
82 static inline pastix_int_t
84 {
85  /* First cblk added */
86  if ( extracblk->sizcblk == 0 ) {
87  extraCblkAlloc( extracblk );
88  }
89 
90  extracblk->curcblk++;
91 
92  /* Check that we have enough space and make it bigger if required */
93  if( extracblk->curcblk >= extracblk->sizcblk )
94  {
95  /* Add 5% of original cblknbr to the cblktab */
96  pastix_int_t extrasize = (extracblk->cblknbr + 20 ) / 20;
97  symbol_cblk_t *tmp;
98 
99  assert( extracblk->curcblk == extracblk->sizcblk);
100  tmp = extracblk->cblktab;
101  extracblk->sizcblk += extrasize;
102 
103  MALLOC_INTERN( extracblk->cblktab, extracblk->sizcblk, symbol_cblk_t );
104  memcpy(extracblk->cblktab, tmp, sizeof(symbol_cblk_t)*extracblk->curcblk);
105 
106  memFree_null(tmp);
107  }
108 
109  return extracblk->curcblk;
110 }
111 
112 /**
113  *******************************************************************************
114  *
115  * @brief Initialize the extracblk structure.
116  *
117  *******************************************************************************
118  *
119  * @param[in] cblknbr
120  * The starting number of cblk that the structure can hold.
121  *
122  * @param[inout] extracblk
123  * Pointer to the allocated extracblk structure to initialize.
124  *
125  *******************************************************************************/
126 void
128  ExtraCblk_t *extracblk )
129 {
130  extracblk->cblknbr = cblknbr;
131  extracblk->addcblk = 0;
132  extracblk->addblok = 0;
133  extracblk->addblof = 0;
134  extracblk->sptcblk = NULL;
135  extracblk->sptcbnb = NULL;
136  extracblk->curcblk = -1;
137  extracblk->sizcblk = 0;
138  extracblk->cblktab = NULL;
139  return;
140 }
141 
142 /**
143  *******************************************************************************
144  *
145  * @brief Free the extracblk structure.
146  *
147  *******************************************************************************
148  *
149  * @param[inout] extracblk
150  * Pointer to the allocated extracblk structure to free.
151  *
152  *******************************************************************************/
153 void
155 {
156  if ( extracblk->sizcblk > 0 ) {
157  memFree_null( extracblk->sptcblk );
158  memFree_null( extracblk->sptcbnb );
159  memFree_null( extracblk->cblktab );
160  }
161  extracblk->curcblk = -1;
162  extracblk->sizcblk = 0;
163  return;
164 }
165 
166 /**
167  *******************************************************************************
168  *
169  * @brief Add a new additional cblk defined by its first and last columns.
170  *
171  *******************************************************************************
172  *
173  * @param[inout] extracblk
174  * Pointer to the extracblk structure to add the cblk.
175  *
176  * @param[in] fcolnum
177  * Index of the first column in the new cblk.
178  *
179  * @param[in] lcolnum
180  * Index of the last column in the new cblk.
181  *
182  * @param[in] selevtx
183  * TODO
184  *
185  *******************************************************************************/
186 void
188  pastix_int_t fcolnum,
189  pastix_int_t lcolnum,
190  int8_t selevtx )
191 {
192  pastix_int_t curcblk = extraCblkInc( extracblk );
193 
194  extracblk->cblktab[ curcblk ].fcolnum = fcolnum;
195  extracblk->cblktab[ curcblk ].lcolnum = lcolnum;
196  extracblk->cblktab[ curcblk ].bloknum = -1;
197  extracblk->cblktab[ curcblk ].selevtx = selevtx;
198 }
199 
200 /**
201  *******************************************************************************
202  *
203  * @brief Merge the existing symbol structure with the additional information
204  * from the extracblk structure.
205  *
206  *******************************************************************************
207  *
208  * @param[in] extracblk
209  * Pointer to the extracblk structure that contains information about
210  * splited cblk.
211  *
212  * @param[inout] newsymb
213  * Symbol matrix to update. On exit, the symbol matrix structure is
214  * extended by the splited cblk described in extracblk structure.
215  *
216  * @param[inout] candtab
217  * On entry, the candtab aray associated to the input symbol matrix.
218  * On exit, the updated candtab array with the extended number of cblk.
219  *
220  *******************************************************************************/
221 void
222 extraCblkMerge( const ExtraCblk_t *extracblk,
223  symbol_matrix_t *newsymb,
224  Cand **candtab )
225 {
226  pastix_int_t i, j, k, l;
227  pastix_int_t curbloknum, curcblknum;
228  pastix_int_t lastcblksplit;
229  pastix_int_t addblok = 0;
230  pastix_int_t *newnum = NULL;
231  pastix_int_t *extranewnum = NULL;
232 
233  symbol_matrix_t *oldsymb;
234 
235 #if defined(PASTIX_BLEND_PROPMAP_2STEPS)
236  Cand *oldcand = *candtab;
237  Cand *newcand;
238 #else
239  (void)candtab;
240 #endif
241 
242  symbol_cblk_t *curcblk;
243  symbol_blok_t *curblok;
244 
245  /* No splitted cblk: partition remains the same */
246  if( extracblk->addcblk == 0 ) {
247  return;
248  }
249 
250  /* Backup the old symbol */
251  MALLOC_INTERN(oldsymb, 1, symbol_matrix_t);
252  memcpy( oldsymb, newsymb, sizeof(symbol_matrix_t) );
253 
254  /* Allocate new cblktab */
255  newsymb->cblknbr = oldsymb->cblknbr + extracblk->addcblk;
256  MALLOC_INTERN(newsymb->cblktab, newsymb->cblknbr+1, symbol_cblk_t);
257 
258  newsymb->browtab = NULL;
259 
260 #if defined(PASTIX_BLEND_PROPMAP_2STEPS)
261  /* Allocate new candtab */
262  newcand = candInit( newsymb->cblknbr );
263 
264  /* Copy the root cand */
265  newcand[-1] = oldcand[-1];
266 #endif
267 
268  /*
269  * We use the sptcbnb array to get the new numbering of the former cblk
270  * in the new symbolic matrix
271  * newnum[i+1] becomes the new number of the first cblk generated from the
272  * split of former cblk number i.
273  */
274  MALLOC_INTERN(newnum, oldsymb->cblknbr+1, pastix_int_t);
275  MALLOC_INTERN(extranewnum, extracblk->curcblk+1, pastix_int_t);
276  newnum[0] = 0;
277  memcpy(newnum+1, extracblk->sptcbnb, (oldsymb->cblknbr) * sizeof(pastix_int_t));
278 #ifndef NDEBUG
279  memset(extranewnum, 0xff, (extracblk->curcblk+1) * sizeof(pastix_int_t));
280 #endif
281 
282  /* Compute number of blocks that will be generated,
283  * and copy main information of cblktab and candtab */
284  lastcblksplit = -1;
285  for(i=0; i<oldsymb->cblknbr; i++)
286  {
287  pastix_int_t fbloknum = oldsymb->cblktab[i ].bloknum;
288  pastix_int_t lbloknum = oldsymb->cblktab[i+1].bloknum;
289  pastix_int_t sptcbnbw = extracblk->sptcbnb[i];
290 
291  /*
292  * First we compute the number of extra blocks that will be generated
293  */
294 
295  /* Diagonal block */
296  addblok += (((sptcbnbw+1) * sptcbnbw) / 2) - 1;
297  for(j=fbloknum+1; j<lbloknum; j++)
298  {
299  pastix_int_t fcblknum = oldsymb->bloktab[j].fcblknm;
300  pastix_int_t sptfcbnb = extracblk->sptcbnb[fcblknum];
301  pastix_int_t sptcbnbh = 0;
302 
303  /* If facing cblk is splitted */
304  if ( sptfcbnb > 1 )
305  {
306  symbol_cblk_t *newfcblk = &(extracblk->cblktab[ extracblk->sptcblk[fcblknum] ]);
307  pastix_int_t frownum = oldsymb->bloktab[j].frownum;
308  pastix_int_t lrownum = oldsymb->bloktab[j].lrownum;
309 
310  /* Compute how many times the block is splitted horizontally */
311  for(k = 0; k < sptfcbnb; k++, newfcblk++)
312  {
313  /* This block doesn't face this new cblk */
314  if ( frownum > newfcblk->lcolnum ) {
315  continue;
316  }
317 
318  /* No more facing cblk will be found */
319  if ( lrownum < newfcblk->fcolnum ) {
320  break;
321  }
322 
323  assert( frownum <= lrownum );
324  sptcbnbh++;
325  frownum = newfcblk->lcolnum+1;
326  }
327  }
328  else
329  sptcbnbh = 1;
330 
331  /*
332  * The number of extra blocks is the number of times the block
333  * is psplitted horizontally times the number of time the cblk
334  * is splitted vertically minu itself
335  */
336  addblok += sptcbnbw * sptcbnbh - 1;
337  }
338 
339  /*
340  * Second, we create newnum/extranewnum arrays and copy information into
341  * cblktab and candtab
342  */
343  {
344  /* This cblk is splitted, we generate new cblktab from extra */
345  pastix_int_t newcblknum = newnum[i];
346  if (sptcbnbw > 1) {
347  pastix_int_t nbcblk2copy = (i - lastcblksplit - 1);
348  pastix_int_t sptcblk = extracblk->sptcblk[i];
349 
350  /* Copy the previous unchanged cblks from oldsymb */
351  if ( nbcblk2copy > 0 ) {
352  lastcblksplit++;
353  memcpy( newsymb->cblktab + newnum[ lastcblksplit ],
354  oldsymb->cblktab + lastcblksplit,
355  nbcblk2copy * sizeof(symbol_cblk_t) );
356 
357 #if defined(PASTIX_BLEND_PROPMAP_2STEPS)
358  memcpy( newcand + newnum[ lastcblksplit ],
359  oldcand + lastcblksplit,
360  nbcblk2copy * sizeof(Cand) );
361 #endif
362  }
363 
364  /* Copy the new cblk from extracblk */
365  assert( (sptcblk >= 0) && (sptcblk <= extracblk->curcblk) );
366  memcpy( newsymb->cblktab + newcblknum,
367  extracblk->cblktab + sptcblk,
368  sptcbnbw * sizeof(symbol_cblk_t) );
369 
370  /* Initialize extranewnum and duplicate the cand for each new cblk */
371  for(j=0; j<sptcbnbw; j++, sptcblk++) {
372  extranewnum[sptcblk] = newcblknum+j;
373 
374  assert( (extranewnum[sptcblk] >= 0) &&
375  (extranewnum[sptcblk] < newsymb->cblknbr) );
376 
377 #if defined(PASTIX_BLEND_PROPMAP_2STEPS)
378  memcpy( newcand + extranewnum[ sptcblk ],
379  oldcand + i, sizeof(Cand) );
380 #endif
381  }
382 
383  lastcblksplit = i;
384  }
385  /* Update newnum of following cblk (newnum is allocated with one extra space) */
386  newnum[i+1] += newcblknum;
387  }
388  }
389 
390  /* Copy last unsplitted block */
391  if ( lastcblksplit < (oldsymb->cblknbr-1) )
392  {
393  pastix_int_t nbcblk2copy = oldsymb->cblknbr - lastcblksplit - 1;
394  lastcblksplit++;
395  memcpy( newsymb->cblktab + newnum[ lastcblksplit ],
396  oldsymb->cblktab + lastcblksplit,
397  nbcblk2copy * sizeof(symbol_cblk_t) );
398 
399 #if defined(PASTIX_BLEND_PROPMAP_2STEPS)
400  memcpy( newcand + newnum[ lastcblksplit ],
401  oldcand + lastcblksplit,
402  nbcblk2copy * sizeof(Cand) );
403 #endif
404  }
405 
406 #if defined(PASTIX_BLEND_PROPMAP_2STEPS)
407  candExit(oldcand);
408  *candtab = newcand;
409 #endif
410 
411  /* Allocate new bloktab */
412  newsymb->bloknbr = oldsymb->bloknbr + addblok;
413  MALLOC_INTERN(newsymb->bloktab, newsymb->bloknbr, symbol_blok_t);
414 
415  /* Fill in the new symbolic matrix resulting from the splitting of the former one */
416  curbloknum = 0;
417  curcblknum = 0;
418  curcblk = newsymb->cblktab;
419  curblok = newsymb->bloktab;
420 
421 #if defined(PASTIX_SYMBOL_DUMP_SYMBMTX)
422  symbol_cblk_t *cblk = newsymb->cblktab;
423 #endif
424  for(i=0; i<oldsymb->cblknbr; i++)
425  {
426  pastix_int_t fbloknum = oldsymb->cblktab[i ].bloknum;
427  pastix_int_t lbloknum = oldsymb->cblktab[i+1].bloknum;
428  pastix_int_t sptcbnbw = extracblk->sptcbnb[i];
429 
430  /* For each new column created by the cblk split */
431  for(j=0; j<sptcbnbw; j++, curcblknum++, curcblk++)
432  {
433  /* Store diagonal bloknum */
434  curcblk->bloknum = curbloknum;
435 
436 #if defined(PASTIX_SYMBOL_DUMP_SYMBMTX)
437  cblk->split_cblk = sptcbnbw-j-1;
438  cblk++;
439 #endif
440 
441  /* Create odb due to the splitting of the diag blok */
442  for(k=0; k<(sptcbnbw-j); k++, curbloknum++, curblok++)
443  {
444  curblok->frownum = curcblk[k].fcolnum;
445  curblok->lrownum = curcblk[k].lcolnum;
446  curblok->lcblknm = curcblknum;
447  curblok->fcblknm = curcblknum + k;
448  }
449  /* Next cblk will have one block less on the diagonal */
450 
451  /* Create other off diagonal blocks */
452  for(k=fbloknum+1; k<lbloknum; k++)
453  {
454  pastix_int_t frownum = oldsymb->bloktab[k].frownum;
455  pastix_int_t lrownum = oldsymb->bloktab[k].lrownum;
456  pastix_int_t fcblknum = oldsymb->bloktab[k].fcblknm;
457  pastix_int_t sptfcblk = extracblk->sptcblk[fcblknum];
458  pastix_int_t sptfcbnb = extracblk->sptcbnb[fcblknum];
459 
460  /* If facing cblk is splitted */
461  if ( sptfcbnb > 1 )
462  {
463  pastix_int_t newfcblknum = extranewnum[ sptfcblk ];
464  symbol_cblk_t *newfcblk = &(extracblk->cblktab[ sptfcblk ]);
465 
466  assert( newfcblknum != -1 );
467  assert( newfcblk != NULL );
468 
469  /* Create new blocks facing this cblk */
470  for(l=0; l<sptfcbnb; l++, newfcblk++)
471  {
472  /* This block doesn't face this new cblk */
473  if ( frownum > newfcblk->lcolnum ) {
474  continue;
475  }
476 
477  /* No more facing cblk will be found */
478  if ( lrownum < newfcblk->fcolnum ) {
479  break;
480  }
481 
482  assert( frownum <= lrownum );
483  assert( frownum >= newfcblk->fcolnum );
484 
485  curblok->frownum = frownum;
486  curblok->lrownum = pastix_imin( lrownum, newfcblk->lcolnum );
487  curblok->lcblknm = curcblknum;
488  curblok->fcblknm = newfcblknum + l;
489  curblok++; curbloknum++;
490 
491  frownum = newfcblk->lcolnum+1;
492  }
493  }
494  else
495  {
496  curblok->frownum = frownum;
497  curblok->lrownum = lrownum;
498  curblok->lcblknm = curcblknum;
499  curblok->fcblknm = newnum[fcblknum];
500  curblok++; curbloknum++;
501  }
502  }
503  }
504  }
505 
506  assert(curcblknum == newsymb->cblknbr);
507  assert(curbloknum == newsymb->bloknbr);
508  assert((curcblk - newsymb->cblktab) == newsymb->cblknbr);
509  assert((curblok - newsymb->bloktab) == newsymb->bloknbr);
510 
511  /* Free old versions and temporary buffer */
512  pastixSymbolExit(oldsymb);
513  memFree_null(oldsymb);
514  memFree_null(newnum);
515  memFree_null(extranewnum);
516 
517  /* Virtual cblk to avoid side effect in the loops on cblk bloks */
518  curcblk[0].fcolnum = curcblk[-1].lcolnum + 1;
519  curcblk[0].lcolnum = curcblk[-1].lcolnum + 1;
520  curcblk[0].bloknum = curbloknum;
521 
522  pastixSymbolBuildRowtab( newsymb );
523 
524  return;
525 }
526 
527 /**
528  *@}
529  */
BEGIN_C_DECLS typedef int pastix_int_t
Definition: datatypes.h:51
Cand * candInit(pastix_int_t cblknbr)
Initialize the candtab array with default values.
Definition: cand.c:48
void candExit(Cand *candtab)
Exit and free the candtab structure given.
Definition: cand.c:83
Processor candidate group to own a column blok.
Definition: cand.h:28
pastix_int_t sizcblk
Definition: extracblk.h:35
pastix_int_t addblok
Definition: extracblk.h:30
pastix_int_t cblknbr
Definition: extracblk.h:28
pastix_int_t addcblk
Definition: extracblk.h:29
pastix_int_t addblof
Definition: extracblk.h:31
symbol_cblk_t * cblktab
Definition: extracblk.h:36
pastix_int_t curcblk
Definition: extracblk.h:34
pastix_int_t * sptcbnb
Definition: extracblk.h:33
pastix_int_t * sptcblk
Definition: extracblk.h:32
void extraCblkAdd(ExtraCblk_t *extracblk, pastix_int_t fcolnum, pastix_int_t lcolnum, int8_t selevtx)
Add a new additional cblk defined by its first and last columns.
Definition: extracblk.c:187
static pastix_int_t extraCblkInc(ExtraCblk_t *extracblk)
Increment the number of extra cblk that can be stored.
Definition: extracblk.c:83
void extraCblkExit(ExtraCblk_t *extracblk)
Free the extracblk structure.
Definition: extracblk.c:154
void extraCblkMerge(const ExtraCblk_t *extracblk, symbol_matrix_t *newsymb, Cand **candtab)
Merge the existing symbol structure with the additional information from the extracblk structure.
Definition: extracblk.c:222
void extraCblkInit(pastix_int_t cblknbr, ExtraCblk_t *extracblk)
Initialize the extracblk structure.
Definition: extracblk.c:127
static void extraCblkAlloc(ExtraCblk_t *extracblk)
Allocate the extracblk structure.
Definition: extracblk.c:39
Extra symbol cblk structure.
Definition: extracblk.h:27
pastix_int_t fcblknm
Definition: symbol.h:63
pastix_int_t frownum
Definition: symbol.h:60
pastix_int_t lrownum
Definition: symbol.h:61
pastix_int_t bloknbr
Definition: symbol.h:80
pastix_int_t * browtab
Definition: symbol.h:85
symbol_cblk_t * cblktab
Definition: symbol.h:83
pastix_int_t bloknum
Definition: symbol.h:48
pastix_int_t fcolnum
Definition: symbol.h:46
pastix_int_t lcolnum
Definition: symbol.h:47
symbol_blok_t * bloktab
Definition: symbol.h:84
pastix_int_t lcblknm
Definition: symbol.h:62
pastix_int_t cblknbr
Definition: symbol.h:79
void pastixSymbolBuildRowtab(symbol_matrix_t *symbptr)
Construct the browtab array that stores the blocks in a CSR way.
Definition: symbol.c:302
void pastixSymbolExit(symbol_matrix_t *symbptr)
Free the content of symbolic matrix.
Definition: symbol.c:137
Symbol block structure.
Definition: symbol.h:59
Symbol column block structure.
Definition: symbol.h:45
Symbol matrix structure.
Definition: symbol.h:77