1#![allow(unused_imports, dead_code)]
13
14use parking_lot::Mutex;
15use std::collections::HashMap;
16use std::sync::Arc;
17
18use anyhow::{Result, bail};
19use metrale_cache::kv_cache::PagedKvCache;
20use metrale_config::{LayerType, ModelConfig};
21use metrale_gpu_runtime::buffers::BufferArena;
22use metrale_gpu_runtime::gpu::{DevicePtr, GpuBackend, GraphHandle, KernelHandle};
23
24use super::block_mgmt::{
25 apply_evicted_blocks, ensure_blocks_through_decode, ensure_blocks_through_prefill,
26 extract_layer_refs, reuse_prefix_match_disk_ids,
27};
28use super::ssm_pool::SsmStatePool;
29use super::ssm_snapshot::SsmSnapshotPool;
30use super::types::{PinnedMetaStaging, TransformerModel};
31use crate::traits::{ChunkedPrefillPageMetadata, Model, SequenceState};
32use metrale_model_layers::layer::{
33 AttnMetadataDev, ForwardContext, GdnPrefillBuffers, LayerState, SsmLayerState, TransformerLayer,
34};
35use metrale_model_layers::layers::ops;
36use metrale_model_layers::speculative::DraftProposer;
37use metrale_model_layers::weight_map::{DenseWeight, MtpWeights, QuantizedWeight};
38
39mod comm_setup;
40mod kernels;
41mod spec_buffers;
42mod ssm_setup;
43
44pub(crate) use spec_buffers::build_lm_head_nvfp4_t;
45
46use kernels::{AuxKernels, ModelKernels};
47
48impl TransformerModel {
49 pub fn new(
50 config: ModelConfig,
51 embed_tokens: DenseWeight,
52 final_norm: DenseWeight,
53 lm_head_weight: DenseWeight,
54 lm_head_nvfp4: Option<QuantizedWeight>,
55 lm_head_fp8: Option<metrale_model_layers::weight_map::Fp8DenseWeight>,
58 mtp_lm_head_nvfp4: Option<QuantizedWeight>,
63 lm_head_nvfp4_t: Option<(QuantizedWeight, u32)>,
66 layers: Vec<Box<dyn TransformerLayer>>,
67 buffers: BufferArena,
68 kv_cache: PagedKvCache,
69 mtp_weights: Vec<MtpWeights>,
70 gpu: Box<dyn GpuBackend>,
71 max_seq_len: usize,
72 max_batch_size: usize,
73 mtp_quant: metrale_model_layers::layers::MtpQuantization,
74 use_speculative: bool,
75 prefix_cache: Box<dyn metrale_telemetry::prefix_cache::PrefixCache>,
76 mtp_vocab_size: u32,
77 comm: Option<std::sync::Arc<dyn metrale_comm::CommBackend>>,
78 self_speculative: bool,
79 num_drafts: usize,
80 vision_encoder: Option<metrale_model_layers::layers::VisionTower>,
81 ssm_cache_slots: usize,
82 ssm_checkpoint_interval: usize,
83 ) -> Result<Self> {
84 let rms_norm_kernel = if metrale_model_layers::ships_vanilla_norm_weights(&config) {
87 gpu.kernel("rms_norm_vanilla", "rms_norm_vanilla")?
88 } else {
89 gpu.kernel("norm", "rms_norm")?
90 };
91 let ModelKernels {
92 dense_gemv_kernel,
93 dense_gemv_fp32out_kernel,
94 w4a16_gemv_kernel,
95 w4a16_gemv_logits_kernel,
96 w4a16_gemm_t_kernel,
97 w4a16_gemm_t_bf16_kernel,
98 w4a16_gemm_kernel,
99 w4a16_gemv_batch2_kernel,
100 w4a16_batchm,
101 w4a16_gemv_batch16_kernel,
102 dense_gemv_fp8w_kernel,
103 dense_gemv_fp8w_batch2_kernel,
104 dense_gemm_kernel,
105 dense_gemv_batchm_kernel,
106 lm_head_m16_tc_kernel,
107 lm_head_m16_tc_n64_kernel,
108 argmax_kernel,
109 argmax_batch_kernel,
110 argmax_logits_kernel,
111 batched_embed_kernel,
112 fill_slots_kernel,
113 argmax_feed_kernel,
114 feed_resolve_kernel,
115 } = kernels::resolve_model_kernels(&config, gpu.as_ref())?;
116 let profile = config.profile;
117 let profile_first = std::env::var("METRALE_PROFILE_FIRST").is_ok();
118
119 let mut levers = ops::ModelLevers::from_env();
125 levers.max_decode_seqs = (max_batch_size as u32).max(1);
126
127 tracing::info!(
128 "TransformerModel: {} layers, vocab={}, hidden={}{}{}",
129 layers.len(),
130 config.vocab_size,
131 config.hidden_size,
132 if profile { " [PROFILE MODE]" } else { "" },
133 if profile_first {
134 " [PROFILE_FIRST]"
135 } else {
136 ""
137 },
138 );
139
140 let (dflash_kgamma, draft_lm_head_nvfp4, has_mtp, mtp_quant_fwd, num_intermediates) =
141 ssm_setup::size_rollback_pools(
142 &config,
143 mtp_lm_head_nvfp4,
144 lm_head_nvfp4,
145 self_speculative,
146 use_speculative,
147 &mtp_weights,
148 mtp_quant,
149 num_drafts,
150 );
151 let ssm_pool = std::sync::Arc::new(SsmStatePool::new(
152 &config,
153 max_batch_size,
154 has_mtp,
155 num_intermediates,
156 num_drafts,
157 metrale_model_layers::layers::qwen3_ssm::ssm_h_f16_pool_enabled(),
160 metrale_model_layers::ssm_reserve::ssm_rollback_mode(),
163 gpu.as_ref(),
164 )?);
165
166 let (ssm_snapshots, ssm_tier_store) = ssm_setup::build_ssm_snapshots(
167 &config,
168 &ssm_pool,
169 use_speculative,
170 ssm_cache_slots,
171 prefix_cache.as_ref(),
172 max_batch_size,
173 ssm_checkpoint_interval,
174 &kv_cache,
175 gpu.as_ref(),
176 )?;
177
178 let max_blocks_per_seq = (max_seq_len / kv_cache.block_size() + 1) as u32;
181
182 let mut kv_cache = kv_cache;
186 let dummy_kv_block = kv_cache.alloc_block()?;
187 kv_cache.zero_block(dummy_kv_block, gpu.as_ref(), gpu.default_stream())?;
188 gpu.synchronize(gpu.default_stream())?;
189
190 let draft_lm_head_nvfp4_t = if mtp_lm_head_nvfp4.is_none() {
198 lm_head_nvfp4_t
199 } else {
200 None
201 };
202 let proposer: Option<Arc<dyn DraftProposer>> = super::impl_a1_init::build_mtp_proposer(
203 use_speculative,
204 mtp_weights,
205 embed_tokens,
206 final_norm,
207 draft_lm_head_nvfp4,
208 draft_lm_head_nvfp4_t,
209 &config,
210 gpu.as_ref(),
211 mtp_quant,
212 mtp_vocab_size,
213 max_seq_len,
214 kv_cache.num_blocks(),
215 &levers,
216 )?;
217
218 ssm_setup::log_self_speculative(&config, self_speculative);
219
220 let (
221 mtp_hidden_save,
222 verify_hidden_stash,
223 verify_catchup_stash,
224 verify_wy_tables,
225 gdn_woa_na_tab,
226 mtp_catchup_ring,
227 ) = spec_buffers::alloc_verify_buffers(&config, &proposer, &levers, gpu.as_ref())?;
228
229 let (capture_rows, mtp_prefill_hidden) = spec_buffers::alloc_prefill_capture(
230 &config,
231 &proposer,
232 max_seq_len,
233 dflash_kgamma,
234 has_mtp,
235 mtp_quant_fwd,
236 &levers,
237 mtp_quant,
238 gpu.as_ref(),
239 )?;
240
241 let (dflash_capture_layers, dflash_hidden_save_rows, dflash_hidden_save) =
242 spec_buffers::alloc_dflash_capture(
243 &config,
244 dflash_kgamma,
245 max_batch_size,
246 gpu.as_ref(),
247 )?;
248
249 let ep_cmd_buf = gpu.alloc(4)?;
251
252 let moe_row_adapter_buf = gpu.alloc(max_batch_size.max(1) * 4)?;
257
258 let secondary_stream = gpu.create_stream()?;
261 let secondary_event = gpu.create_event()?;
262 let snapshot_event = gpu.create_event()?;
265
266 if let Some(ref comm) = comm {
271 comm_setup::assert_rank_levers_agree(gpu.as_ref(), comm)?;
272 }
273
274 if let Some(ref comm) = comm
280 && comm.world_size() == 2
281 {
282 comm_setup::register_reduce_buffers(comm, &buffers, gpu.as_ref());
283 }
284
285 let (feed_rows, feed_cells, feed_ids, feed_sources, feed_masks) =
289 kernels::alloc_feed_buffers(
290 &buffers,
291 argmax_feed_kernel,
292 feed_resolve_kernel,
293 gpu.as_ref(),
294 )?;
295 let pinned_bytes = buffers.sizes().scratch.max(64 * 1024);
296 let pinned_ptr = gpu.alloc_host_pinned(pinned_bytes)?;
297 tracing::info!("Pinned metadata staging: {} KB", pinned_bytes / 1024);
298 let max_batch_tokens = buffers.max_batch_tokens();
299 let pinned_staging = std::cell::UnsafeCell::new(PinnedMetaStaging {
300 ptr: pinned_ptr,
301 bytes: pinned_bytes,
302 positions: Vec::with_capacity(max_batch_tokens),
303 positions_h: Vec::with_capacity(max_batch_tokens),
304 positions_w: Vec::with_capacity(max_batch_tokens),
305 slots: Vec::with_capacity(max_batch_tokens),
306 });
307
308 let AuxKernels {
309 ssm_norm_k,
310 ssm_norm_f16_k,
311 ssm_h_f32_to_f16_k,
312 ssm_h_f16_to_f32_k,
313 logit_softcap_kernel,
314 logit_softcap_fp32_kernel,
315 use_fp32_logits,
316 logits_fp32_buf,
317 embed_scale_kernel,
318 ssm_norm_ptrs,
319 } = kernels::resolve_aux_kernels(&config, &ssm_pool, gpu.as_ref())?;
320
321 let (gdn_qkv, gdn_gate_beta, gdn_out, gdn_z, gdn_buf_len) =
324 super::impl_a1_init::build_gdn_prefill_buffers(
325 &config,
326 max_batch_tokens,
327 max_seq_len,
328 gpu.as_ref(),
329 )?;
330
331 let has_fp8_calibration = config.fp8_kv_calibration_tokens > 0
335 && kv_cache.dtype() == metrale_cache::kv_cache::KvCacheDtype::Fp8;
336 let overlay_kernels =
339 metrale_model_layers::layers::ops::token_overlay::OverlayKernels::new(gpu.as_ref());
340 Ok(Self {
341 weight_store: None,
344 config,
345 dispatch: metrale_model_layers::layers::ops::GemmDispatch::from_env(),
346 derived: metrale_model_layers::layers::ops::DerivedWeights::new(),
347 levers,
348 stats: ops::ModelStats::new(),
349 #[cfg(feature = "cuda")]
350 innerq: kernels::start_innerq(gpu.as_ref()),
351 embed_tokens,
352 ngram_embed: None,
353 final_norm,
354 lm_head_weight,
355 lm_head_nvfp4,
356 lm_head_nvfp4_t,
357 lm_head_fp8,
358 lm_head_q6k: None,
359 lm_head_rows: super::lm_head_fp8_rows::LmHeadRows::resolve(gpu.as_ref()),
360 decode_graph_veto: layers.iter().any(|l| l.decode_graph_unsupported()),
363 layers,
364 buffers,
365 lora: None,
366 lora_rotatable: false,
367 kv_cache: Mutex::new(kv_cache),
368 gpu,
369 rms_norm_kernel,
370 dense_gemv_kernel,
371 dense_gemv_fp32out_kernel,
372 w4a16_gemv_kernel,
373 w4a16_gemv_logits_kernel,
374 w4a16_gemm_t_kernel,
375 w4a16_gemm_t_bf16_kernel,
376 w4a16_gemm_kernel,
377 w4a16_gemv_batch2_kernel,
378 w4a16_batchm,
379 w4a16_gemv_batch16_kernel,
380 dense_gemv_fp8w_kernel,
381 dense_gemv_fp8w_batch2_kernel,
382 dense_gemm_kernel,
383 dense_gemv_batchm_kernel,
384 lm_head_m16_tc_kernel,
385 lm_head_m16_tc_n64_kernel,
386 argmax_kernel,
387 argmax_batch_kernel,
388 argmax_logits_kernel,
389 batched_embed_kernel,
390 fill_slots_kernel,
391 argmax_feed_kernel,
392 feed_resolve_kernel,
393 feed_cells,
394 feed_ids,
395 feed_sources,
396 feed_masks,
397 feed_rows,
398 inflight_fed_graph_keys: Mutex::new(std::collections::VecDeque::new()),
399 decode_graph: Mutex::new(std::collections::HashMap::new()),
400 batch_decode_graphs: Mutex::new((HashMap::new(), 0)),
401 suppress_graphs: std::sync::atomic::AtomicBool::new(
402 has_fp8_calibration
403 || std::env::var("METRALE_DIAG_GEMMA4").is_ok_and(|v| v == "1" || v == "true")
404 || std::env::var("METRALE_DEBUG_NO_GRAPH").as_deref() == Ok("1"),
408 ),
409 ssm_pool,
410 ssm_snapshots,
411 ssm_tier_store,
412 max_blocks_per_seq,
413 dummy_kv_block,
414 profile,
415 profile_first_pending: std::sync::atomic::AtomicBool::new(profile_first),
416 proposer,
417 mtp_hidden_save,
418 verify_hidden_stash,
419 verify_catchup_stash,
420 mtp_catchup_ring,
421 mtp_catchup_meta: parking_lot::Mutex::new((0, 0)),
422 mtp_prefill_hidden,
423 mtp_prefill_capacity: if mtp_prefill_hidden.is_null() {
426 0
427 } else {
428 capture_rows
429 },
430 mtp_prefill_capture_len: std::sync::atomic::AtomicUsize::new(0),
431 mtp_prefill_capture_gen: std::sync::atomic::AtomicU64::new(0),
432 mtp_store_gen_seq: std::sync::atomic::AtomicU64::new(0),
433 mtp_carry: parking_lot::Mutex::new(None),
434 mtp_store_range: parking_lot::Mutex::new(
435 metrale_model_layers::mtp_carry::StoreRange::EMPTY,
436 ),
437 dflash_hidden_save,
438 verify_ptok_meta: std::sync::OnceLock::new(),
439 dflash_hidden_save_rows,
440 dflash_kgamma,
441 dflash_capture_layers,
442 verify2_graph: Mutex::new(std::collections::HashMap::new()),
443 verify3_graph: Mutex::new(std::collections::HashMap::new()),
444 verify4_graph: Mutex::new(std::collections::HashMap::new()),
445 verify_batched_graphs: Mutex::new((std::collections::HashMap::new(), 0)),
446 verify_wy_tables,
447 gdn_woa_na_tab,
448 gdn_woa_folded_slots: parking_lot::Mutex::new(Vec::new()),
449 gdn_woa_eligible: std::sync::atomic::AtomicBool::new(false),
450 gdn_woa_bound: parking_lot::Mutex::new((DevicePtr::NULL, DevicePtr::NULL, 0)),
451 gdn_carry: Default::default(),
452 verify_wy_cache: Mutex::new(None),
455 verify_kgamma_graph: Mutex::new(std::collections::HashMap::new()),
456 fused_graph: Mutex::new(std::collections::HashMap::new()),
457 prefix_cache,
458 secondary_stream,
459 secondary_event,
460 snapshot_event,
461 comm,
462 ep_cmd_buf,
463 ep_protocol_v2: matches!(std::env::var("METRALE_EP_PROTOCOL").as_deref(), Ok("v2")),
464 self_speculative,
465 last_mtp_hidden_idx: std::sync::atomic::AtomicUsize::new(0),
466 vision_encoder,
467 vision_embed_patches: Mutex::new(0),
468 vision_image_grids: Mutex::new(Vec::new()),
469 vision_row_base: Mutex::new(0),
470 vision_grid_base: Mutex::new(0),
471 vision_owned_images: Mutex::new(0),
472 pinned_staging,
473 ssm_checkpoint_interval,
474 ssm_state_norm_kernel: ssm_norm_k,
475 ssm_state_norm_f16_kernel: ssm_norm_f16_k,
476 ssm_h_f32_to_f16_kernel: ssm_h_f32_to_f16_k,
477 ssm_h_f16_to_f32_kernel: ssm_h_f16_to_f32_k,
478 ssm_h_f16_scratch: std::sync::OnceLock::new(),
479 ssm_norm_ptrs_buf: ssm_norm_ptrs,
480 moe_row_adapter_buf,
481 gdn_buf_qkv: gdn_qkv,
482 gdn_buf_gate_beta: gdn_gate_beta,
483 gdn_buf_out: gdn_out,
484 gdn_buf_z: gdn_z,
485 gdn_buf_max_len: gdn_buf_len,
486 logit_softcap_kernel,
487 logit_softcap_fp32_kernel,
488 use_fp32_logits,
489 logits_fp32_buf,
490 embed_scale_kernel,
491 overlays: None,
492 overlay_kernels,
493 overlay_route_slot: std::sync::atomic::AtomicI32::new(-1),
494 decode_moe_route: std::sync::atomic::AtomicI32::new(1), circuit: parking_lot::RwLock::new(None),
496 })
497 }
498}