Summary
Compiling a moderately stratified model produces a very large IR and a long compile,
and the cost is dominated by scalar-unrolling of stratified transitions, not by
integration. A single camdl simulate spends the great majority of its wall-clock in the
compiler before the solver runs.
Observed
A model with dimensions 2 × 5 × 5 over 7 compartments (= 350 states, ~110 source
lines) compiles to a ~1.6 GB IR in ~154 s; the compile log reports a 288,895× source-node
expansion. The RK4 solve itself is fast — essentially all of the ~2.5 min is compilation.
compiled <model>.camdl 1.6GB IR in 154.0s (288895× source)
The model has ~10 transitions, several declared over [c in compartments, …] (e.g. a
death/removal term and an inter-band aging term run over every compartment × every
stratum), plus a few lets with nested sum(...) reductions over two stratum axes.
Likely cause
Transitions declared over [c in compartments, …] combined with the dimension product
appear to be fully scalar-expanded: every (compartment × stratum) cell becomes a flat
scalar IR node with no retained loop/tensor structure, so IR size scales with the full
stratum product rather than with the source. The compartment-indexed transitions are the
worst offenders, since each multiplies the already-large stratum grid by the compartment
count.
Secondary: no cross-invocation compile cache
Repeated CLI invocations of the identical model recompile it from scratch each time. A
parameter sweep run as N separate camdl simulate calls therefore pays N× the full compile
— a 5-point sweep is ~5 × 154 s ≈ 13 min of pure compilation, with zero reuse.
Asks
- Retain loop/tensor structure in the IR for stratified transitions — emit a vectorized
kernel over the stratum axes instead of scalar-unrolling into per-cell nodes, so IR size
scales with the source, not with the stratum product.
- Cache the compiled artifact keyed on model content across CLI invocations, so a sweep
(or repeated simulate/fit on an unchanged model) compiles once rather than per call.
Environment
- camdl
0.1.0+0b1fbe12 (2026-07-15)
- macOS / arm64 (Darwin 25.3.0)
Summary
Compiling a moderately stratified model produces a very large IR and a long compile,
and the cost is dominated by scalar-unrolling of stratified transitions, not by
integration. A single
camdl simulatespends the great majority of its wall-clock in thecompiler before the solver runs.
Observed
A model with dimensions
2 × 5 × 5over 7 compartments (= 350 states, ~110 sourcelines) compiles to a ~1.6 GB IR in ~154 s; the compile log reports a 288,895× source-node
expansion. The RK4 solve itself is fast — essentially all of the ~2.5 min is compilation.
The model has ~10 transitions, several declared over
[c in compartments, …](e.g. adeath/removal term and an inter-band aging term run over every compartment × every
stratum), plus a few
lets with nestedsum(...)reductions over two stratum axes.Likely cause
Transitions declared over
[c in compartments, …]combined with the dimension productappear to be fully scalar-expanded: every
(compartment × stratum)cell becomes a flatscalar IR node with no retained loop/tensor structure, so IR size scales with the full
stratum product rather than with the source. The compartment-indexed transitions are the
worst offenders, since each multiplies the already-large stratum grid by the compartment
count.
Secondary: no cross-invocation compile cache
Repeated CLI invocations of the identical model recompile it from scratch each time. A
parameter sweep run as N separate
camdl simulatecalls therefore pays N× the full compile— a 5-point sweep is ~5 × 154 s ≈ 13 min of pure compilation, with zero reuse.
Asks
kernel over the stratum axes instead of scalar-unrolling into per-cell nodes, so IR size
scales with the source, not with the stratum product.
(or repeated
simulate/fiton an unchanged model) compiles once rather than per call.Environment
0.1.0+0b1fbe12(2026-07-15)