use half::f16;
use crate::families::deepseek2::RealDeepseek2State;
use crate::moe_prefill_pipeline::RoutedSlot;
use crate::real_forward_dispatch::{encode_moe_phase1_any, encode_moe_phase2_any};
use crate::real_forward_init::MappedResidency;
use crate::real_forward_layout::RoutedLayerLayout;
use crate::real_forward_types::{DecodeScratch, PhaseCounters, RealForwardError};
use crate::real_forward_utils::f16_slice_to_le_bytes;
pub(crate) fn softmax_topk_no_renorm(logits: &[f32], k: usize) -> (Vec<usize>, Vec<f32>) {
let max = logits.iter().cloned().fold(f32::NEG_INFINITY, f32::max);
let mut probs: Vec<(usize, f32)> = logits
.iter()
.enumerate()
.map(|(i, &l)| (i, (l - max).exp()))
.collect();
let denom: f32 = probs.iter().map(|(_, p)| p).sum();
for (_, p) in probs.iter_mut() {
*p /= denom;
}
probs.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap_or(std::cmp::Ordering::Equal));
probs.truncate(k);
probs.into_iter().unzip()
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_shared_expert(
context: &mut gpu::MetalContext,
pass: &gpu::PassEncoder,
weights: &gpu::ResidentGpuWeights,
index: &model_io::ResidentIndex,
state: &RealDeepseek2State,
layer: usize,
token: usize,
hidden: usize,
inter: usize,
) -> Result<(), RealForwardError> {
let x_off = (token * hidden * 2) as u64;
let name = |suffix: &str| {
crate::families::deepseek2::layer_tensor(layer, &format!("mlp.shared_expert.{suffix}"))
};
encode_gemv_rows(
context,
pass,
weights,
index,
&name("gate_proj.weight"),
inter,
hidden,
(&state.moe_x, x_off),
(&state.ffn_a, 0),
)?;
encode_gemv_rows(
context,
pass,
weights,
index,
&name("up_proj.weight"),
inter,
hidden,
(&state.moe_x, x_off),
(&state.ffn_b, 0),
)?;
gpu::encode_silu_mul(
context,
pass,
(&state.ffn_a, 0),
(&state.ffn_b, 0),
(&state.ffn_a, 0),
inter as u32,
)
.map_err(RealForwardError::Gpu)?;
encode_gemv_rows(
context,
pass,
weights,
index,
&name("down_proj.weight"),
hidden,
inter,
(&state.ffn_a, 0),
(&state.shared_out, 0),
)
}
#[allow(clippy::too_many_arguments)]
fn encode_gemv_rows(
context: &mut gpu::MetalContext,
pass: &gpu::PassEncoder,
weights: &gpu::ResidentGpuWeights,
index: &model_io::ResidentIndex,
name: &str,
rows: usize,
cols: usize,
x: (&gpu::MetalBuffer, u64),
y: (&gpu::MetalBuffer, u64),
) -> Result<(), RealForwardError> {
crate::real_forward_dispatch::encode_gemv_any(
context, pass, weights, index, name, rows, cols, x, y,
)
}
#[allow(clippy::too_many_arguments)]
pub(crate) fn encode_deepseek2_layer_moe(
context: &mut gpu::MetalContext,
pass: &gpu::PassEncoder,
weights: &gpu::ResidentGpuWeights,
index: &model_io::ResidentIndex,
scratch: &DecodeScratch,
state: &RealDeepseek2State,
streamers: &mut [Option<streaming::PreadExpertStreamer>],
slot_buffers: &[Vec<gpu::MetalBuffer>],
mapped: &MappedResidency,
routed_blobs: Option<&gpu::RoutedBlobsBuffer>,
routed_blobs_banks: &[gpu::RoutedBlobsBuffer],
moe_offsets: &[gpu::MoeExpertOffsets],
routed_layouts: &[RoutedLayerLayout],
router_hist: &mut Option<crate::router_hist::RouterHistogram>,
phases: &mut PhaseCounters,
layer: usize,
hidden: usize,
moe_inter: u32,
num_experts: usize,
top_k: usize,
slot: &RoutedSlot,
) -> Result<Vec<usize>, RealForwardError> {
let x_off = (slot.token * hidden * 2) as u64;
let rw_off = slot.bank * gpu::MAX_STREAMED_EXPERTS * 2;
let blob_layer = layer - state.lead;
encode_shared_expert(
context,
pass,
weights,
index,
state,
layer,
slot.token,
hidden,
state.shared_inter,
)?;
let router_logits = gpu::read_f32_buffer_at(
&state.router_logits_f32,
slot.token * num_experts,
num_experts,
);
let (selected, route_weights) = softmax_topk_no_renorm(&router_logits, top_k);
if let Some(hist) = router_hist.as_mut() {
hist.record(blob_layer, &selected);
}
let mapped_active = mapped.buffers.get(layer).is_some_and(Option::is_some);
let slots: Vec<usize> = if mapped_active {
phases.expert_requests += selected.len() as u64;
phases.expert_hits += selected.len() as u64;
selected.clone()
} else {
let streamer = streamers[layer].as_mut().ok_or_else(|| {
RealForwardError::Unsupported(format!(
"deepseek2 layer {layer} has no packed-expert streamer"
))
})?;
let plan = streamer.plan_experts_cached(&selected, &slot.protect);
phases.expert_requests += plan.experts.len() as u64;
phases.expert_hits += plan.hits as u64;
let t_io = std::time::Instant::now();
let slots = streamer
.execute_expert_cache_plan(&plan)
.map_err(|e| RealForwardError::Unsupported(format!("expert stream: {e}")))?;
phases.expert_io_nanos += t_io.elapsed().as_nanos() as u64;
slots
};
let ordered: Vec<(usize, f32)> = (0..selected.len())
.map(|i| (slots[i], route_weights[i]))
.collect();
let mut routing16 = vec![f16::from_f32(0.0); gpu::MAX_STREAMED_EXPERTS];
for (dispatch_slot, &(_, weight)) in ordered.iter().enumerate() {
routing16[dispatch_slot] = f16::from_f32(weight);
}
gpu::write_buffer_bytes(
&scratch.routing_w,
rw_off,
&f16_slice_to_le_bytes(&routing16),
);
let blob_refs: Vec<(&gpu::MetalBuffer, u64)> = if mapped_active {
let buffer = mapped.buffers[layer]
.as_ref()
.expect("mapped residency checked above");
let mapping = mapped.layers[layer]
.as_ref()
.expect("mapped residency checked above");
ordered
.iter()
.map(|&(expert, _)| {
mapping
.expert_offset(expert)
.map(|offset| (buffer, offset))
.map_err(|e| {
RealForwardError::Unsupported(format!(
"mapped expert layer {layer}, expert {expert}: {e}"
))
})
})
.collect::<Result<Vec<_>, _>>()?
} else {
let layer_slots = &slot_buffers[layer];
ordered
.iter()
.map(|&(cache_slot, _)| (&layer_slots[cache_slot], 0u64))
.collect()
};
let routed = match slot.bank {
0 => routed_blobs,
n => routed_blobs_banks.get(n - 1),
}
.ok_or_else(|| {
RealForwardError::Unsupported("install has no routed-blob buffer".to_string())
})?;
let offsets = &moe_offsets[blob_layer];
let (blob_source, blob_function) = routed_layouts[blob_layer].phase1.source_function();
let use_silu = true;
routed
.bind_for(context, blob_source, blob_function, use_silu, &blob_refs)
.map_err(RealForwardError::Gpu)?;
for &(buffer, _) in &blob_refs {
pass.use_read_buffer(buffer);
}
encode_moe_phase1_any(
routed_layouts[blob_layer].phase1,
context,
pass,
routed,
offsets,
(&state.moe_x, x_off),
(&scratch.moe_acts, 0),
hidden as u32,
moe_inter,
ordered.len() as u32,
use_silu,
)
.map_err(RealForwardError::Gpu)?;
encode_moe_phase2_any(
routed_layouts[blob_layer].phase2,
context,
pass,
routed,
offsets,
(&scratch.moe_acts, 0),
(&scratch.routing_w, rw_off as u64),
(&state.shared_out, 0),
(&state.h2, 0),
hidden as u32,
moe_inter,
top_k as u32,
use_silu,
)
.map_err(RealForwardError::Gpu)?;
gpu::encode_residual_add(
context,
pass,
(&scratch.x, x_off),
(&state.h2, 0),
hidden as u32,
)
.map_err(RealForwardError::Gpu)?;
Ok(ordered.iter().map(|&(cache_slot, _)| cache_slot).collect())
}