---
title: "ClikaRT::nn::Module"
sidebar_label: "Module"
description: "Base class of every ClikaRT module: an ownership tree of parameters, buffers, and child modules."
---

<!-- Generated by tools/doxygen2mdx from Doxygen XML. Do not edit. -->

<span class="api-kind api-kind--class">class</span>

**Header:** `ClikaRT/nn/module.h`  
**Inherits:** `std::enable_shared_from_this<Module>`  
**Inherited by:** [`ClikaRT::nn::AdaptiveAvgPool1d`](./AdaptiveAvgPool1d.md), [`ClikaRT::nn::AdaptiveAvgPool2d`](./AdaptiveAvgPool2d.md), [`ClikaRT::nn::AdaptiveAvgPool3d`](./AdaptiveAvgPool3d.md), [`ClikaRT::nn::AdaptiveMaxPool1d`](./AdaptiveMaxPool1d.md), [`ClikaRT::nn::AdaptiveMaxPool2d`](./AdaptiveMaxPool2d.md), [`ClikaRT::nn::AdaptiveMaxPool3d`](./AdaptiveMaxPool3d.md), [`ClikaRT::nn::Add`](./Add.md), [`ClikaRT::nn::Attention`](./Attention.md), [`ClikaRT::nn::AvgPool1d`](./AvgPool1d.md), [`ClikaRT::nn::AvgPool2d`](./AvgPool2d.md), [`ClikaRT::nn::AvgPool3d`](./AvgPool3d.md), [`ClikaRT::nn::BCELoss`](./BCELoss.md), [`ClikaRT::nn::BCEWithLogitsLoss`](./BCEWithLogitsLoss.md), [`ClikaRT::nn::BatchNorm`](./BatchNorm.md), [`ClikaRT::nn::CELU`](./CELU.md), [`ClikaRT::nn::CircularPad`](./CircularPad.md), [`ClikaRT::nn::Clamp`](./Clamp.md), [`ClikaRT::nn::ConstantPad`](./ConstantPad.md), [`ClikaRT::nn::Conv`](./Conv.md), [`ClikaRT::nn::ConvTranspose`](./ConvTranspose.md), [`ClikaRT::nn::CosineSimilarity`](./CosineSimilarity.md), [`ClikaRT::nn::CrossEntropyLoss`](./CrossEntropyLoss.md), [`ClikaRT::nn::Div`](./Div.md), [`ClikaRT::nn::Dropout`](./Dropout.md), [`ClikaRT::nn::ELU`](./ELU.md), [`ClikaRT::nn::Embedding`](./Embedding.md), [`ClikaRT::nn::Flatten`](./Flatten.md), [`ClikaRT::nn::Fold`](./Fold.md), [`ClikaRT::nn::GELU`](./GELU.md), [`ClikaRT::nn::GLU`](./GLU.md), [`ClikaRT::nn::GeGLU`](./GeGLU.md), [`ClikaRT::nn::GroupNorm`](./GroupNorm.md), [`ClikaRT::nn::Hardshrink`](./Hardshrink.md), [`ClikaRT::nn::Hardsigmoid`](./Hardsigmoid.md), [`ClikaRT::nn::Hardswish`](./Hardswish.md), [`ClikaRT::nn::Hardtanh`](./Hardtanh.md), [`ClikaRT::nn::HuberLoss`](./HuberLoss.md), [`ClikaRT::nn::Identity`](./Identity.md), [`ClikaRT::nn::InstanceNorm`](./InstanceNorm.md), [`ClikaRT::nn::KLDivLoss`](./KLDivLoss.md), [`ClikaRT::nn::L1Loss`](./L1Loss.md), [`ClikaRT::nn::LayerNorm`](./LayerNorm.md), [`ClikaRT::nn::LeakyReLU`](./LeakyReLU.md), [`ClikaRT::nn::Linear`](./Linear.md), [`ClikaRT::nn::LogSigmoid`](./LogSigmoid.md), [`ClikaRT::nn::LogSoftmax`](./LogSoftmax.md), [`ClikaRT::nn::MSELoss`](./MSELoss.md), [`ClikaRT::nn::MaxPool1d`](./MaxPool1d.md), [`ClikaRT::nn::MaxPool2d`](./MaxPool2d.md), [`ClikaRT::nn::MaxPool3d`](./MaxPool3d.md), [`ClikaRT::nn::Maximum`](./Maximum.md), [`ClikaRT::nn::Minimum`](./Minimum.md), [`ClikaRT::nn::Mish`](./Mish.md), [`ClikaRT::nn::MoE`](./MoE.md), [`ClikaRT::nn::ModuleDict`](./ModuleDict.md), [`ClikaRT::nn::ModuleList`](./ModuleList.md), [`ClikaRT::nn::Mul`](./Mul.md), [`ClikaRT::nn::NLLLoss`](./NLLLoss.md), [`ClikaRT::nn::PReLU`](./PReLU.md), [`ClikaRT::nn::PairwiseDistance`](./PairwiseDistance.md), [`ClikaRT::nn::PixelShuffle`](./PixelShuffle.md), [`ClikaRT::nn::PixelUnshuffle`](./PixelUnshuffle.md), [`ClikaRT::nn::Pow`](./Pow.md), [`ClikaRT::nn::QConv`](./QConv.md), [`ClikaRT::nn::QConvWoQ`](./QConvWoQ.md), [`ClikaRT::nn::QEmbedding`](./QEmbedding.md), [`ClikaRT::nn::QMoEWoQ`](./QMoEWoQ.md), [`ClikaRT::nn::RMSNorm`](./RMSNorm.md), [`ClikaRT::nn::ReGLU`](./ReGLU.md), [`ClikaRT::nn::ReLU`](./ReLU.md), [`ClikaRT::nn::ReLU6`](./ReLU6.md), [`ClikaRT::nn::ReflectionPad`](./ReflectionPad.md), [`ClikaRT::nn::ReplicationPad`](./ReplicationPad.md), [`ClikaRT::nn::RotaryEmbedding`](./RotaryEmbedding.md), [`ClikaRT::nn::SELU`](./SELU.md), [`ClikaRT::nn::Sequential`](./Sequential.md), [`ClikaRT::nn::SiLU`](./SiLU.md), [`ClikaRT::nn::Sigmoid`](./Sigmoid.md), [`ClikaRT::nn::SmoothL1Loss`](./SmoothL1Loss.md), [`ClikaRT::nn::Softmax`](./Softmax.md), [`ClikaRT::nn::Softmin`](./Softmin.md), [`ClikaRT::nn::Softplus`](./Softplus.md), [`ClikaRT::nn::Softshrink`](./Softshrink.md), [`ClikaRT::nn::Softsign`](./Softsign.md), [`ClikaRT::nn::Sub`](./Sub.md), [`ClikaRT::nn::SwiGLU`](./SwiGLU.md), [`ClikaRT::nn::Tanh`](./Tanh.md), [`ClikaRT::nn::Threshold`](./Threshold.md), [`ClikaRT::nn::Unflatten`](./Unflatten.md), [`ClikaRT::nn::Unfold`](./Unfold.md), [`ClikaRT::nn::Upsample`](./Upsample.md), [`ClikaRT::nn::Where`](./Where.md), [`ClikaRT::nn::ZeroPad`](./ZeroPad.md)

Base class of every [ClikaRT](../../index.md) module: an ownership tree of parameters, buffers, and child modules.

Lifecycle: construct (register tensors and children) -\> [`load_state_dict`](./Module.md#load_state_dict) or `set_weights` binds a checkpoint onto the registered names -\> `to(...)` places or casts the tree -\> `forward`. The first forward packs each weight into its backend form, once and thread-safe ([`LoadOptions::pack_on_load`](./LoadOptions.md#pack_on_load) pays that pack at the end of the load instead); after the pack exactly ONE resident copy of each weight exists, and [`named_parameters()`](./Module.md#named_parameters) / [`state_dict()`](./Module.md#state_dict) stay total before and after it: a packed weight reads back from its pack as a fresh owning tensor, at its registered name and position. Held by `std::shared_ptr` (module trees share children).

## Member functions

### \~Module() {#Module}

<div class="api-signature">

`virtual` **`~Module`**()

</div>

Virtual base destructor; derived modules release their packed weights.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 202

</div>

### Module(Module) {#Module-2}

<div class="api-signature">

**`Module`**(`const Module&`) `=delete`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 204

</div>

### operator=(Module) {#operator-assign}

<div class="api-signature">

[`Module`](./Module.md)`&` **`operator=`**(`const` [`Module`](./Module.md)`&`) `=delete`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 205

</div>

### Module(Module) {#Module-3}

<div class="api-signature">

**`Module`**(`Module&&`) `=delete`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 206

</div>

### operator=(Module) {#operator-assign-2}

<div class="api-signature">

[`Module`](./Module.md)`&` **`operator=`**([`Module`](./Module.md)`&&`) `=delete`

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 207

</div>

### register\_parameter(string\_view, Tensor) {#register_parameter}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`register_parameter`**(`std::string_view` `name`, [`Tensor`](../Tensor.md) `tensor`)

</div>

Register `tensor` as a learnable parameter under `name`; returns the registered handle (shares `tensor`'s storage).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 216

</div>

### register\_buffer(string\_view, Tensor) {#register_buffer}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`register_buffer`**(`std::string_view` `name`, [`Tensor`](../Tensor.md) `tensor`)

</div>

Register `tensor` as a non-learnable buffer under `name`; returns the registered handle (shares `tensor`'s storage).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 219

</div>

### register\_parameter(string\_view, FakeTensor) {#register_parameter-2}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`register_parameter`**(`std::string_view` `name`, `const` [`FakeTensor`](../FakeTensor.md)`&` `spec`)

</div>

Declare a storage-free SLOT from a metadata spec (shape / dtype / placement): the slot enumerates under its dotted name, so [`load_state_dict`](./Module.md#load_state_dict) matches it and binds the checkpoint tensor onto the spec's placement + dtype, and reads as [`Tensor::is_fake()`](../Tensor.md#is_fake) until bound. A module built this way holds no weight memory until loading. The returned handle is the registered slot; re-registering the same name (e.g. with a real tensor) replaces it, keeping its position.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 227

</div>

### register\_buffer(string\_view, FakeTensor) {#register_buffer-2}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`register_buffer`**(`std::string_view` `name`, `const` [`FakeTensor`](../FakeTensor.md)`&` `spec`)

</div>

Declare a storage-free buffer slot under `name` from the metadata [`spec`](../spec/index.md); a later bind fills it (the buffer twin of the parameter overload above).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 231

</div>

### register\_buffer(string\_view, Tensor, bool) {#register_buffer-3}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`register_buffer`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::string_view` `name`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Tensor`](../Tensor.md) `tensor`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`bool` `persistent`<br />
)

</div>

[`register_buffer`](./Module.md#register_buffer) with a persistence choice. A NON-persistent buffer (`persistent == false`) enumerates through [`named_buffers()`](./Module.md#named_buffers) and moves and casts with the tree, but stays OUT of [`state_dict()`](./Module.md#state_dict), and [`load_state_dict`](./Module.md#load_state_dict) neither expects it nor binds it (a table the module derives itself, a cache). The two-argument forms register persistent buffers.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 238

</div>

### register\_buffer(string\_view, FakeTensor, bool) {#register_buffer-4}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`register_buffer`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::string_view` `name`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`const` [`FakeTensor`](../FakeTensor.md)`&` `spec`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`bool` `persistent`<br />
)

</div>

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 239

</div>

### register\_module() {#register_module}

<div class="api-signature">

`void` **`register_module`**(`std::string_view` `name`, `std::shared_ptr<`[`Module`](./Module.md)`>` `module`)

</div>

Attach a child module under `name` (the tree edge `name.child_key` names its tensors).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 242

</div>

### release\_parameter() {#release_parameter}

<div class="api-signature">

`void` **`release_parameter`**(`std::string_view` `name`)

</div>

Erase THIS module's parameter slot `name` (no dots) from the registry: a slot bound from a checkpoint's own mapping hands its pages back to the file first, then the entry goes. An absent name is a no-op success; a bound, live slot is released the same way (the caller owns the one-copy law: call it only once every reader of the raw values has finished).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 257

</div>

### release\_buffer() {#release_buffer}

<div class="api-signature">

`void` **`release_buffer`**(`std::string_view` `name`)

</div>

The buffer twin of [`release_parameter`](./Module.md#release_parameter): erase THIS module's buffer slot `name` (no dots), pages first. Same absent-name and live-slot contract.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 261

</div>

### named\_parameters() {#named_parameters}

<div class="api-signature">

`std::vector<std::pair<std::string,` [`Tensor`](../Tensor.md)`>>` **`named_parameters`**(`bool` `recurse` `=` `true`) `const`

</div>

All parameters as `(dotted-name, tensor)` pairs; `recurse` walks children. A tensor shared under several names appears once, under the first. A weight a layer has packed for serving reads back from the pack as a fresh owning tensor, at its own name and position, so the list is total before and after the pack.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 272

</div>

### named\_buffers() {#named_buffers}

<div class="api-signature">

`std::vector<std::pair<std::string,` [`Tensor`](../Tensor.md)`>>` **`named_buffers`**(`bool` `recurse` `=` `true`) `const`

</div>

All buffers as `(dotted-name, tensor)` pairs, persistent and non-persistent alike; `recurse` walks children.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 275

</div>

### named\_children() {#named_children}

<div class="api-signature">

`std::vector<std::pair<std::string, std::shared_ptr<`[`Module`](./Module.md)`>>>` **`named_children`**() `const`

</div>

Direct children as `(name, module)` pairs.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 277

</div>

### parameters() {#parameters}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`parameters`**(`bool` `recurse` `=` `true`) `const`

</div>

All parameter tensors (names dropped); `recurse` walks children.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 280

</div>

### buffers() {#buffers}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`buffers`**(`bool` `recurse` `=` `true`) `const`

</div>

All buffer tensors (names dropped); `recurse` walks children.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 283

</div>

### state\_dict() {#state_dict}

<div class="api-signature">

[`NamedTensors`](../NamedTensors.md) **`state_dict`**(`bool` `recurse` `=` `true`) `const`

</div>

The module's checkpoint view: every named parameter and every PERSISTENT named buffer under its dotted name, the [`load_state_dict`](./Module.md#load_state_dict) dual: a dict taken here loads back exactly, before or after a pack (a packed weight reads back from its pack as a fresh owning tensor; still-bound entries share storage with the module). A slot released after a fold ([`release_parameter`](./Module.md#release_parameter) / [`release_buffer`](./Module.md#release_buffer)) is not in the dict: its values live in the form that consumed them.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 291

</div>

### get\_parameter() {#get_parameter}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`get_parameter`**(`std::string_view` `target`) `const`

</div>

ONE parameter by its dotted name (`"layers.0.weight"`): the bound tensor (shares storage with the module) or, for a weight the layer has packed, a fresh owning read-back of that one slot from the pack.

**Throws**

- `ClikaRT::Error`: when no parameter carries the name.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 298

</div>

### get\_buffer() {#get_buffer}

<div class="api-signature">

[`Tensor`](../Tensor.md) **`get_buffer`**(`std::string_view` `target`) `const`

</div>

ONE buffer by its dotted name, persistent or not.

**Throws**

- `ClikaRT::Error`: when no buffer carries the name.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 302

</div>

### parameter\_spec() {#parameter_spec}

<div class="api-signature">

[`FakeTensor`](../FakeTensor.md) **`parameter_spec`**(`std::string_view` `target`) `const`

</div>

The dtype, shape, placement and quantized flag of the parameter slot at dotted `target`, read with NO reconstruction: a packed weight answers with the geometry its carrier recorded and the dtype and quantized flag the weight had when it packed (never the carrier's own dtype, which is what a re-bind accepts), an unpacked one with its own metadata. The read a dtype probe wants after a load with `pack_on_load` ([`get_parameter`](./Module.md#get_parameter) reads the whole weight back for it).

**Throws**

- `ClikaRT::Error`: when a submodule on the way or the slot does not exist.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 313

</div>

### to(StreamOrDevice) {#to}

<div class="api-signature">

`void` **`to`**([`StreamOrDevice`](../StreamOrDevice.md) `where`)

</div>

Move the tree to a placement: a [`Device`](../Device.md), or a [`Stream`](../Stream.md) so the tree computes on that stream and lands its outputs there (the lane-placement call: build/load once, `to(lane)` once, forward every step). Children move first; a packed leaf ([`Linear`](./Linear.md) / [`QLinearWoQ`](./QLinearWoQ.md) / [`MoE`](./MoE.md) / [`QMoEWoQ`](./QMoEWoQ.md)) rebuilds its pack on the target, and a still-fake slot re-declares its metadata there.

**Throws**

- `ClikaRT::Error`: when the tree cannot move as asked.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 332

</div>

### can\_cast\_to\_impl() {#can_cast_to_impl}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`can_cast_to_impl`**([`DataType`](../../index.md#DataType) `dtype`) `const`

</div>

Whether THIS module's own slots can be cast to [`dtype`](../dtype/index.md) (children are asked by the tree walk, never here). A failure is the refusal `to(dtype)` would raise; `Module::to(dtype)` asks every module of the tree BEFORE it casts any, so a refused cast leaves the tree untouched and names the leaf. Default: a dense module casts. Override in a leaf that pins its dtype.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 339

</div>

### to(DataType) {#to-2}

<div class="api-signature">

`void` **`to`**([`DataType`](../../index.md#DataType) `dtype`)

</div>

Cast the tree's parameters/buffers to [`dtype`](../dtype/index.md) (children first), ATOMICALLY: every module of the tree is asked [`can_cast_to_impl`](./Module.md#can_cast_to_impl) before any slot is cast, so a refusal (a quantized leaf, a shared weight) leaves the whole tree at its prior dtypes and names the refusing module. A dense packed leaf restores its raw weights, casts, and re-packs on the next forward; quantized leaves refuse dtype moves.

**Throws**

- `ClikaRT::Error`: when the cast cannot be served (a quantized leaf, e.g.).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 347

</div>

### to(StreamOrDevice, DataType) {#to-3}

<div class="api-signature">

`void` **`to`**([`StreamOrDevice`](../StreamOrDevice.md) `where`, [`DataType`](../../index.md#DataType) `dtype`)

</div>

Cast, then place: `to(dtype)` followed by `to(where)`, in the order that re-packs ONCE. The cast restores a packed dense weight from its pack, casts it and drops the pack; the move then carries the unpacked slots to `where`, and the next forward (or a later load with `pack_on_load`) packs once, on the target.

**Throws**

- `ClikaRT::Error`: when either half cannot be served (a quantized leaf refuses the cast).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 355

</div>

### load\_state\_dict(NamedTensors, LoadOptions) {#load_state_dict}

<div class="api-signature">

`void` **`load_state_dict`**([`NamedTensors`](../NamedTensors.md) `checkpoint`, [`LoadOptions`](./LoadOptions.md) `options` `=` `{}`)

</div>

Bind every parameter/buffer whose dotted name is present in `checkpoint` (placed on the slot's declared device + dtype). With `options.strict`, raises [`ClikaRT::Error`](../Error.md) if any declared name is missing from the checkpoint or any checkpoint key is unexpected, minus the per-name allowances in `options`, the same completeness verdict the container overload below applies. The dict is taken by value: pass it with `std::move` for the one-copy load (this call drops its own handle before the `pack_on_load` pack runs, so no weight is held twice); an lvalue keeps the caller's own pin on every bound tensor until the caller drops it. Note: a bare braced second argument ([`load_state_dict`](./Module.md#load_state_dict)`(ckpt, {…})`) is ambiguous against the strictness-only overload below; spell [`LoadOptions`](./LoadOptions.md)`{…}` (or a named local) explicitly.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 372

</div>

### load\_state\_dict(NamedTensors, bool) {#load_state_dict-2}

<div class="api-signature">

`void` **`load_state_dict`**([`NamedTensors`](../NamedTensors.md) `checkpoint`, `bool` `strict`)

</div>

Bind every parameter/buffer whose dotted name is present in `checkpoint` (placed on the slot's declared device + dtype). With `options.strict`, raises [`ClikaRT::Error`](../Error.md) if any declared name is missing from the checkpoint or any checkpoint key is unexpected, minus the per-name allowances in `options`, the same completeness verdict the container overload below applies. The dict is taken by value: pass it with `std::move` for the one-copy load (this call drops its own handle before the `pack_on_load` pack runs, so no weight is held twice); an lvalue keeps the caller's own pin on every bound tensor until the caller drops it. Note: a bare braced second argument ([`load_state_dict`](./Module.md#load_state_dict)`(ckpt, {…})`) is ambiguous against the strictness-only overload below; spell [`LoadOptions`](./LoadOptions.md)`{…}` (or a named local) explicitly.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 378

</div>

### load\_state\_dict(io::TensorsContainer, LoadOptions) {#load_state_dict-3}

<div class="api-signature">

`void` **`load_state_dict`**([`io::TensorsContainer`](../io/TensorsContainer.md)`&` `checkpoint`, [`LoadOptions`](./LoadOptions.md) `options` `=` `{}`)

</div>

Bind every parameter/buffer whose dotted name is present in `checkpoint` (placed on the slot's declared device + dtype). With `options.strict`, raises [`ClikaRT::Error`](../Error.md) if any declared name is missing from the checkpoint or any checkpoint key is unexpected, minus the per-name allowances in `options`, the same completeness verdict the container overload below applies. The dict is taken by value: pass it with `std::move` for the one-copy load (this call drops its own handle before the `pack_on_load` pack runs, so no weight is held twice); an lvalue keeps the caller's own pin on every bound tensor until the caller drops it. Note: a bare braced second argument ([`load_state_dict`](./Module.md#load_state_dict)`(ckpt, {…})`) is ambiguous against the strictness-only overload below; spell [`LoadOptions`](./LoadOptions.md)`{…}` (or a named local) explicitly.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 394

</div>

### init\_weights() {#init_weights}

<div class="api-signature">

`void` **`init_weights`**(`const` [`InitSpec`](./InitSpec.md)`&` `spec`)

</div>

Give every storage-free slot of the tree (a parameter or buffer declared from a [`FakeTensor`](../FakeTensor.md) spec and not yet bound) real storage on the slot's declared placement and dtype, filled per [`spec`](../spec/index.md): the base kind, or the first override row naming the slot ([`InitSpec`](./InitSpec.md)). The tree is walked in registration order, self then children. A slot that already holds storage is left alone unless `spec.reinit_materialized`, which fills it in place; a weight the module has packed stays packed either way. [`parameter_spec`](./Module.md#parameter_spec) reads the same metadata before and after. The fills are ordinary operators, so under a [`TracingScope`](../TracingScope.md) the slots take placeholders and no kernel runs. Raises [`ClikaRT::Error`](../Error.md) naming the slot for a symbolic dimension, a slot with no dtype, a negative standard deviation, an override key that is neither a slot's name nor a valid pattern, or a `Normal` override aimed at a slot whose dtype is not floating point.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 412

</div>

### output\_shapes() {#output_shapes}

<div class="api-signature">

`virtual` `std::vector<`[`FakeTensor`](../FakeTensor.md)`>` **`output_shapes`**([`ClikaRT::Span`](../Span.md)`<const` [`FakeTensor`](../FakeTensor.md)`>`) `const`

</div>

Shape rule: read input metadata (each input a [`FakeTensor`](../FakeTensor.md): `SymInt` dims, dtype, placement, quantized flag) → output [`FakeTensor`](../FakeTensor.md)s. Compose dimensions with `SymInt` / `SymFloat`; declare a data-dependent extent with `SymInt::unknown(...)`. Outputs are placed on the op's stream (derived from the inputs), so the output [`FakeTensor`](../FakeTensor.md)'s placement is informational. An exception thrown here surfaces as the [`dispatch`](./Module.md#dispatch) call's error (a [`ClikaRT::Error`](../Error.md) keeps its [`Status`](../../index.md#Status); any other exception reports [`Status::Internal`](../../index.md#Status)). Default: an error (a composite module never calls [`dispatch`](./Module.md#dispatch), so it need not override this).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 424

</div>

### compute() {#compute}

<div class="api-signature">

`virtual` `void` **`compute`**([`ClikaRT::Span`](../Span.md)`<const` [`Tensor`](../Tensor.md)`>`, [`ClikaRT::Span`](../Span.md)`<`[`Tensor`](../Tensor.md)`>`) `const`

</div>

Kernel: `outputs` arrive pre-allocated on the op's device (sharing storage). Read inputs and write outputs through the pointers that match where the kernel runs. `device_const_data_ptr()` / `device_mutable_data_ptr()` are for a kernel on the op's device: no host wait, and the pointer is ordered on the op's stream. `const_data_ptr()` / `mutable_data_ptr()` are for a plain host loop over CPU-resident tensors: they wait for the data and refuse a device tensor. The runtime binds the op's stream (read it with `this->`[`stream()`](./Module.md#stream)) and makes its device current before calling this, so a GPU kernel launches on the right device.

This is the hand-written-kernel hook. [`compute()`](./Module.md#compute) runs on whatever device its tensors live on; branch on `this->`[`stream()`](./Module.md#stream)`.`[`device()`](../device-namespace/index.md) and launch directly:

```cpp
Stream s = this->stream();                                     // the op's stream
auto cu = static_cast<cudaStream_t>(s.native_handle());        // the queue
const float* q = static_cast<const float*>(inputs[0].device_const_data_ptr());
float*       o = static_cast<float*>(outputs[0].device_mutable_data_ptr());
my_attention_kernel<<<grid, block, smem, cu>>>(q, ..., o);     // your kernel
```

Size the launch from `get_device_properties(this->`[`stream()`](./Module.md#stream)`.`[`device()`](../device-namespace/index.md)`)` (SM count, shared-mem budget); take stream-ordered scratch from `this->`[`stream()`](./Module.md#stream)`.allocate(shape, dtype)`. An exception thrown here does not escape: it surfaces as the operation's error at the caller's synchronization point (a [`ClikaRT::Error`](../Error.md) keeps its [`Status`](../../index.md#Status); any other exception reports [`Status::Internal`](../../index.md#Status)), and the process keeps running. Default: an error.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 459

</div>

### stream() {#stream}

<div class="api-signature">

[`Stream`](../Stream.md) **`stream`**() `const`

</div>

The stream the runtime is currently dispatching this module on; valid ONLY inside [`compute()`](./Module.md#compute) (and anything it calls). It is the queue a hand-written kernel launches on ([`stream()`](./Module.md#stream)`.native_handle()`) and the device the op runs on ([`stream()`](./Module.md#stream)`.`[`device()`](../device-namespace/index.md)). Calling it outside a [`compute()`](./Module.md#compute) invocation raises [`ClikaRT::Error`](../Error.md).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 472

</div>

### dispatch() {#dispatch}

<div class="api-signature">

`std::vector<`[`Tensor`](../Tensor.md)`>` **`dispatch`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`ClikaRT::Span`](../Span.md)`<const` [`Tensor`](../Tensor.md)`>` `inputs`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`Device`](../Device.md) `device` `=` [`Device::cpu`](../Device.md#cpu)`()`<br />
) `const`

</div>

Dispatch THIS module's ([`output_shapes`](./Module.md#output_shapes), [`compute`](./Module.md#compute)) through the runtime: eager runs [`compute`](./Module.md#compute); tracing records the op from [`output_shapes`](./Module.md#output_shapes) alone. [`device`](../device-namespace/index.md) (default CPU) picks where a leaf with no tensor inputs runs.

**Throws**

- `ClikaRT::Error`: when the dispatch is rejected (e.g. [`output_shapes`](./Module.md#output_shapes) reports an error).

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 480

</div>

## Protected static member functions

### initialize\_child() {#initialize_child}

<div class="api-signature">

`static` [`Result`](../Result.md)`<void>` **`initialize_child`**([`Module`](./Module.md)`&` `child`)

</div>

Runs one child's pack hook now, through the entry point that child captured at construction. A parent that consumed some of its children (their weights fused into one leaf it built) packs the leaves it keeps from its own [`initialize_impl`](./Module.md#initialize_impl) override, one call per kept child, and skips the consumed ones; the base walk would reach a consumed child and refuse. Reachable from a derived class only: a load with [`LoadOptions::pack_on_load`](./LoadOptions.md#pack_on_load) and a leaf's first forward remain the public routes to the pack.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 515

</div>

## Protected member functions

### Module() {#Module-4}

<div class="api-signature">

**`Module`**()

</div>

Constructs the module and captures the hook entry points compiled into the translation unit this constructor runs in (the unit that defines the most derived constructor). The runtime reaches every overridable hook ([`output_shapes`](./Module.md#output_shapes), [`compute`](./Module.md#compute), [`to_impl`](./Module.md#to), [`can_cast_to_impl`](./Module.md#can_cast_to_impl), [`initialize_impl`](./Module.md#initialize_impl), [`apply_weight_residency`](./Module.md#apply_weight_residency)) through those entry points, so an exception an override raises is caught by the same C++ runtime that raised it and arrives in the library as a status; no exception unwinds across the library boundary.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 492

</div>

### Module(ModuleHooks) {#Module-5}

<div class="api-signature">

`explicit` **`Module`**(`const` [`ModuleHooks`](./ModuleHooks.md)`&` `hooks`)

</div>

The constructor [`Module()`](./Module.md#Module-4) delegates to, with the hook entry points.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 494

</div>

### initialize\_impl() {#initialize_impl}

<div class="api-signature">

`virtual` [`Result`](../Result.md)`<void>` **`initialize_impl`**()

</div>

The one-time weight pack, the hook [`LoadOptions::pack_on_load`](./LoadOptions.md#pack_on_load) runs from the root and a packing leaf's first forward runs on itself. The base packs nothing of its own and recurses into its children (registration order), so one call on a root packs the whole tree; a leaf with a packable form overrides this with its pack (once, thread-safe, idempotent); a composite that fuses or folds at pack time overrides it, does that work, and calls the base for the children it did not consume. A weight slot still unbound ([`Tensor::is_fake()`](../Tensor.md#is_fake)) is an error here.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 505

</div>

### apply\_weight\_residency() {#apply_weight_residency}

<div class="api-signature">

`virtual` `void` **`apply_weight_residency`**(<br />
&nbsp;&nbsp;&nbsp;&nbsp;[`WeightResidency`](./index.md#WeightResidency) `residency`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::uint64_t&` `stamped`,<br />
&nbsp;&nbsp;&nbsp;&nbsp;`std::uint64_t&` `class_pinned`<br />
)

</div>

The load-scope residency stamp ([`LoadOptions::weight_residency`](./LoadOptions.md#weight_residency) routes here before the checkpoint binds). The base recurses into children in registration order; a module that admits a residency choice overrides this to adopt `residency` (counting itself in `stamped`) or to keep its own posture, class-pinned or tied (counting itself in `class_pinned`), and then calls the base so its own children are still walked. A subclass with no residency of its own needs no override.

<div class="api-declared">

Declared in `ClikaRT/nn/module.h`, line 524

</div>
