use half::f16;
use model_io::ResidentIndex;
use crate::real_forward_types::RealForwardError;
pub(crate) fn le_bytes_to_u16(bytes: &[u8]) -> Vec<u16> {
bytes
.chunks_exact(2)
.map(|c| u16::from_le_bytes([c[0], c[1]]))
.collect()
}
pub(crate) fn f32_to_f16(v: &[f32]) -> Vec<f16> {
v.iter().map(|&x| f16::from_f32(x)).collect()
}
pub(crate) fn f16_to_f32(v: &[f16]) -> Vec<f32> {
v.iter().map(|x| x.to_f32()).collect()
}
pub(crate) fn f16_slice_to_le_bytes(v: &[f16]) -> Vec<u8> {
let mut out = Vec::with_capacity(v.len() * 2);
for x in v {
out.extend_from_slice(&x.to_bits().to_le_bytes());
}
out
}
pub(crate) fn tensor_bytes<'a>(
index: &'a ResidentIndex,
data: &'a [u8],
name: &str,
) -> Result<&'a [u8], RealForwardError> {
let entry = index
.entries
.get(name)
.ok_or_else(|| RealForwardError::MissingTensor(name.to_string()))?;
let local = (entry.file_offset - index.header.index_size) as usize;
Ok(&data[local..local + entry.size_bytes as usize])
}
pub(crate) fn affine_group_size(
e: &model_io::ResidentIndexEntry,
name: &str,
rows: usize,
cols: usize,
bits: usize,
) -> Result<usize, RealForwardError> {
let bad = |detail: String| Err(RealForwardError::Unsupported(detail));
if rows == 0 || cols == 0 {
return bad(format!(
"tensor {name}: {bits}-bit shape {rows}x{cols} has a zero dimension"
));
}
if e.shape.0 as usize != rows || e.shape.1 as usize != cols {
return bad(format!(
"tensor {name}: declared shape {}x{} does not match {rows}x{cols}",
e.shape.0, e.shape.1
));
}
if e.scale_offset % 2 != 0 || e.bias_offset % 2 != 0 {
return bad(format!(
"tensor {name}: affine companion offsets must be aligned to 2 bytes"
));
}
let elements_per_byte = 8 / bits;
let elements = rows.checked_mul(cols).ok_or_else(|| {
RealForwardError::Unsupported(format!("tensor {name}: shape {rows}x{cols} overflows"))
})?;
if elements % elements_per_byte != 0 || e.size_bytes as usize != elements / elements_per_byte {
return bad(format!(
"tensor {name}: {bits}-bit packed size {} does not match {rows}x{cols} ({} bytes)",
e.size_bytes,
rows * cols / elements_per_byte
));
}
if e.scale_size != e.bias_size {
return bad(format!(
"tensor {name}: {bits}-bit scale plane is {} bytes against {} bias bytes; the two \
carry one FP16 value per group each",
e.scale_size, e.bias_size
));
}
let plane = e.scale_size as usize;
if plane == 0 || plane % (2 * rows) != 0 {
return bad(format!(
"tensor {name}: {plane} companion bytes is not a whole number of FP16 values across \
{rows} rows"
));
}
let groups = plane / (2 * rows);
if cols % groups != 0 {
return bad(format!(
"tensor {name}: {groups} groups per row does not divide {cols} columns"
));
}
let group_size = cols / groups;
if group_size % elements_per_byte != 0 {
return bad(format!(
"tensor {name}: derived group size {group_size} is not a whole number of bytes"
));
}
Ok(group_size)
}
pub(crate) fn resident_matrix<'a>(
weights: &'a gpu::ResidentGpuWeights,
index: &ResidentIndex,
name: &str,
rows: usize,
cols: usize,
) -> Result<gpu::Int4ResidentMatrix<'a>, RealForwardError> {
let entry = index
.entries
.get(name)
.ok_or_else(|| RealForwardError::MissingTensor(name.to_string()))?;
if entry.dtype != 4 {
return Err(RealForwardError::Unsupported(format!(
"tensor {name}: dtype {} is not INT4-affine",
entry.dtype
)));
}
let group_size = affine_group_size(entry, name, rows, cols, 4)?;
if group_size != 64 {
return Err(RealForwardError::Unsupported(format!(
"tensor {name}: INT4 group size {group_size} does not match kernel group size 64"
)));
}
let base = index.header.index_size;
Ok(gpu::Int4ResidentMatrix {
buffer: weights.buffer(),
weights_offset: weights.gpu_offset(entry.file_offset - base),
scales_offset: weights.gpu_offset(entry.scale_offset - base),
biases_offset: weights.gpu_offset(entry.bias_offset - base),
rows,
cols,
})
}
pub(crate) fn owned_rows(
index: &ResidentIndex,
data: &[u8],
name: &str,
rows: usize,
cols: usize,
) -> Result<Vec<compute::quant::Int4AffineRow>, RealForwardError> {
let packed_all = tensor_bytes(index, data, name)?;
let entry = index
.entries
.get(name)
.ok_or_else(|| RealForwardError::MissingTensor(name.to_string()))?;
let base = index.header.index_size;
let scale_local = (entry.scale_offset - base) as usize;
let bias_local = (entry.bias_offset - base) as usize;
let scales = le_bytes_to_u16(&data[scale_local..scale_local + entry.scale_size as usize]);
let biases = le_bytes_to_u16(&data[bias_local..bias_local + entry.bias_size as usize]);
let row_bytes = cols / 2;
let group_size = affine_group_size(entry, name, rows, cols, 4)?;
let groups = cols / group_size;
Ok((0..rows)
.map(|r| compute::quant::Int4AffineRow {
packed: packed_all[r * row_bytes..(r + 1) * row_bytes].to_vec(),
scales: scales[r * groups..(r + 1) * groups].to_vec(),
biases: biases[r * groups..(r + 1) * groups].to_vec(),
})
.collect())
}
pub(crate) fn layer_name(prefix: &str, layer: usize) -> String {
format!("layer{layer}.{prefix}")
}
pub(crate) fn layer_tensor(layer: usize, suffix: &str) -> String {
format!("language_model.model.layers.{layer}.{suffix}")
}
pub(crate) fn entry<'a>(
index: &'a ResidentIndex,
name: &str,
) -> Result<&'a model_io::ResidentIndexEntry, RealForwardError> {
index
.entries
.get(name)
.ok_or_else(|| RealForwardError::MissingTensor(name.to_string()))
}
pub(crate) fn read_bf16_host(
weights: &gpu::ResidentGpuWeights,
index: &ResidentIndex,
name: &str,
) -> Result<Vec<f32>, RealForwardError> {
let e = entry(index, name)?;
let base = index.header.index_size;
let local = (e.file_offset - base) as usize;
let bytes = &weights.data()[local..local + e.size_bytes as usize];
Ok(bytes
.chunks_exact(2)
.map(|c| compute::bf16_to_f32(u16::from_le_bytes([c[0], c[1]])))
.collect())
}
pub(crate) fn norm_view<'a>(
weights: &'a gpu::ResidentGpuWeights,
index: &ResidentIndex,
name: &str,
expect_elems: usize,
) -> Result<(&'a gpu::MetalBuffer, u64), RealForwardError> {
let e = entry(index, name)?;
if e.size_bytes as usize != expect_elems * 2 {
return Err(RealForwardError::Unsupported(format!(
"tensor {name}: {} bytes does not match expected BF16 [{expect_elems}]",
e.size_bytes
)));
}
let base = index.header.index_size;
Ok((weights.buffer(), weights.gpu_offset(e.file_offset - base)))
}
pub(crate) fn topk_softmax(logits: &[f32], k: usize) -> (Vec<usize>, Vec<f32>) {
let max = logits.iter().copied().fold(f32::NEG_INFINITY, f32::max);
let exps: Vec<f32> = logits.iter().map(|&x| (x - max).exp()).collect();
let sum: f32 = exps.iter().sum();
let probs: Vec<f32> = exps.iter().map(|&e| e / sum).collect();
let mut order: Vec<usize> = (0..probs.len()).collect();
order.sort_by(|&a, &b| probs[b].total_cmp(&probs[a]));
let selected: Vec<usize> = order.into_iter().take(k).collect();
let selected_sum: f32 = selected.iter().map(|&i| probs[i]).sum();
let weights: Vec<f32> = selected
.iter()
.map(|&i| {
if selected_sum > 0.0 {
probs[i] / selected_sum
} else {
0.0
}
})
.collect();
(selected, weights)
}
pub(crate) fn ring_spans(capacity: usize, base: usize, rows: usize) -> [(usize, usize); 2] {
assert!(
capacity > 0 && rows <= capacity,
"capacity must be positive and rows <= capacity: rows={rows}, capacity={capacity}"
);
let first = rows.min(capacity - base % capacity);
[(0, first), (first, rows - first)]
}
#[cfg(test)]
#[path = "real_forward_utils_tests.rs"]
mod tests;