Skip to content

feat(sparse-inference): TernarySparseFfn -- dual sparsity via ternary weights#605

Open
simeon-kepp wants to merge 7 commits into
ruvnet:mainfrom
simeon-kepp:feat/sparse-inference-ternary-ffn
Open

feat(sparse-inference): TernarySparseFfn -- dual sparsity via ternary weights#605
simeon-kepp wants to merge 7 commits into
ruvnet:mainfrom
simeon-kepp:feat/sparse-inference-ternary-ffn

Conversation

@simeon-kepp

Copy link
Copy Markdown
Contributor

Summary

Builds on the LinearBitNet layer merged in #477 to integrate ternary weight quantization directly into the sparse FFN pipeline.

TernarySparseFfn is a drop-in alternative to SparseFfn that stores W1 and W2 as i8 ternary weights {-1, 0, +1} instead of f32. This adds a second, independent axis of sparsity:

Axis Mechanism Typical savings
Activation sparsity (existing) LowRankPredictor skips inactive neurons 70 % of neurons not visited
Weight sparsity (new) Zero weights inside each active neuron's dot product are skipped 50–60 % of MACs within active neurons

Combined at BitNet b1.58 realistic numbers: ~15 % of dense f32 multiply-accumulate operations remain.

What changed

  • crates/ruvector-sparse-inference/src/sparse/ternary_ffn.rs — new TernarySparseFfn struct implementing the FeedForward trait, with from_f32() constructor, forward_sparse(), forward_dense(), and w1_sparsity()/w2_sparsity() accessors. 9 unit tests including a sparse-vs-dense agreement check.
  • src/sparse/mod.rsmod ternary_ffn; pub use ternary_ffn::TernarySparseFfn;
  • src/lib.rsTernarySparseFfn added to the crate-level re-export

Additive only

Usage

use ruvector_sparse_inference::TernarySparseFfn;
use ruvector_sparse_inference::config::ActivationType;

// BitNet b1.58 recipe: threshold = mean(|W|)
let threshold = w1.iter().map(|w| w.abs()).sum::<f32>() / w1.len() as f32;

let ffn = TernarySparseFfn::from_f32(
    512, 2048, 512,
    &w1, &w2,
    threshold,
    None, None,
    ActivationType::Silu,
)?;

// active_neurons from your LowRankPredictor as usual
let output = ffn.forward_sparse(&input, &active_neurons)?;
println!("W1 sparsity: {:.1}%", ffn.w1_sparsity() * 100.0);

github-actions Bot and others added 7 commits May 20, 2026 12:01
Built from commit dd5e145

Platforms updated:
- linux-x64-gnu
- linux-x64-musl
- linux-arm64-gnu
- linux-arm64-musl
- darwin-x64
- darwin-arm64
- win32-x64-msvc

Generated by GitHub Actions
Built from commit dd5e145

Platforms updated:
- linux-x64-gnu
- linux-x64-musl
- linux-arm64-gnu
- linux-arm64-musl
- darwin-x64
- darwin-arm64
- win32-x64-msvc
- wasm

Generated by GitHub Actions
Built from commit dd5e145

Platforms: linux-x64-gnu, linux-arm64-gnu, darwin-x64, darwin-arm64, win32-x64-msvc

Co-Authored-By: claude-flow <ruv@ruv.net>
  Built from commit dd5e145

  Platforms updated:
  - linux-x64-gnu
  - linux-arm64-gnu
  - darwin-x64
  - darwin-arm64
  - win32-x64-msvc

  🤖 Generated by GitHub Actions
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