Skip to main content

cusolverDnDsyevj

Function cusolverDnDsyevj 

Source
pub unsafe extern "C" fn cusolverDnDsyevj(
    handle: cusolverDnHandle_t,
    jobz: cusolverEigMode_t,
    uplo: cublasFillMode_t,
    n: c_int,
    A: *mut f64,
    lda: c_int,
    W: *mut f64,
    work: *mut f64,
    lwork: c_int,
    info: *mut c_int,
    params: syevjInfo_t,
) -> cusolverStatus_t
Expand description

The helper functions below can calculate the sizes needed for pre-allocated buffer.

The S and D data types are real valued single and double precision, respectively.

The C and Z data types are complex valued single and double precision, respectively.

This function computes eigenvalues and eigenvectors of a symmetric (Hermitian) $n \times n$ matrix A. The standard symmetric eigenvalue problem is: $$ A\Q = Q\\Lambda $$

where Λ is a real $n \times n$ diagonal matrix. Q is an $n \times n$ unitary matrix. The diagonal elements of Λ are the eigenvalues of A in ascending order.

syevj has the same functionality as syevd. The difference is that syevd uses QR algorithm and syevj uses Jacobi method. The parallelism of Jacobi method gives GPU better performance on small and medium size matrices. Moreover the user can configure syevj to perform approximation up to certain accuracy.

How does it work?

syevj iteratively generates a sequence of unitary matrices to transform matrix A to the following form: $$ V^{H}\*A\*V = W + E $$

where W is diagonal and E is symmetric without diagonal.

During the iterations, the Frobenius norm of E decreases monotonically. As E goes down to zero, W is the set of eigenvalues. In practice, Jacobi method stops if: $$ {\|E\|}{F}\leq\operatorname{eps}\*{\|A\|}{F} $$

where eps is the given tolerance.

syevj has two parameters to control the accuracy. First parameter is tolerance (eps). The default value is machine accuracy but The user can use function cusolverDnXsyevjSetTolerance to set a priori tolerance. The second parameter is maximum number of sweeps which controls number of iterations of Jacobi method. The default value is 100 but the user can use function cusolverDnXsyevjSetMaxSweeps to set a proper bound. The experiments show 15 sweeps are good enough to converge to machine accuracy. syevj stops either tolerance is met or maximum number of sweeps is met.

The Jacobi method has quadratic convergence, so the accuracy is not proportional to number of sweeps. To guarantee certain accuracy, the user should configure tolerance only.

After syevj, the user can query residual by function cusolverDnXsyevjGetResidual and number of executed sweeps by function cusolverDnXsyevjGetSweeps. However the user needs to be aware that residual is the Frobenius norm of E, not accuracy of individual eigenvalue, i.e. $$ {residual}={\|E\|}{F} = {{\|}\Lambda - W{\|}}{F} $$

The same as syevd, the user has to provide working space pointed by input parameter work. The input parameter lwork is the size of the working space, and it is returned by syevj_bufferSize(). Please note that the size in bytes of the working space is equal to sizeof(<type>) * lwork.

If output parameter info = -i (less than zero), the i-th parameter is wrong (not counting handle). If info = n+1, syevj does not converge under given tolerance and maximum sweeps.

If the user sets an improper tolerance, syevj may not converge. For example, tolerance should not be smaller than machine accuracy.

If jobz = cusolverEigMode_t::CUSOLVER_EIG_MODE_VECTOR, A contains the orthonormal eigenvectors V.

Please visit cuSOLVER Library Samples - syevj for a code example.