3.3 KiB
CPU fast guided-filter memory
local::guided_fast computes blurred coefficients on the same reduced grid as before, then
samples them while applying a * p + b. It keeps the raster resizer's weights, boundary
normalization and horizontal-then-vertical accumulation order. Odd dimensions therefore use
their actual reduced/full dimension ratios. Four coefficient row pairs and one bias row are cached
per active 32-row band; adjacent output rows reuse their horizontal samples.
The two full-resolution coefficient planes and their resize intermediates are gone. The returned full-resolution base remains: downstream CPU tone mapping and the spatial-plane cache need it. The step-1 filter, Box reduction, Gaussian coefficients, V2's median input, process selection and Draft sigma cap are unchanged. The GPU implementation is unchanged; this reduces CPU memory only.
Reproduce
The dev-only example includes the previous materialized algorithm and uses the workspace's
existing dhat allocator. No allocator or profiling dependency is added to product builds.
cargo build --release -p lightcraft-pipeline --example guided_memory
RAYON_NUM_THREADS=1 target/release/examples/guided_memory old 6000 4000 120 15
RAYON_NUM_THREADS=1 target/release/examples/guided_memory new 6000 4000 120 15
RAYON_NUM_THREADS=1 target/release/examples/guided_memory old 6000 4000 120 1 --heap
RAYON_NUM_THREADS=1 target/release/examples/guided_memory new 6000 4000 120 1 --heap
If CARGO_TARGET_DIR is set, use that directory instead of target for the executable.
Arguments are mode, width, height, integer sigma and timing iterations. The example warms up
before measurement; --heap counts one filter call with the source allocated beforehand.
Time the runs without --heap: allocation profiling significantly changes timings. It reports
the minimum wall time; on a shared machine repeat when other builds/renders have stopped.
Use LIGHTCRAFT_PROFILE=1 and cargo xtask bench for broader pipeline measurements.
Observed allocation and time
Measured 2026-10-16 UTC, macOS aarch64, Rust 1.96.0, release build, one Rayon thread. Bytes are requested heap bytes counted by dhat, not process RSS. Timings are minimums of 15 unprofiled calls on a shared machine with concurrent builds; they are indicative, not a speed guarantee.
| Dimensions / sigma / step | Old peak bytes | New peak bytes | Old total allocated bytes | New total allocated bytes | Old / new wall ms |
|---|---|---|---|---|---|
| 6000 × 4000 / 120 / 16 | 289,125,000 | 97,780,856 | 313,083,488 | 135,643,856 | 42.135 / 45.131 |
| 1601 × 1067 / 24 / 8 | 20,822,412 | 7,331,172 | 25,102,604 | 11,562,560 | 3.359 / 3.121 |
The 24 MP result saves about 191 MB of peak allocation (66%). Its 96,000,000-byte output is included; its 96,000,000-byte input is excluded. Application RGB images, log luminance, V2 median input and its construction temporaries, other spatial planes and caches also remain outside this isolated measurement. More Rayon threads can hold more band scratch concurrently. This is not a bound on total pipeline memory.
Regression tests compare the sampled result exactly against materialized bilinear resizes for empty/singleton/one-dimensional, odd/even and multiple-band images; flat fields, signed texture, edges and impulses; small/full and reduced filters; and median tone bases.