Skip to content

Run a learned MLP policy forward without copying its parameters - #340

Open
Thiago316316 wants to merge 2 commits into
kmolan:mainfrom
Thiago316316:fix/83-mlp-inference-core
Open

Run a learned MLP policy forward without copying its parameters#340
Thiago316316 wants to merge 2 commits into
kmolan:mainfrom
Thiago316316:fix/83-mlp-inference-core

Conversation

@Thiago316316

Copy link
Copy Markdown
Contributor

What & why

A trained policy reaches a robot as one flat block of numbers. Two hidden layers 64 units wide over a 22-component observation come to about 5,900 of them, some 23 KB as f32, against the 64 KB of RAM a small Cortex-M has in total.

Layer holds a MatrixView of its weights and a VectorView of its biases instead, so the coefficients are read where they were stored. forward writes only the activations, OUTPUT of them rather than OUTPUTxINPUT. Activation carries the scalar nonlinearity as an enum rather than a fn pointer, so the choice is inlinable and a layer stays inspectable; it is #[non_exhaustive], leaving room for more.

Widths are const parameters, so chaining a layer that produces three values into one that expects four fails to build rather than at runtime. Nothing allocates and nothing panics, so it runs under no_std.

issue #83

Checklist

  • cargo test + cargo clippy --all-targets clean locally
  • New public APIs have a doc example
  • No unwrap/expect/panic on library paths (typed errors instead)

A trained policy reaches a robot as one flat block of numbers. Two
hidden layers 64 units wide over a 22-component observation come to
about 5,900 of them, some 23 KB as `f32`, against the 64 KB of RAM a
small Cortex-M has in total. Owning those weights would copy the block
onto the stack every control cycle.

`Layer` holds a `MatrixView` of its weights and a `VectorView` of its
biases instead, so the coefficients are read where they were stored.
`forward` writes only the activations, `OUTPUT` of them rather than
`OUTPUT`x`INPUT`. `Activation` carries the scalar nonlinearity as an
enum rather than a `fn` pointer, so the choice is inlinable and a layer
stays inspectable; it is `#[non_exhaustive]`, leaving room for more.

Widths are const parameters, so chaining a layer that produces three
values into one that expects four fails to build rather than at runtime.
Nothing allocates and nothing panics, so it runs under `no_std`.

Inference only. Training belongs on a machine with room for it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Thiago316316
Thiago316316 requested a review from kmolan as a code owner August 28, 2026 15:50
The overview ran three long paragraphs before the example, restating in
prose what the example shows. Cut to what a reader cannot get from the
code: what the layers do, why the parameters are borrowed, and what the
const widths buy.

The links go with it. `cargo doc` denies warnings in CI, and rustdoc
counts a link whose label already names a path in scope as a redundant
explicit target. Both view types are imported here, so the bare labels
resolve to the same pages the spelled-out paths did.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Thiago316316
Thiago316316 force-pushed the fix/83-mlp-inference-core branch from a38ddda to 6a32e97 Compare August 28, 2026 23:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant