Skip to content

Commit d03f6f9

Browse files
authored
342 execution issue with custom preconditioning function in conjugate gradient non blocking backend (#344)
This PCG algorithm allows for user-defined preconditioners to be supplied by the user. This functionality, in turn, was then used by the solver and KML_Solver transition paths to offer ready-made libraries for which users could supply their own preconditioners via function pointers. Those preconditioners would operate on standard raw C arrays, thus making use of the ALP native interface -- however, the PCG algorithm in ALP/GraphBLAS implicitly assumed the preconditioner action was implemented as an ALP function; i.e., not using the native interface. This mismatch causes issues in combination with the nonblocking backend, which guarantees valid nonblocking execution for pure ALP programs, but in combination with native code requires calls to `grb::wait`. This MR introduces a template argument to indicate whether the preconditioner may make use of native calls. This is done by extending the already-existing Boolean argument that previously indicated whether to apply preconditioning-- this is now become an `int` rather than `bool`, with `0` indicating no preconditioning, `1` indicating non-native (ALP-based) user-defined preconditioning, and `2` indicating possibly-native user-defined preconditioning. Only in the latter case does this MR furthermore activate the new calls to `grb::wait` that are necessary for native preconditioning functions. An alternative design has that the authors of user-defined preconditioners should call `grb::wait` before taking and operating on native views of ALP/GraphBLAS vectors. In this design, the reported issue #342 would in fact indicate a bug in the related transition libraries. Comparing the implemented solution with this alternative design has that more care should be taken by those supplying user-defined preconditioners, and we instead prefer to make the life of any ALP user easier; hence the present solution was taken instead. The bug that this MR fixes affected the PCG transition paths only; i.e., users of `solver.h` and/or `kml_iss.h`, only when using custom preconditioners, and only non-diagonal preconditioner actions.
1 parent d5e9a06 commit d03f6f9

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

include/graphblas/algorithms/conjugate_gradient.hpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,19 @@ namespace grb {
4545
* positive definite.
4646
*
4747
* @tparam descr The user descriptor
48-
* @tparam preconditioned Whether to apply any given preconditioners.
48+
* @tparam preconditioned Nonzero to apply any given preconditioners, zero to
49+
* not apply preconditioning and ignore related
50+
* arguments, two if the preconditioner action may be
51+
* native.
4952
*
50-
* \note The default value for \a preconditioned is <tt>true</tt> and it is
53+
* \note The default value for \a preconditioned is <tt>1</tt> and it is
5154
* normally not necessary to override this value: if wishing to call a
5255
* non-preconditioned CG, please see #conjugate_gradient.
5356
*
57+
* \note Native in the above means the preconditioner action may not consist
58+
* of pure ALP code. In this case a nonblocking implementation should
59+
* take care to not attempt to fuse across the preconditioner action.
60+
*
5461
* @tparam IOType The input/output vector nonzero type
5562
* @tparam ResidualType The type of the residual
5663
* @tparam NonzeroType The matrix nonzero type
@@ -98,8 +105,8 @@ namespace grb {
98105
* achieved by constructing \a Minv so that the condition number of
99106
* \f$ M^{-1}A \f$ is much smaller than that of \f$ A \f$.
100107
*
101-
* @param[in] Minv The preconditioner action if
102-
* \a preconditioned equals <tt>true</tt>.
108+
* @param[in] Minv The preconditioner action, used only if
109+
* \a preconditioned is nonzero.
103110
*
104111
* If \a A is \f$ n \times n \f$, then \a x and \a b must have matching length
105112
* \f$ n \f$. The vector \a x furthermore must have a capacity of \f$ n \f$.
@@ -123,7 +130,7 @@ namespace grb {
123130
* @param[in,out] temp A temporary vector of the same size as \a x.
124131
* @param[in,out] temp_precond A temporary vector of the same size as \a x.
125132
*
126-
* \note If \a preconditioned is <tt>false</tt>, then both \a Minv and
133+
* \note If \a preconditioned is <tt>0</tt>, then both \a Minv and
127134
* \a temp_precond are ignored. In this case, \a temp_precond need not
128135
* have the same length as \a x, nor need it have full capacity.
129136
*
@@ -175,7 +182,7 @@ namespace grb {
175182
*/
176183
template<
177184
Descriptor descr = descriptors::no_operation,
178-
bool preconditioned = true,
185+
int preconditioned = 1,
179186
typename IOType,
180187
typename ResidualType,
181188
typename NonzeroType,
@@ -344,6 +351,9 @@ namespace grb {
344351
// z = M^-1r
345352
if( preconditioned ) {
346353
ret = ret ? ret : grb::set( z, 0 ); // also ensures z is dense, henceforth
354+
if( preconditioned == 2 ) {
355+
ret = ret ? ret : grb::wait( z, r );
356+
}
347357
ret = ret ? ret : Minv( z, r );
348358
} // else, z equals r (by reference)
349359

@@ -443,6 +453,9 @@ namespace grb {
443453
// beta = r' * z
444454
if( preconditioned ) {
445455
beta = zero;
456+
if( preconditioned == 2 ) {
457+
ret = ret ? ret : grb::wait( z, r );
458+
}
446459
ret = ret ? ret : Minv( z, r ); assert( ret == grb::SUCCESS );
447460
ret = ret ? ret : grb::dot< descr_dense >(
448461
beta,
@@ -572,7 +585,7 @@ namespace grb {
572585
grb::Vector< IOType, backend > dummy_buffer( 0 );
573586

574587
// call PCG with preconditioning disabled
575-
return preconditioned_conjugate_gradient< descr, false >(
588+
return preconditioned_conjugate_gradient< descr, 0 >(
576589
x, A, b,
577590
dummy_preconditioner,
578591
max_iterations, tol,

src/transition/solver.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ class CG_Data {
261261
workspace[ 0 ], workspace[ 1 ], workspace[ 2 ]
262262
);
263263
} else {
264-
return grb::algorithms::preconditioned_conjugate_gradient< descr >(
264+
return grb::algorithms::preconditioned_conjugate_gradient< descr, 2 >(
265265
x, matrix, b,
266266
alpified_preconditioner(),
267267
max_iter, tolerance,

0 commit comments

Comments
 (0)