pub struct ModelSpec {Show 15 fields
pub id: &'static str,
pub name: &'static str,
pub stage: ModelStage,
pub status: WeightStatus,
pub origin: Framework,
pub description: &'static str,
pub paper: &'static str,
pub source: &'static str,
pub license: &'static str,
pub files: &'static [WeightFile],
pub inputs: &'static [&'static str],
pub outputs: &'static [&'static str],
pub size_divisor: u32,
pub tile_bytes_per_voxel: Option<u64>,
pub memory: NetworkMemory,
}Expand description
A deep-learning QSM model and everything needed to obtain and run it.
Fields§
§id: &'static strStable identifier, e.g. "bfrnet", "qsmnet". Used by find_model and
as the env-var suffix $QSM_MODEL_DIR.
name: &'static strHuman-readable name, e.g. "BFRnet".
stage: ModelStageReconstruction stage this model implements.
status: WeightStatusWhether the weights are hosted and ready.
origin: FrameworkFramework the weights came from (before ONNX export).
description: &'static strOne-line description of the method.
paper: &'static strReference (citation / DOI / arXiv).
source: &'static strUpstream code repository.
license: &'static strLicense / redistribution note for the weights.
files: &'static [WeightFile]ONNX weight file(s) required at inference time.
inputs: &'static [&'static str]ONNX graph input tensor name(s), in the order the runner feeds them.
outputs: &'static [&'static str]ONNX graph output tensor name(s).
size_divisor: u32Spatial dimensions must be zero-padded to a multiple of this before
inference (0/1 = no constraint). Fully-convolutional nets with
pooling need e.g. 8 or 16.
tile_bytes_per_voxel: Option<u64>Heap one tile of this network holds while it runs, in bytes per voxel of its padded
patch, for the networks QSM-Core runs tiled (None for the rest).
Covers the tile’s activations and everything else its wrapper allocates per tile (the
input and output patches, and for the unrolled networks their FFT buffers), as measured
in WASM, fragmentation included: the slope of the heap’s high-water against patch voxels,
one tile in flight (the browser_memory::tile_cost_* cases in tests/wasm_pipeline.rs;
examples/tile_memory_footprint.rs measures the same natively by counting allocations).
What a run holds once whatever the number of tiles (the parsed model and its plan, the
full-volume buffers) is not in it, except for the networks whose wrapper loads the network
inside every patch (LPCNN, MoDL-QSM, NeXtQSM): each of their tiles in flight holds its own
parsed model, so their figure is a whole 64³ tile’s heap per voxel, which over-counts larger
patches slightly.
inversion::tile_bytes turns it into a tile’s bytes for a config, and it is what
inversion::tile_concurrency budgets with on WASM, so a host estimating a tiled run’s
memory should use this same figure.
memory: NetworkMemoryHeap the network takes in tract: the parsed model, and one inference as a function of its
input shape. See ModelSpec::inference_bytes and the module docs.
Implementations§
Source§impl ModelSpec
impl ModelSpec
Sourcepub fn tile_cost(&self) -> Option<TileCost>
pub fn tile_cost(&self) -> Option<TileCost>
The cost of one tile of this network, for the networks QSM-Core runs tiled. The tiled
wrappers budget with it, and a host estimating a tiled run’s memory should use it too
(inversion::tile_bytes, inversion::wasm_tiles_in_flight).
Sourcepub fn inference_bytes(&self, shape: [usize; 3]) -> u64
pub fn inference_bytes(&self, shape: [usize; 3]) -> u64
Native peak heap of one inference of this network at input spatial shape shape, above
the resident model (Self::resident_bytes), in bytes:
NetworkMemory::inference_fixed_bytes + voxels · NetworkMemory::inference_bytes_per_voxel.
shape is the spatial shape of the tensor the network itself sees: a tile’s or window’s
patch, or for a whole-volume run the volume after the wrapper’s padding (to
Self::size_divisor; for HD-BET to multiples of 16×32×32 in its (z, y, x) order, see
crate::bet::hd_bet_network_input). Only its number of voxels matters. Pass the spatial
shape even for networks with several input channels (χ-separation, MoDL-QSM) or inputs
(iQSM): those are counted. Fixed-shape networks (RS2-Net, AutoQSM, QSMGAN) always see their
patch; pass that.
It covers the plan tract builds for the shape (its copy of the weights and per-shape
tables), the input and output tensors, the activations and tract’s scratch, both for a plan
built per call (onnx::OnnxModel::run) and for one built once and reused
(onnx::OnnxModel::plan_for). A wrapper’s own buffers (the padded volume, overlap
accumulators, test-time flips, pre- and post-processing) come on top, as do further tiles
in flight. Measured single-threaded: with the parallel feature, 8–16 threads added
1–13 MB (0.1–0.6 %) for HD-BET, SynthSeg and xQSM.
Sourcepub fn resident_bytes(&self) -> u64
pub fn resident_bytes(&self) -> u64
Heap the parsed model holds while loaded, in bytes (NetworkMemory::resident_bytes).
Sourcepub fn peak_bytes(&self, shape: [usize; 3], heap: Heap) -> u64
pub fn peak_bytes(&self, shape: [usize; 3], heap: Heap) -> u64
Peak heap of loading this network and running it once at input spatial shape shape
(as for Self::inference_bytes), in bytes: what one inference needs besides the
caller’s own buffers and the weight file’s bytes.
Heap::Native: the larger of parsing the model (NetworkMemory::load_peak_bytes) and the resident model plusSelf::inference_bytes.Heap::Wasm32: the growth of awasm32linear memory over the same,NetworkMemory::wasm_fixed_bytes+ voxels ·NetworkMemory::wasm_bytes_per_voxel(at least the load peak). Between 0.8 and 1.6 times the native figure, depending on the network and the shape: the WASM allocator cannot reuse every freed block for the next, larger tensor.
Sourcepub fn is_available(&self) -> bool
pub fn is_available(&self) -> bool
true if every weight file has a non-empty URL and hash (i.e. hosted).
Trait Implementations§
Auto Trait Implementations§
impl Freeze for ModelSpec
impl RefUnwindSafe for ModelSpec
impl Send for ModelSpec
impl Sync for ModelSpec
impl Unpin for ModelSpec
impl UnsafeUnpin for ModelSpec
impl UnwindSafe for ModelSpec
Blanket Implementations§
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
impl<T> CloneAny for T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSend for T
impl<T> DowncastSend for T
§impl<T> DowncastSync for T
impl<T> DowncastSync for T
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