Skip to main content

vyre_libs/nn/linear/inner/linear_4bit/
mod.rs

1//! Fused `linear_4bit` constructor  -  unpack-on-demand 4-bit quantized linear.
2//!
3//! Instead of materializing an unpacked f32 weight buffer, this kernel loads
4//! the packed u32 weight, extracts the correct nibble inside the inner `k`
5//! loop, and accumulates directly. This eliminates the 8× memory expansion
6//! of a separate unpack dispatch.
7//!
8//! [`unpack_on_demand`] owns the plain INT4 dot product. The grouped affine
9//! path splits across [`affine_grouped`] and its weight-tile strategy in
10//! [`affine_grouped_weight_reuse`], over the geometry in [`grouped_layout`].
11//! [`quantized_spec`] validates first-class quantized metadata and
12//! [`planner_evidence`] reports the cost of the fused path.
13
14mod affine_grouped;
15mod affine_grouped_weight_reuse;
16mod grouped_layout;
17mod op_registration;
18mod planner_evidence;
19mod quantized_spec;
20mod unpack_on_demand;
21
22pub use affine_grouped::{linear_4bit_affine_grouped, linear_4bit_affine_grouped_batched};
23pub use planner_evidence::linear_4bit_affine_grouped_planner_evidence;
24pub use quantized_spec::{
25    linear_4bit_affine_grouped_batched_typed, linear_4bit_affine_grouped_typed,
26};
27pub use unpack_on_demand::linear_4bit;
28
29use vyre_foundation::ir::DataType;
30
31/// Maximum absolute output drift allowed for grouped INT4 planner evidence tests.
32pub const LINEAR_4BIT_AFFINE_GROUPED_OUTPUT_DRIFT_ABS_TOLERANCE: f32 = 1.0e-4;
33
34/// Planner evidence for fused grouped INT4 linear versus dequantized matmul.
35#[derive(Debug, Clone, PartialEq)]
36pub struct QuantizedLinear4BitPlannerEvidence {
37    /// Input feature dimension.
38    pub in_dim: u32,
39    /// Output feature dimension.
40    pub out_dim: u32,
41    /// Quantization group size.
42    pub group_size: u32,
43    /// Number of quantization groups.
44    pub group_count: u32,
45    /// Packed INT4 weight bytes.
46    pub packed_weight_bytes: u64,
47    /// Bytes that a materialized f32 dequantized weight matrix would require.
48    pub dequantized_weight_bytes: u64,
49    /// Scale plus zero-point sidecar bytes.
50    pub sidecar_bytes: u64,
51    /// Bias bytes.
52    pub bias_bytes: u64,
53    /// Output bytes.
54    pub output_bytes: u64,
55    /// Dequantized weight bytes avoided by the fused path.
56    pub dequant_bytes_elided: u64,
57    /// Equivalent matmul planner M dimension.
58    pub matmul_m: u32,
59    /// Equivalent matmul planner K dimension.
60    pub matmul_k: u32,
61    /// Equivalent matmul planner N dimension.
62    pub matmul_n: u32,
63    /// Equivalent matmul planner K tile.
64    pub matmul_tile: u32,
65    /// Selected shared matmul planner path.
66    pub matmul_selected_path: &'static str,
67    /// Candidate tensor-core path from the shared matmul planner, when any.
68    pub matmul_candidate_path: Option<&'static str>,
69    /// Shared matmul planner fallback reason, when the selected path is cooperative.
70    pub matmul_fallback_reason: Option<&'static str>,
71    /// Whether the shared matmul planner selected a tensor-core path.
72    pub tensor_core_eligible: bool,
73    /// Maximum absolute output drift accepted by evidence tests.
74    pub output_drift_abs_tolerance: f32,
75}
76
77/// Typed metadata for fused grouped INT4 linear.
78///
79/// The actual packed weight buffer is still addressed as `u32` words because
80/// the kernel extracts eight nibbles per word. This spec binds that physical
81/// layout to the first-class `DataType::Quantized` contract so call sites do
82/// not pass an untyped integer buffer and lose the scale/zero-point semantics.
83#[derive(Debug, Clone, PartialEq, Eq)]
84pub struct QuantizedLinear4BitSpec {
85    /// Input feature dimension.
86    pub in_dim: u32,
87    /// Output feature dimension.
88    pub out_dim: u32,
89    /// First-class quantized weight metadata.
90    pub weight_type: DataType,
91}