pub enum SvdDriver {
Auto,
Gesvdj,
Gesvd,
Xgesvdp,
}Expand description
cuSOLVER SVD routine selection used by SvdOptions on the CUDA backend.
The driver changes speed and numerical behavior; Self::Xgesvdp may
perturb near-singular inputs. Gauge handling and AD rule selection are
unchanged. CPU providers have a single SVD kernel and ignore the driver.
Equivalent to jax.lax.linalg.svd(..., algorithm=...) and
torch.linalg.svd(..., driver=...).
§Examples
use tenferro_linalg::{SvdDriver, SvdOptions};
let options = SvdOptions::default().driver(SvdDriver::Gesvd);
assert_eq!(options.driver, SvdDriver::Gesvd);
assert_eq!(SvdOptions::default().driver, SvdDriver::Auto);Variants§
Auto
The backend’s default policy. On CUDA this is the accuracy-preserving,
JAX-compatible rule: gesvdj when both matrix dimensions are at most
1024, otherwise gesvd. It never selects the polar
Self::Xgesvdp, whose small singular values are only accurate to
about 1e-6 of the largest (#2182). CPU providers have a single SVD
kernel and ignore the driver.
Gesvdj
cuSOLVER’s Jacobi driver (cusolverDn<t>gesvdj) regardless of size.
Gesvd
cuSOLVER’s QR-based driver (cusolverDn<t>gesvd) regardless of size.
Xgesvdp
cuSOLVER’s polar-decomposition driver (cusolverDnXgesvdp).
Explicit only: Self::Auto never selects this routine. It is the
fastest of the three drivers for min(m, n) >= 256 on an A100 (see the
cuda_svd_driver benchmark), but its small singular values are only
accurate to about 1e-6 of the largest singular value. Do not use it
for an eps-scale truncation (a pseudoinverse or tensor-network
truncation at 1e-12..1e-14): the perturbation can change the
retained rank.
Tenferro reads cuSOLVER’s h_err_sigma perturbation bound and returns a
typed backend failure instead of silently wrong factors when it is not
small relative to the largest singular value. On rank-deficient
F32/C32 input cuSOLVER reports a perturbation comparable to the
spectrum, so an explicit single-precision call there fails rather than
returning the perturbed values. CPU providers accept and ignore this
selection.
Accuracy is input-dependent, not uniformly better or worse than
Self::Gesvd. On ten-decade spectra built as U diag(s) Vᴴ it was
the most accurate of the three drivers on an A100, but on a
circulant-like matrix with the same spectrum it lost about two digits
against gesvd. Measure on your own inputs before relying on it for
small singular values.
Trait Implementations§
impl Copy for SvdDriver
impl Eq for SvdDriver
impl StructuralPartialEq for SvdDriver
Auto Trait Implementations§
impl Freeze for SvdDriver
impl RefUnwindSafe for SvdDriver
impl Send for SvdDriver
impl Sync for SvdDriver
impl Unpin for SvdDriver
impl UnsafeUnpin for SvdDriver
impl UnwindSafe for SvdDriver
Blanket Implementations§
impl<T> Boilerplate for T
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
impl<T, U> Imply<T> for U
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more