1.13. Very large models

RISE is built to handle very large models – the parser and the post-parse pipeline are engineered so that models with several thousand equations, shocks and parameters go through end to end (parse, build the auxiliary structures, differentiate, solve). Models of upwards of ~6000 equations, ~3900 shocks and ~7000 parameters parse successfully.

1.13.1. Why RISE requires MATLAB R2023b

Scalability rests on using the right data structures. Throughout parsing, RISE looks up variables, parameters, equations, lead/lag atoms and so on by name an enormous number of times; doing that with linear scans (strcmp / find over a cell array) or with containers.Map makes the whole pipeline grow like the square of the number of equations – the wall that used to stop large models. RISE now uses MATLAB’s dictionary type for these lookups – O(1) access, bulk operations, value type. dictionary arrived in R2022b and configureDictionary in R2023b, which is why R2023b is the minimum supported release (rise_startup enforces it).

The symbolic-differentiation backend handles sparse occurrence patterns and avoids a “post-print” blow-up, so building the derivatives of a multi-thousand-equation system stays tractable.

1.13.2. Writing a large model

Large models are written in the usual model language (see Model file language) – there is nothing special to declare. In practice, though, you will not type thousands of equations by hand: use the macro language (the @#for / @#if loops, file includes, and the pseudo-functions) to generate the @endogenous / @exogenous / @parameters lists and the @model block compactly. A multi-country or multi-sector model, for instance, is naturally written as a loop over members.

1.13.3. Parsing, differentiation and memory

The first dsge_model(...) call on a very large model is the expensive step – parsing plus symbolic differentiation of the whole system. It is no longer quadratic in the number of equations, but it is still substantial in absolute terms and uses a fair amount of memory. A few practical points:

  • Parse once, then save the model object and reload it, rather than re-parsing each session.

  • RISE reuses computation where it can – common-subexpression elimination in the symbolic differentiator, and (for block-structured models such as multi-country ones) it avoids re-checking subtrees across blocks that cannot share them.

  • When the model is large because it repeats a few equations – a loop over countries or sectors, or the cells of a heterogeneous-agent model – template differentiation (on by default, template_diff) differentiates each repeated expression once and its derivatives are evaluated for all copies at once. Differentiation time and memory then stop growing with the number of copies, and the Jacobian is evaluated tens of times faster. See Template differentiation.

  • The differentiation backend is selectable: @rsymbdiff (symbolic, arbitrary order – the default) or @adolm (automatic, up to order 5). For the largest models without that repetition, the automatic backend can be more economical. The relevant solve-time options (e.g. solve_automatic_differentiator) are documented in Solving.

1.13.4. Solving a large model

First-order perturbation of a model with thousands of equations is feasible – the solvers exploit sparsity. Be aware that higher-order perturbation grows quickly with the size of the state vector (the number of distinct Kronecker columns explodes), so for the very largest models a first-order solution is the practical choice; pick solve_order with the model size in mind. Estimation, filtering, simulation and forecasting then proceed as usual on the solved object.

If the model is large because an expansion manufactured it – heterogeneous-agent models being the standard case – much of that size can be constant at the linearization point. The option solve_prune_hank_constants finds those variables and solves without them, at no cost in accuracy: the answer is identical with the option on or off. The gain grows with the model, so this page is where it matters; it is overhead-bound on small systems. See Heterogeneous agents (HANK).

Pruning leaves the size of the system that remains untouched. When that is still too large – for estimation, where the model is solved and filtered at every draw – the option solve_reduction replaces the individual variables by a few coordinates on a basis built once, and solves and filters the small system; unlike pruning, it is an approximation to validate. See Model reduction.