metrale_model_layers/layers/ple/
aux_state.rs1use anyhow::Result;
11use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend};
12
13use super::{PleLayer, PleSeqState};
14use crate::layers::ple::ids::ple_ngram_ids;
15
16impl PleLayer {
17 pub fn snapshot_aux(
20 &self,
21 st: &PleSeqState,
22 gpu: &dyn GpuBackend,
23 stream: u64,
24 ) -> Result<Vec<u8>> {
25 let conv_bytes = self.state_len * self.hc_mult * self.hidden * 4;
26 let mut blob = Vec::with_capacity(4 + st.history.len() * 4 + conv_bytes);
27 blob.extend_from_slice(&(st.history.len() as u32).to_le_bytes());
28 for t in &st.history {
29 blob.extend_from_slice(&t.to_le_bytes());
30 }
31 let off = blob.len();
32 blob.resize(off + conv_bytes, 0);
33 gpu.copy_d2h_on_stream(st.conv, &mut blob[off..], stream)?;
34 Ok(blob)
35 }
36
37 pub fn restore_aux(
40 &self,
41 st: &mut PleSeqState,
42 blob: &[u8],
43 gpu: &dyn GpuBackend,
44 stream: u64,
45 ) -> Result<()> {
46 anyhow::ensure!(blob.len() >= 4, "PLE aux blob truncated");
47 let n = u32::from_le_bytes(blob[..4].try_into().unwrap()) as usize;
48 let conv_bytes = self.state_len * self.hc_mult * self.hidden * 4;
49 anyhow::ensure!(
50 blob.len() == 4 + n * 4 + conv_bytes,
51 "PLE aux blob size mismatch"
52 );
53 st.history = blob[4..4 + n * 4]
54 .chunks_exact(4)
55 .map(|c| u32::from_le_bytes(c.try_into().unwrap()))
56 .collect();
57 st.prestaged_va = None;
58 gpu.copy_h2d_async(&blob[4 + n * 4..], st.conv, stream)?;
59 Ok(())
60 }
61}
62
63impl PleLayer {
64 pub(super) fn reset(
67 &self,
68 st: &mut PleSeqState,
69 gpu: &dyn GpuBackend,
70 stream: u64,
71 ) -> Result<()> {
72 st.history = vec![self.dims.eos_token_id; self.dims.context_len()];
73 st.prestaged_va = None;
74 let zeros = vec![0u8; self.state_len * self.hc_mult * self.hidden * 4];
75 gpu.copy_h2d_async(&zeros, st.conv, stream)?;
76 Ok(())
77 }
78
79 pub fn prestage(
86 &self,
87 st: &mut PleSeqState,
88 tokens: &[u32],
89 gpu: &dyn GpuBackend,
90 stream: u64,
91 ) -> Result<()> {
92 if st.history.len() != self.dims.context_len() {
93 self.reset(st, gpu, stream)?;
94 }
95 let mut window = st.history.clone();
96 window.extend_from_slice(tokens);
97 let all = ple_ngram_ids(&self.dims, &window);
98 let rows = &all[all.len() - tokens.len()..];
99 let flat: Vec<u64> = rows.iter().flat_map(|r| r.iter().copied()).collect();
100 let va = self.gather_host(&flat, gpu, stream)?;
101 let keep = self.dims.context_len();
102 st.history = window[window.len() - keep..].to_vec();
103 st.prestaged_va = Some(va);
104 st.last_staged_va = va;
105 Ok(())
106 }
107
108 pub fn release_seq_state(&self, st: &mut PleSeqState, gpu: &dyn GpuBackend) -> Result<()> {
113 if st.conv.is_null() {
114 return Ok(());
115 }
116 let r = gpu.free(st.conv);
117 st.conv = DevicePtr(0);
118 st.history.clear();
119 st.prestaged_va = None;
120 st.last_staged_va = 0;
121 r
122 }
123}