Skip to content

v0.5.0

Choose a tag to compare

@physwkim physwkim released this 02 Jul 08:53
· 186 commits to main since this release

Headline: the wgpu (portable GPU) backend becomes device-resident end to end,
closing most of the gap to CUDA — analytic recon, streaming, SIRT and the
gridding recons now keep their data on the GPU across the pipeline, and the
scatter kernels use native f32 atomics (wgpu 30). The workspace is also now
self-contained (all dependencies resolve from crates.io) and gains
CI on every branch push across Linux, Windows and macOS.

Added

  • CGLS reconstruction (--algorithm cgls). Conjugate-gradient least squares
    (the standard algorithm; recurrence parity-checked against ASTRA's
    CglsAlgorithm but implemented independently — ASTRA is GPL-3.0, no ASTRA code
    is used): a Krylov solver of the same ‖Ax − b‖² normal equations as SIRT/GRAD
    but with the optimal step and conjugate directions, so it reaches a given
    residual in far fewer iterations (≈4–30× vs SIRT). Runs on every backend via
    the generic solver, plus a CUDA device-resident fast path (per-slice dot/axpy
    kernels; one upload / one download across all iterations). Parameter-free;
    supports warm-start chaining. No built-in regularization, so it needs early
    stopping on ill-posed data.
  • Per-stage iteration budgets in algorithm chains. An iterative stage in a
    --algorithm chain can carry a :iters suffix
    (e.g. --algorithm fbp,sirt:30,tv:10); stages without one fall back to
    --num_iter. Analytic stages reject the suffix. Lets a chain spend, say, 30
    SIRT iterations then 10 TV iterations in one run — previously every stage shared
    a single --num_iter.
  • Continuous integration (GitHub Actions). Runs on every branch push and
    every pull request: rustfmt, then a per-platform matrix — Linux/x86_64,
    Windows/x86_64, macOS/arm64 — each running clippy -D warnings, the test
    suite and doctests on the default (CPU) build plus a gpu-wgpu compile-check,
    and a Linux job that type-checks the CUDA FFI bindings without an nvcc toolkit.

Changed

  • wgpu backend upgraded to wgpu 30 (from 23). Enables SHADER_FLOAT32_ATOMIC
    (Vulkan VK_EXT_shader_atomic_float); devices without it fall back to the
    portable compare-exchange emulation automatically.
  • wgpu reconstruction is now device-resident. A fused analytic path keeps the
    filtered sinogram on-GPU (fbp/linerec/fourierrec); device-resident streaming
    reconstructs chunk-by-chunk (fbp/linerec/fourierrec and lprec, the latter
    caching its log-polar grids across chunks); SIRT keeps volume/sinogram resident
    across iterations; the FBP filter and the fourierrec/lprec gridding run on the
    GPU. The scatter kernels (forward projection, fourierrec gather/wrap, lprec
    gather) use native f32 atomicAdd, replacing the CAS-emulation penalty —
    forward projection ~6.6× and SIRT ~6.4× faster (same-build A/B). Net effect:
    fbp/linerec reach CUDA parity, SIRT and lprec beat CUDA on this hardware.
  • Shared host precompute sped up. lprec precomputes its FFTs on the CPU
    (rustfft) instead of a GPU round-trip (wgpu and CUDA), build_grids coordinate
    loops are parallelised with rayon, and the CPU minus_log prep is parallelised
    across the projection volume.
  • xraylib (the optional beam-hardening dependency) is now sourced from
    crates.io
    instead of an out-of-repo path dependency, so a fresh clone / CI
    resolves the workspace without a sibling checkout. Local development against a
    sibling checkout can override via [patch.crates-io].

Fixed

  • wgpu forward projection now applies the π/nproj adjoint gain, so the
    {A, Aᵀ} pair is matched — fixes forward_project output scale and the
    iterative solvers built on it (SIRT).
  • stripe TI block-size division uses checked_div (satisfies
    clippy::manual_checked_ops, new on stable Rust 1.96).
  • HDF5 test fixtures were swallowed by the repo-wide *.h5 gitignore and
    never committed; they are now tracked so the test suite runs on a fresh clone.