117 const int *
const restrict matrix_col_ptr,
118 const int *
const restrict matrix_row_index,
119 const double *
const restrict matrix_values)
123 int *parent = malloc(
sizeof(
int) *
dimension);
124 int *ancestor = malloc(
sizeof(
int) *
dimension);
125 int *workspace = malloc(
sizeof(
int) *
dimension);
126 int *sstk = malloc(
sizeof(
int) *
dimension);
128 int *colptr = NULL, *rowind = NULL, *colfill = NULL, *col_level = NULL;
129 int *updoff = NULL, *updljk = NULL, *updk = NULL;
130 int *contptr_h = NULL, *contsrc_h = NULL, *contljk_h = NULL, *fillc = NULL;
131 int *posof_h = NULL, *levcols = NULL;
132 int *rowptr = NULL, *rowcol = NULL, *rowpos = NULL, *diagpos = NULL, *rowfill = NULL;
133 double *values_host = NULL;
134 if(!parent || !ancestor || !workspace || !sstk || !
factor)
goto fail;
142 colptr = calloc(
dimension + 1,
sizeof(
int));
143 updoff = calloc(
dimension + 2,
sizeof(
int));
144 if(!colptr || !updoff)
goto fail;
150 const int stack_top =
_sp_ereach(
dimension, matrix_col_ptr, matrix_row_index, j, parent, sstk, workspace);
151 for(
int stack_pos = stack_top; stack_pos <
dimension; stack_pos++)
153 colptr[sstk[stack_pos] + 1] += 1;
156 updoff[j + 1] = (int)nupd;
158 for(
int j = 0; j <
dimension; j++) colptr[j + 1] += colptr[j];
162 rowind = malloc(
sizeof(
int) *
factor->n_nonzero);
163 colfill = malloc(
sizeof(
int) *
dimension);
164 updljk = malloc(
sizeof(
int) * (nupd ? nupd : 1));
165 updk = malloc(
sizeof(
int) * (nupd ? nupd : 1));
166 if(!rowind || !colfill || !updljk || !updk)
goto fail;
169 rowind[colptr[j]] = j;
173 size_t upd_index = 0;
177 const int stack_top =
_sp_ereach(
dimension, matrix_col_ptr, matrix_row_index, j, parent, sstk, workspace);
178 for(
int stack_pos = stack_top; stack_pos <
dimension; stack_pos++)
180 const int k = sstk[stack_pos];
181 const int pos = colptr[
k] + colfill[
k];
184 updljk[upd_index] = pos;
199 contptr_h = calloc((
size_t)
factor->n_nonzero + 1,
sizeof(
int));
200 fillc = calloc(
factor->n_nonzero,
sizeof(
int));
201 if(!contptr_h || !fillc)
goto fail;
203 OMP_PRAGMA(omp parallel
for default(firstprivate) schedule(dynamic, 16))
206 for(
int upd_slot = updoff[j]; upd_slot < updoff[j + 1]; upd_slot++)
208 const int k = updk[upd_slot];
209 int pos_j = colptr[j];
210 for(
int pos_k = updljk[upd_slot]; pos_k < colptr[
k + 1]; pos_k++)
212 const int row = rowind[pos_k];
213 while(rowind[pos_j] !=
row) pos_j++;
214 contptr_h[pos_j + 1]++;
218 for(
int entry = 0; entry <
factor->n_nonzero; entry++) contptr_h[entry + 1] += contptr_h[entry];
219 npairs = (size_t)contptr_h[
factor->n_nonzero];
220 contsrc_h = malloc(
sizeof(
int) * (npairs ? npairs : 1));
221 contljk_h = malloc(
sizeof(
int) * (npairs ? npairs : 1));
222 if(!contsrc_h || !contljk_h)
goto fail;
224 OMP_PRAGMA(omp parallel
for default(firstprivate) schedule(dynamic, 16))
227 for(
int upd_slot = updoff[j]; upd_slot < updoff[j + 1]; upd_slot++)
229 const int k = updk[upd_slot];
230 const int ljk_pos = updljk[upd_slot];
231 int pos_j = colptr[j];
232 for(
int pos_k = ljk_pos; pos_k < colptr[
k + 1]; pos_k++)
234 const int row = rowind[pos_k];
235 while(rowind[pos_j] !=
row) pos_j++;
236 const int dest_index = contptr_h[pos_j] + fillc[pos_j]++;
237 contsrc_h[dest_index] = pos_k;
238 contljk_h[dest_index] = ljk_pos;
250 col_level = calloc(
dimension,
sizeof(
int));
251 if(!col_level)
goto fail;
255 int neighbor_max = -1;
256 for(
int upd_slot = updoff[j]; upd_slot < updoff[j + 1]; upd_slot++)
257 if(col_level[updk[upd_slot]] > neighbor_max) neighbor_max = col_level[updk[upd_slot]];
258 col_level[j] = neighbor_max + 1;
259 if(col_level[j] > maxlev) maxlev = col_level[j];
261 factor->nlev = maxlev + 1;
262 factor->lev_off = calloc(
factor->nlev + 1,
sizeof(
int));
263 levcols = malloc(
sizeof(
int) *
dimension);
264 if(!
factor->lev_off || !levcols)
goto fail;
265 for(
int j = 0; j <
dimension; j++)
factor->lev_off[col_level[j] + 1]++;
266 for(
int level = 0; level <
factor->nlev; level++)
factor->lev_off[level + 1] +=
factor->lev_off[level];
268 int *fill = calloc(
factor->nlev,
sizeof(
int));
270 for(
int j = 0; j <
dimension; j++) levcols[
factor->lev_off[col_level[j]] + fill[col_level[j]]++] = j;
275 posof_h = malloc(
sizeof(
int) *
factor->n_nonzero);
276 factor->lev_pos_off = calloc(
factor->nlev + 1,
sizeof(
int));
277 if(!posof_h || !
factor->lev_pos_off)
goto fail;
280 for(
int level = 0; level <
factor->nlev; level++)
282 factor->lev_pos_off[level] = dest_index;
283 for(
int c =
factor->lev_off[level]; c <
factor->lev_off[level + 1]; c++)
285 const int j = levcols[c];
286 for(
int pos = colptr[j]; pos < colptr[j + 1]; pos++) posof_h[dest_index++] = pos;
297 int *col_level_bwd = calloc(
dimension,
sizeof(
int));
298 int *level_rows = malloc(
sizeof(
int) *
dimension);
299 if(!col_level_bwd || !level_rows)
308 int neighbor_max = -1;
309 for(
int pos = colptr[j] + 1; pos < colptr[j + 1]; pos++)
310 if(col_level_bwd[rowind[pos]] > neighbor_max) neighbor_max = col_level_bwd[rowind[pos]];
311 col_level_bwd[j] = neighbor_max + 1;
312 if(col_level_bwd[j] > max_bwd) max_bwd = col_level_bwd[j];
314 factor->nlev_bwd = max_bwd + 1;
315 factor->lev_off_bwd = calloc(
factor->nlev_bwd + 1,
sizeof(
int));
322 for(
int j = 0; j <
dimension; j++)
factor->lev_off_bwd[col_level_bwd[j] + 1]++;
323 for(
int level = 0; level <
factor->nlev_bwd; level++)
324 factor->lev_off_bwd[level + 1] +=
factor->lev_off_bwd[level];
325 int *fill = calloc(
factor->nlev_bwd,
sizeof(
int));
333 level_rows[
factor->lev_off_bwd[col_level_bwd[j]] + fill[col_level_bwd[j]]++] = j;
343 rowptr = calloc(
dimension + 1,
sizeof(
int));
344 diagpos = malloc(
sizeof(
int) *
dimension);
345 rowfill = calloc(
dimension,
sizeof(
int));
346 if(!rowptr || !diagpos || !rowfill)
goto fail;
349 diagpos[c] = colptr[c];
350 for(
int pos = colptr[c] + 1; pos < colptr[c + 1]; pos++) rowptr[rowind[pos] + 1]++;
352 for(
int j = 0; j <
dimension; j++) rowptr[j + 1] += rowptr[j];
355 if(!rowcol || !rowpos)
goto fail;
357 for(
int pos = colptr[c] + 1; pos < colptr[c + 1]; pos++)
359 const int row = rowind[pos];
360 const int dest_index = rowptr[
row] + rowfill[
row]++;
361 rowcol[dest_index] = c;
362 rowpos[dest_index] = pos;
366 values_host = calloc(
factor->n_nonzero,
sizeof(
double));
367 if(!values_host)
goto fail;
369 for(
int pos = matrix_col_ptr[c]; pos < matrix_col_ptr[c + 1]; pos++)
371 const int row = matrix_row_index[pos];
373 values_host[colptr[c]] = matrix_values[pos];
376 int dest_index = colptr[
row];
377 while(rowind[dest_index] != c) dest_index++;
378 values_host[dest_index] = matrix_values[pos];
413 const int local_size = 64;
414 for(
int level = 0; level <
factor->nlev; level++)
416 const int n_level_cols =
factor->lev_off[level + 1] -
factor->lev_off[level];
417 if(!n_level_cols)
continue;
418 const int npos =
factor->lev_pos_off[level + 1] -
factor->lev_pos_off[level];
421 size_t sizes[3] = {
ROUNDUP(npos, 64), 1, 1 };
432 size_t sizes[3] = { (size_t)n_level_cols * local_size, 1, 1 };
433 size_t local[3] = { local_size, 1, 1 };
448 "[sparse cholesky] factor n=%d nnz=%d nlev=%d npairs=%llu: sym=%.0fms up=%.0fms"
449 " enq=%.0fms gpu=%.0fms\n",
451 (_tf2 - _tf1) * 1e3, (_tf3 - _tf2) * 1e3, (
dt_get_wtime() - _tf3) * 1e3);