[Edge][CPU] KV-cached code predictor, int8-dynamic CPU fast path, model-side CPU sampler
Measured on a Xeon 8480C (12+4 threads, 0.6B): the 15 residual-codebook sub-steps re-ran the 5-layer predictor over the whole prefix each time (97 ms per frame of the 134 ms talker step) and vLLM's stock sampler spent 9 ms per step in its torch.compile'd random-sample kernel on CPU. - code predictor: forward_cached (KV cache per layer, 2-token prefill then one token per sub-step) and a shape-static forward_static_step (tensor position + boolean mask) that torch.compile handles as one graph; incremental decoding is the default on CPU (VLLM_OMNI_PREDICTOR_INCREMENTAL), optional compile (VLLM_OMNI_PREDICTOR_COMPILE=step), optional thread cap. - CPU fast path: dynamic int8 Linear layers (fp32 activations) for the predictor and its lm heads (VLLM_OMNI_PREDICTOR_INT8, default on; micro-benchmark 70 -> 36 ms per frame for the 15 sub-steps); VLLM_OMNI_PREDICTOR_PARITY_CHECK=1 records top-1 agreement / max logit diff against the bf16 model in situ. - Qwen3-TTS talker: prefer_model_sampler on CPU with a sample() that mirrors vLLM's Sampler (logits processors + penalties, temperature, top-k/top-p, exponential-noise sampling with per-request generators) without the compiled kernel (VLLM_OMNI_CPU_FAST_SAMPLER, default on). - step_stats: sampler phase timers and sample-metadata timers. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
936c10be4b
commit
6ce8de1b28
6 files changed
+604
-8
No files matched your search
@@ -15,6 +15,7 @@ Shared by Qwen3-Omni and Qwen3-TTS talker models.
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses
|
||||
import os
|
||||
import time
|
||||
from collections.abc import Iterable, Sequence
|
||||
|
||||
@@ -270,11 +271,58 @@ class CodePredictorAttention(nn.Module):
|
||||
sync=True,
|
||||
)[0]
|
||||
|
||||
def forward_static_step(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
||||
kv_cache: tuple[torch.Tensor, torch.Tensor],
|
||||
cache_pos: torch.Tensor,
|
||||
attn_mask: torch.Tensor,
|
||||
) -> torch.Tensor:
|
||||
"""One new token against a fixed-size cache (shape-static, ``torch.compile``-friendly).
|
||||
|
||||
``cache_pos`` is a 1-element int64 tensor (the slot to write), ``attn_mask`` a bool
|
||||
``[B, 1, 1, max_seq]`` mask that is True for the valid slots ``<= cache_pos``.
|
||||
"""
|
||||
bsz, seq_len, _ = hidden_states.shape
|
||||
qkv = self.qkv_proj(hidden_states)
|
||||
q_raw, k_raw, v_raw = self._split_qkv(qkv)
|
||||
q = self.q_norm(q_raw.view(bsz, seq_len, self.num_heads, self.head_dim)).transpose(1, 2)
|
||||
k = self.k_norm(k_raw.view(bsz, seq_len, self.num_kv_heads, self.head_dim)).transpose(1, 2)
|
||||
v = v_raw.view(bsz, seq_len, self.num_kv_heads, self.head_dim).transpose(1, 2)
|
||||
cos, sin = position_embeddings
|
||||
cos = cos.unsqueeze(1)
|
||||
sin = sin.unsqueeze(1)
|
||||
q = (q * cos) + (_rotate_half(q) * sin)
|
||||
k = (k * cos) + (_rotate_half(k) * sin)
|
||||
k_cache, v_cache = kv_cache
|
||||
k_cache.index_copy_(2, cache_pos, k.to(k_cache.dtype))
|
||||
v_cache.index_copy_(2, cache_pos, v.to(v_cache.dtype))
|
||||
attn_out = F.scaled_dot_product_attention(
|
||||
q,
|
||||
k_cache[:bsz],
|
||||
v_cache[:bsz],
|
||||
attn_mask=attn_mask,
|
||||
scale=self.scaling,
|
||||
enable_gqa=self.is_gqa,
|
||||
)
|
||||
attn_out = attn_out.transpose(1, 2).reshape(bsz, seq_len, -1)
|
||||
return self.o_proj(attn_out)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
||||
kv_cache: tuple[torch.Tensor, torch.Tensor] | None = None,
|
||||
cache_pos: int = 0,
|
||||
) -> torch.Tensor:
|
||||
"""Causal self-attention.
|
||||
|
||||
With ``kv_cache=(k_cache, v_cache)`` of shape ``[B, kv_heads, max_seq, head_dim]`` the
|
||||
new positions ``cache_pos .. cache_pos+seq_len`` are written into the cache and attended
|
||||
together with the cached prefix (incremental decoding of the residual codebooks); a
|
||||
multi-token call is only allowed from an empty cache (``cache_pos == 0``).
|
||||
"""
|
||||
bsz, seq_len, _ = hidden_states.shape
|
||||
hidden_shape_q = (bsz, seq_len, self.num_heads, self.head_dim)
|
||||
hidden_shape_kv = (bsz, seq_len, self.num_kv_heads, self.head_dim)
|
||||
@@ -299,12 +347,21 @@ class CodePredictorAttention(nn.Module):
|
||||
else:
|
||||
q = (q * cos) + (_rotate_half(q) * sin)
|
||||
k = (k * cos) + (_rotate_half(k) * sin)
|
||||
if kv_cache is not None:
|
||||
if seq_len > 1 and cache_pos != 0:
|
||||
raise ValueError("incremental code-predictor attention: multi-token append needs an empty cache")
|
||||
k_cache, v_cache = kv_cache
|
||||
end = cache_pos + seq_len
|
||||
k_cache[:bsz, :, cache_pos:end] = k
|
||||
v_cache[:bsz, :, cache_pos:end] = v
|
||||
k = k_cache[:bsz, :, :end]
|
||||
v = v_cache[:bsz, :, :end]
|
||||
attn_out = F.scaled_dot_product_attention(
|
||||
q,
|
||||
k,
|
||||
v,
|
||||
scale=self.scaling,
|
||||
is_causal=True,
|
||||
is_causal=seq_len > 1,
|
||||
enable_gqa=self.is_gqa,
|
||||
)
|
||||
|
||||
@@ -355,14 +412,35 @@ class CodePredictorDecoderLayer(nn.Module):
|
||||
self.input_layernorm = _RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
||||
self.post_attention_layernorm = _RMSNorm(config.hidden_size, eps=config.rms_norm_eps)
|
||||
|
||||
def forward_static_step(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
||||
kv_cache: tuple[torch.Tensor, torch.Tensor],
|
||||
cache_pos: torch.Tensor,
|
||||
attn_mask: torch.Tensor,
|
||||
) -> torch.Tensor:
|
||||
residual = hidden_states
|
||||
hidden_states = self.input_layernorm(hidden_states)
|
||||
hidden_states = self.self_attn.forward_static_step(
|
||||
hidden_states, position_embeddings, kv_cache, cache_pos, attn_mask
|
||||
)
|
||||
hidden_states = residual + hidden_states
|
||||
residual = hidden_states
|
||||
hidden_states = self.post_attention_layernorm(hidden_states)
|
||||
hidden_states = self.mlp(hidden_states)
|
||||
return residual + hidden_states
|
||||
|
||||
def forward(
|
||||
self,
|
||||
hidden_states: torch.Tensor,
|
||||
position_embeddings: tuple[torch.Tensor, torch.Tensor],
|
||||
kv_cache: tuple[torch.Tensor, torch.Tensor] | None = None,
|
||||
cache_pos: int = 0,
|
||||
) -> torch.Tensor:
|
||||
residual = hidden_states
|
||||
hidden_states = self.input_layernorm(hidden_states)
|
||||
hidden_states = self.self_attn(hidden_states, position_embeddings)
|
||||
hidden_states = self.self_attn(hidden_states, position_embeddings, kv_cache=kv_cache, cache_pos=cache_pos)
|
||||
if current_omni_platform.is_npu():
|
||||
hidden_states, _, residual = torch_npu.npu_add_rms_norm(
|
||||
hidden_states,
|
||||
@@ -448,6 +526,55 @@ class CodePredictorBaseModel(nn.Module):
|
||||
hidden_states = self.norm(hidden_states)
|
||||
return hidden_states.to(input_dtype)
|
||||
|
||||
def new_kv_caches(self, bsz: int, max_seq: int, device: torch.device, dtype: torch.dtype) -> list:
|
||||
"""Per-layer ``(k_cache, v_cache)`` buffers for :meth:`forward_cached`."""
|
||||
attn0 = self.layers[0].self_attn
|
||||
shape = (bsz, attn0.num_kv_heads, max_seq, attn0.head_dim)
|
||||
return [
|
||||
(torch.zeros(shape, device=device, dtype=dtype), torch.zeros(shape, device=device, dtype=dtype))
|
||||
for _ in self.layers
|
||||
]
|
||||
|
||||
def forward_static_step(
|
||||
self,
|
||||
inputs_embeds: torch.Tensor,
|
||||
position_ids: torch.Tensor,
|
||||
kv_caches: list,
|
||||
cache_pos: torch.Tensor,
|
||||
attn_mask: torch.Tensor,
|
||||
) -> torch.Tensor:
|
||||
"""One-token step with tensor-valued position and mask (no Python ints -> one compiled graph)."""
|
||||
hidden_states = inputs_embeds
|
||||
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
||||
for layer, cache in zip(self.layers, kv_caches, strict=True):
|
||||
hidden_states = layer.forward_static_step(hidden_states, position_embeddings, cache, cache_pos, attn_mask)
|
||||
return self.norm(hidden_states)
|
||||
|
||||
def forward_cached(
|
||||
self,
|
||||
inputs_embeds: torch.Tensor,
|
||||
position_ids: torch.Tensor,
|
||||
kv_caches: list,
|
||||
cache_pos: int,
|
||||
) -> torch.Tensor:
|
||||
"""Incremental forward: process only ``inputs_embeds`` (positions ``cache_pos..``) against the caches.
|
||||
|
||||
Same math as :meth:`forward` over the full prefix, without re-running the
|
||||
cached positions; used for the residual-codebook loop on CPU where each
|
||||
of the 15 sub-steps would otherwise recompute up to 17 positions.
|
||||
"""
|
||||
input_dtype = inputs_embeds.dtype
|
||||
use_fp32 = input_dtype == torch.float16 and inputs_embeds.device.type != "cpu"
|
||||
if use_fp32:
|
||||
inputs_embeds = inputs_embeds.float()
|
||||
hidden_states = inputs_embeds
|
||||
with torch.amp.autocast(inputs_embeds.device.type, enabled=use_fp32, dtype=torch.float32):
|
||||
position_embeddings = self.rotary_emb(hidden_states, position_ids)
|
||||
for layer, cache in zip(self.layers, kv_caches, strict=True):
|
||||
hidden_states = layer(hidden_states, position_embeddings, kv_cache=cache, cache_pos=cache_pos)
|
||||
hidden_states = self.norm(hidden_states)
|
||||
return hidden_states.to(input_dtype)
|
||||
|
||||
# Mapping from HF checkpoint shard name to the (fused parameter,
|
||||
# slice index) pair used to assemble the fused tensor. See
|
||||
# ``load_weights`` below.
|
||||
@@ -998,6 +1125,149 @@ class CodePredictorWrapper(nn.Module):
|
||||
]
|
||||
)
|
||||
|
||||
# ------------------------------------------------------------------
|
||||
# Incremental (KV-cached) residual decoding
|
||||
# ------------------------------------------------------------------
|
||||
_INCREMENTAL_ENV = "VLLM_OMNI_PREDICTOR_INCREMENTAL"
|
||||
_INT8_ENV = "VLLM_OMNI_PREDICTOR_INT8" # CPU: dynamic int8 Linear layers (default on; "0" disables)
|
||||
_PARITY_ENV = "VLLM_OMNI_PREDICTOR_PARITY_CHECK" # "1": compare int8 logits with the bf16 model per sub-step
|
||||
|
||||
def _parity_check(self, step: int, proj_row: torch.Tensor, logits_int8: torch.Tensor, ref_caches: list) -> None:
|
||||
"""Record top-1 agreement and max |logit diff| between the int8 and the reference predictor."""
|
||||
from vllm_omni.edge.step_stats import StepStats
|
||||
|
||||
ref_model, ref_heads = self._parity_ref
|
||||
rdtype = next(ref_model.parameters()).dtype
|
||||
bsz = proj_row.shape[0]
|
||||
if step == 1:
|
||||
x = proj_row.to(rdtype) # [B, 2, H] prefill rows
|
||||
h = ref_model.forward_cached(x, self._incremental_pos_ids(bsz, 0, 2, proj_row.device), ref_caches, 0)[:, 1]
|
||||
else:
|
||||
x = proj_row.to(rdtype) # [B, 1, H]
|
||||
h = ref_model.forward_cached(x, self._incremental_pos_ids(bsz, step, 1, proj_row.device), ref_caches, step)[
|
||||
:, 0
|
||||
]
|
||||
ref_logits = ref_heads[step - 1](h).float()
|
||||
stats = StepStats.get()
|
||||
agree = (ref_logits.argmax(-1) == logits_int8.float().argmax(-1)).float().mean().item()
|
||||
stats.add("predictor.parity_top1_agree", agree)
|
||||
stats.add("predictor.parity_logit_maxdiff", (ref_logits - logits_int8.float()).abs().max().item())
|
||||
|
||||
def _setup_cpu_fast_path(self, device: torch.device) -> None:
|
||||
"""CPU: dynamic int8 quantization of every Linear (weights int8 per-channel, activations per call).
|
||||
|
||||
Measured on a Xeon 8480C (12 threads): bf16 M=1 GEMVs carry ~30 us of fixed
|
||||
kernel overhead each and the 15 residual sub-steps cost 70 ms per frame; with
|
||||
int8-dynamic Linear layers (fp32 activations) the same loop costs 36 ms.
|
||||
"""
|
||||
if getattr(self, "_cpu_fast_path_done", False):
|
||||
return
|
||||
self._cpu_fast_path_done = True
|
||||
if device.type != "cpu" or current_omni_platform.is_npu():
|
||||
return
|
||||
if os.environ.get(self._INT8_ENV, "1").strip().lower() in ("0", "false", "off", "no"):
|
||||
return
|
||||
from torch.ao.quantization import quantize_dynamic
|
||||
|
||||
self._parity_ref = None
|
||||
if os.environ.get(self._PARITY_ENV, "0").strip().lower() in ("1", "true", "on", "yes"):
|
||||
# keep an unquantized copy to measure int8 fidelity in situ (see _parity_check)
|
||||
import copy as _copy
|
||||
|
||||
self._parity_ref = (_copy.deepcopy(self.model), _copy.deepcopy(self.lm_head))
|
||||
self.model = quantize_dynamic(self.model.float(), {nn.Linear}, dtype=torch.qint8)
|
||||
self.lm_head = quantize_dynamic(self.lm_head.float(), {nn.Linear}, dtype=torch.qint8)
|
||||
self.small_to_mtp_projection = self.small_to_mtp_projection.float()
|
||||
self._model_dtype = torch.float32
|
||||
self._lm_heads_list = list(self.lm_head)
|
||||
self._codec_embeds_list = list(self.model.codec_embedding)
|
||||
self._compiled_model_fwd = self.model.forward
|
||||
self._proj_buf = None # re-allocated in fp32 by _ensure_buffers
|
||||
logger.info("code_predictor: CPU fast path (KV-cached sub-steps, dynamic int8 Linear, fp32 activations)")
|
||||
|
||||
_THREADS_ENV = "VLLM_OMNI_PREDICTOR_THREADS" # CPU: OpenMP threads for the residual loop (0 = unchanged)
|
||||
_COMPILE_ENV = (
|
||||
"VLLM_OMNI_PREDICTOR_COMPILE" # "1": torch.compile the per-layer MLP/norm blocks (CPU, static shapes)
|
||||
)
|
||||
|
||||
def _incremental_threads(self) -> int:
|
||||
try:
|
||||
return max(0, int(os.environ.get(self._THREADS_ENV, "0")))
|
||||
except ValueError:
|
||||
return 0
|
||||
|
||||
def _setup_incremental_compile(self) -> None:
|
||||
"""Compile the whole shape-static one-token step (``forward_static_step``) for the incremental path.
|
||||
|
||||
The step takes the fixed-size caches, a tensor position and a boolean mask, so a
|
||||
single ``torch.compile`` graph serves all 14 residual sub-steps without
|
||||
recompilation; the 2-token prefill of the first sub-step stays eager.
|
||||
"""
|
||||
if getattr(self, "_incremental_compiled", False):
|
||||
return
|
||||
self._incremental_compiled = True
|
||||
self._static_step_fn = None
|
||||
if os.environ.get(self._COMPILE_ENV, "0").strip().lower() not in ("1", "true", "on", "yes", "step"):
|
||||
return
|
||||
self._static_step_fn = torch.compile(self.model.forward_static_step, dynamic=False)
|
||||
logger.info("code_predictor: incremental path with a compiled static one-token step")
|
||||
|
||||
def _use_incremental(self, device: torch.device) -> bool:
|
||||
"""KV-cached sub-steps: default on CPU (no device graphs there), ``=1`` forces, ``=0`` disables."""
|
||||
mode = os.environ.get(self._INCREMENTAL_ENV, "auto").strip().lower()
|
||||
if mode in ("0", "false", "off", "no"):
|
||||
return False
|
||||
if mode in ("1", "true", "on", "yes"):
|
||||
return not current_omni_platform.is_npu()
|
||||
return device.type == "cpu" and not self._device_graphs
|
||||
|
||||
def _incremental_caches(self, bsz: int, max_seq: int, device: torch.device, dtype: torch.dtype) -> list:
|
||||
key = (bsz, max_seq, str(device), dtype)
|
||||
buffers = getattr(self, "_kv_cache_buffers", None)
|
||||
if buffers is None:
|
||||
buffers = self._kv_cache_buffers = {}
|
||||
caches = buffers.get(key)
|
||||
if caches is None:
|
||||
caches = buffers[key] = self.model.new_kv_caches(bsz, max_seq, device, dtype)
|
||||
return caches
|
||||
|
||||
@staticmethod
|
||||
def _incremental_pos_ids(bsz: int, start: int, n: int, device: torch.device) -> torch.Tensor:
|
||||
return torch.arange(start, start + n, device=device, dtype=torch.long).unsqueeze(0).expand(bsz, -1)
|
||||
|
||||
def _sample_step_code(
|
||||
self,
|
||||
logits: torch.Tensor,
|
||||
sample_generator: _GeneratorLike,
|
||||
*,
|
||||
stored_mode: bool,
|
||||
s_top_k: int,
|
||||
s_top_p: float,
|
||||
use_sampling: bool,
|
||||
inv_temperature: float,
|
||||
top_k: int,
|
||||
) -> torch.Tensor:
|
||||
"""Same sampling as the re-prefill loop body (kept identical so codes match)."""
|
||||
if stored_mode:
|
||||
if s_top_k > 0:
|
||||
topk_vals, _ = logits.topk(s_top_k, dim=-1)
|
||||
logits = logits.masked_fill(logits < topk_vals[:, -1:], float("-inf"))
|
||||
if s_top_p < 1.0:
|
||||
sorted_logits, sorted_idx = logits.sort(dim=-1, descending=True)
|
||||
sorted_probs = F.softmax(sorted_logits, dim=-1, dtype=torch.float32)
|
||||
cumulative_probs = sorted_probs.cumsum(dim=-1)
|
||||
remove_mask = (cumulative_probs - sorted_probs) >= s_top_p
|
||||
sorted_logits[remove_mask] = float("-inf")
|
||||
logits = sorted_logits.scatter(1, sorted_idx, sorted_logits)
|
||||
return self._sample_codes_gumbel(logits, generator=sample_generator)
|
||||
if use_sampling:
|
||||
scaled = logits * inv_temperature
|
||||
if top_k > 0:
|
||||
topk_vals, _ = scaled.topk(top_k, dim=-1)
|
||||
scaled = scaled.masked_fill(scaled < topk_vals[:, -1:], float("-inf"))
|
||||
return self._sample_codes_gumbel(scaled, generator=sample_generator)
|
||||
return logits.argmax(dim=-1, keepdim=True)
|
||||
|
||||
@torch.inference_mode()
|
||||
def forward(
|
||||
self,
|
||||
@@ -1022,6 +1292,7 @@ class CodePredictorWrapper(nn.Module):
|
||||
# _setup_compile caches _model_dtype on first call; use it for buffers
|
||||
# so they always match model weight precision (#2385).
|
||||
self._setup_compile()
|
||||
self._setup_cpu_fast_path(device)
|
||||
dtype = self._model_dtype
|
||||
|
||||
padded_bsz = self._padded_bsz(bsz)
|
||||
@@ -1067,8 +1338,80 @@ class CodePredictorWrapper(nn.Module):
|
||||
|
||||
_stats = StepStats.get()
|
||||
_t_loop = time.perf_counter() if _stats.enabled else 0.0
|
||||
incremental = self._use_incremental(device)
|
||||
kv_caches = self._incremental_caches(bsz, max_seq, device, dtype) if incremental else None
|
||||
prev_threads = None
|
||||
if incremental:
|
||||
self._setup_incremental_compile()
|
||||
n_threads = self._incremental_threads()
|
||||
if n_threads > 0 and device.type == "cpu" and n_threads != torch.get_num_threads():
|
||||
prev_threads = torch.get_num_threads()
|
||||
torch.set_num_threads(n_threads)
|
||||
sample_kwargs = (
|
||||
dict(
|
||||
stored_mode=True, s_top_k=s_top_k, s_top_p=s_top_p, use_sampling=False, inv_temperature=0.0, top_k=top_k
|
||||
)
|
||||
if stored_mode
|
||||
else dict(
|
||||
stored_mode=False,
|
||||
s_top_k=0,
|
||||
s_top_p=1.0,
|
||||
use_sampling=use_sampling,
|
||||
inv_temperature=inv_temperature,
|
||||
top_k=top_k,
|
||||
)
|
||||
)
|
||||
for step in range(1, num_groups):
|
||||
_t_sub = time.perf_counter() if _stats.enabled else 0.0
|
||||
if incremental:
|
||||
# KV-cached: prefill positions 0..1 at the first sub-step, then one new position per sub-step.
|
||||
if step == 1:
|
||||
hidden_new = self.model.forward_cached(
|
||||
proj_buf[:bsz, :2, :], self._incremental_pos_ids(bsz, 0, 2, device), kv_caches, 0
|
||||
)
|
||||
hidden_step = hidden_new[:, 1, :]
|
||||
elif self._static_step_fn is not None:
|
||||
pos_t = torch.tensor([step], device=device, dtype=torch.long)
|
||||
attn_mask = (
|
||||
(torch.arange(max_seq, device=device) <= step).view(1, 1, 1, max_seq).expand(bsz, 1, 1, max_seq)
|
||||
)
|
||||
hidden_new = self._static_step_fn(
|
||||
proj_buf[:bsz, step : step + 1, :],
|
||||
self._incremental_pos_ids(bsz, step, 1, device),
|
||||
kv_caches,
|
||||
pos_t,
|
||||
attn_mask,
|
||||
)
|
||||
hidden_step = hidden_new[:, 0, :]
|
||||
else:
|
||||
hidden_new = self.model.forward_cached(
|
||||
proj_buf[:bsz, step : step + 1, :],
|
||||
self._incremental_pos_ids(bsz, step, 1, device),
|
||||
kv_caches,
|
||||
step,
|
||||
)
|
||||
hidden_step = hidden_new[:, 0, :]
|
||||
logits = lm_heads[step - 1](hidden_step)
|
||||
if getattr(self, "_parity_ref", None) is not None:
|
||||
if step == 1:
|
||||
ref_model = self._parity_ref[0]
|
||||
self._parity_caches = ref_model.new_kv_caches(
|
||||
bsz, max_seq, device, next(ref_model.parameters()).dtype
|
||||
)
|
||||
self._parity_check(step, proj_buf[:bsz, :2, :], logits, self._parity_caches)
|
||||
else:
|
||||
self._parity_check(step, proj_buf[:bsz, step : step + 1, :], logits, self._parity_caches)
|
||||
code = self._sample_step_code(logits, sample_generator, **sample_kwargs)
|
||||
if self._wrapper_config.return_proj_buf:
|
||||
all_codes[:, step] = code
|
||||
else:
|
||||
all_codes[:, step] = code.reshape(bsz)
|
||||
if step < num_groups - 1 or self._wrapper_config.return_proj_buf:
|
||||
new_embed = codec_embeds[step - 1](code)
|
||||
proj_buf[:bsz, step + 1, :] = projection(new_embed.reshape(bsz, 1, -1)).reshape(bsz, -1)
|
||||
if _stats.enabled:
|
||||
_stats.add("predictor.substep_ms", (time.perf_counter() - _t_sub) * 1000.0)
|
||||
continue
|
||||
graph_key: int | tuple[int, int] = padded_bsz
|
||||
seq_len = max_seq
|
||||
if self._prefix_graphs_enabled:
|
||||
@@ -1144,6 +1487,8 @@ class CodePredictorWrapper(nn.Module):
|
||||
proj_buf[:bsz, step + 1, :] = projection(new_embed.reshape(bsz, 1, -1)).reshape(bsz, -1)
|
||||
if _stats.enabled:
|
||||
_stats.add("predictor.substep_ms", (time.perf_counter() - _t_sub) * 1000.0)
|
||||
if prev_threads is not None:
|
||||
torch.set_num_threads(prev_threads)
|
||||
if _stats.enabled:
|
||||
_stats.add("predictor.loop_ms", (time.perf_counter() - _t_loop) * 1000.0)
|
||||
|
||||
|
||||
Reference in new issue
Block a user