120 const int *
const restrict matrix_col_ptr,
121 const int *
const restrict matrix_row_index,
122 const double *
const restrict matrix_values)
126 int *parent = malloc(
sizeof(
int) *
dimension);
127 int *ancestor = malloc(
sizeof(
int) *
dimension);
128 int *workspace = malloc(
sizeof(
int) *
dimension);
129 int *sstk = malloc(
sizeof(
int) *
dimension);
131 int *colptr = NULL, *rowind = NULL, *colfill = NULL, *col_level = NULL;
132 int *updoff = NULL, *updljk = NULL, *updk = NULL;
133 int *contptr_h = NULL, *contsrc_h = NULL, *contljk_h = NULL, *fillc = NULL;
134 int *posof_h = NULL, *levcols = NULL;
135 int *rowptr = NULL, *rowcol = NULL, *rowpos = NULL, *diagpos = NULL, *rowfill = NULL;
136 double *values_host = NULL;
137 if(!parent || !ancestor || !workspace || !sstk || !
factor)
goto fail;
145 colptr = calloc(
dimension + 1,
sizeof(
int));
146 updoff = calloc(
dimension + 2,
sizeof(
int));
147 if(!colptr || !updoff)
goto fail;
153 const int stack_top =
_sp_ereach(
dimension, matrix_col_ptr, matrix_row_index, j, parent, sstk, workspace);
154 for(
int stack_pos = stack_top; stack_pos <
dimension; stack_pos++)
156 colptr[sstk[stack_pos] + 1] += 1;
159 updoff[j + 1] = (int)nupd;
161 for(
int j = 0; j <
dimension; j++) colptr[j + 1] += colptr[j];
165 rowind = malloc(
sizeof(
int) *
factor->n_nonzero);
166 colfill = malloc(
sizeof(
int) *
dimension);
167 updljk = malloc(
sizeof(
int) * (nupd ? nupd : 1));
168 updk = malloc(
sizeof(
int) * (nupd ? nupd : 1));
169 if(!rowind || !colfill || !updljk || !updk)
goto fail;
172 rowind[colptr[j]] = j;
176 size_t upd_index = 0;
180 const int stack_top =
_sp_ereach(
dimension, matrix_col_ptr, matrix_row_index, j, parent, sstk, workspace);
181 for(
int stack_pos = stack_top; stack_pos <
dimension; stack_pos++)
183 const int k = sstk[stack_pos];
184 const int pos = colptr[
k] + colfill[
k];
187 updljk[upd_index] = pos;
202 contptr_h = calloc((
size_t)
factor->n_nonzero + 1,
sizeof(
int));
203 fillc = calloc(
factor->n_nonzero,
sizeof(
int));
204 if(!contptr_h || !fillc)
goto fail;
206 OMP_PRAGMA(omp parallel
for default(firstprivate) schedule(dynamic, 16))
209 for(
int upd_slot = updoff[j]; upd_slot < updoff[j + 1]; upd_slot++)
211 const int k = updk[upd_slot];
212 int pos_j = colptr[j];
213 for(
int pos_k = updljk[upd_slot]; pos_k < colptr[
k + 1]; pos_k++)
215 const int row = rowind[pos_k];
216 while(rowind[pos_j] !=
row) pos_j++;
217 contptr_h[pos_j + 1]++;
221 for(
int entry = 0; entry <
factor->n_nonzero; entry++) contptr_h[entry + 1] += contptr_h[entry];
222 npairs = (size_t)contptr_h[
factor->n_nonzero];
223 contsrc_h = malloc(
sizeof(
int) * (npairs ? npairs : 1));
224 contljk_h = malloc(
sizeof(
int) * (npairs ? npairs : 1));
225 if(!contsrc_h || !contljk_h)
goto fail;
227 OMP_PRAGMA(omp parallel
for default(firstprivate) schedule(dynamic, 16))
230 for(
int upd_slot = updoff[j]; upd_slot < updoff[j + 1]; upd_slot++)
232 const int k = updk[upd_slot];
233 const int ljk_pos = updljk[upd_slot];
234 int pos_j = colptr[j];
235 for(
int pos_k = ljk_pos; pos_k < colptr[
k + 1]; pos_k++)
237 const int row = rowind[pos_k];
238 while(rowind[pos_j] !=
row) pos_j++;
239 const int dest_index = contptr_h[pos_j] + fillc[pos_j]++;
240 contsrc_h[dest_index] = pos_k;
241 contljk_h[dest_index] = ljk_pos;
253 col_level = calloc(
dimension,
sizeof(
int));
254 if(!col_level)
goto fail;
258 int neighbor_max = -1;
259 for(
int upd_slot = updoff[j]; upd_slot < updoff[j + 1]; upd_slot++)
260 if(col_level[updk[upd_slot]] > neighbor_max) neighbor_max = col_level[updk[upd_slot]];
261 col_level[j] = neighbor_max + 1;
262 if(col_level[j] > maxlev) maxlev = col_level[j];
264 factor->nlev = maxlev + 1;
265 factor->lev_off = calloc(
factor->nlev + 1,
sizeof(
int));
266 levcols = malloc(
sizeof(
int) *
dimension);
267 if(!
factor->lev_off || !levcols)
goto fail;
268 for(
int j = 0; j <
dimension; j++)
factor->lev_off[col_level[j] + 1]++;
269 for(
int level = 0; level <
factor->nlev; level++)
factor->lev_off[level + 1] +=
factor->lev_off[level];
271 int *fill = calloc(
factor->nlev,
sizeof(
int));
273 for(
int j = 0; j <
dimension; j++) levcols[
factor->lev_off[col_level[j]] + fill[col_level[j]]++] = j;
278 posof_h = malloc(
sizeof(
int) *
factor->n_nonzero);
279 factor->lev_pos_off = calloc(
factor->nlev + 1,
sizeof(
int));
280 if(!posof_h || !
factor->lev_pos_off)
goto fail;
283 for(
int level = 0; level <
factor->nlev; level++)
285 factor->lev_pos_off[level] = dest_index;
286 for(
int c =
factor->lev_off[level]; c <
factor->lev_off[level + 1]; c++)
288 const int j = levcols[c];
289 for(
int pos = colptr[j]; pos < colptr[j + 1]; pos++) posof_h[dest_index++] = pos;
300 int *col_level_bwd = calloc(
dimension,
sizeof(
int));
301 int *level_rows = malloc(
sizeof(
int) *
dimension);
302 if(!col_level_bwd || !level_rows)
311 int neighbor_max = -1;
312 for(
int pos = colptr[j] + 1; pos < colptr[j + 1]; pos++)
313 if(col_level_bwd[rowind[pos]] > neighbor_max) neighbor_max = col_level_bwd[rowind[pos]];
314 col_level_bwd[j] = neighbor_max + 1;
315 if(col_level_bwd[j] > max_bwd) max_bwd = col_level_bwd[j];
322 const int nlev_bwd = max_bwd + 1;
329 factor->nlev_bwd = nlev_bwd;
330 factor->lev_off_bwd = calloc((
size_t)nlev_bwd + 1,
sizeof(
int));
337 for(
int j = 0; j <
dimension; j++)
factor->lev_off_bwd[col_level_bwd[j] + 1]++;
338 for(
int level = 0; level <
factor->nlev_bwd; level++)
339 factor->lev_off_bwd[level + 1] +=
factor->lev_off_bwd[level];
340 int *fill = calloc((
size_t)nlev_bwd,
sizeof(
int));
348 level_rows[
factor->lev_off_bwd[col_level_bwd[j]] + fill[col_level_bwd[j]]++] = j;
358 rowptr = calloc(
dimension + 1,
sizeof(
int));
359 diagpos = malloc(
sizeof(
int) *
dimension);
360 rowfill = calloc(
dimension,
sizeof(
int));
361 if(!rowptr || !diagpos || !rowfill)
goto fail;
364 diagpos[c] = colptr[c];
365 for(
int pos = colptr[c] + 1; pos < colptr[c + 1]; pos++) rowptr[rowind[pos] + 1]++;
367 for(
int j = 0; j <
dimension; j++) rowptr[j + 1] += rowptr[j];
370 if(!rowcol || !rowpos)
goto fail;
372 for(
int pos = colptr[c] + 1; pos < colptr[c + 1]; pos++)
374 const int row = rowind[pos];
375 const int dest_index = rowptr[
row] + rowfill[
row]++;
376 rowcol[dest_index] = c;
377 rowpos[dest_index] = pos;
381 values_host = calloc(
factor->n_nonzero,
sizeof(
double));
382 if(!values_host)
goto fail;
384 for(
int pos = matrix_col_ptr[c]; pos < matrix_col_ptr[c + 1]; pos++)
386 const int row = matrix_row_index[pos];
388 values_host[colptr[c]] = matrix_values[pos];
391 int dest_index = colptr[
row];
392 while(rowind[dest_index] != c) dest_index++;
393 values_host[dest_index] = matrix_values[pos];
428 const int local_size = 64;
429 for(
int level = 0; level <
factor->nlev; level++)
431 const int n_level_cols =
factor->lev_off[level + 1] -
factor->lev_off[level];
432 if(!n_level_cols)
continue;
433 const int npos =
factor->lev_pos_off[level + 1] -
factor->lev_pos_off[level];
436 size_t sizes[3] = {
ROUNDUP(npos, 64), 1, 1 };
447 size_t sizes[3] = { (size_t)n_level_cols * local_size, 1, 1 };
448 size_t local[3] = { local_size, 1, 1 };
463 "[sparse cholesky] factor n=%d nnz=%d nlev=%d npairs=%llu: sym=%.0fms up=%.0fms"
464 " enq=%.0fms gpu=%.0fms\n",
466 (_tf2 - _tf1) * 1e3, (_tf3 - _tf2) * 1e3, (
dt_get_wtime() - _tf3) * 1e3);