model_state.py 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. # SPDX-License-Identifier: Apache-2.0
  2. # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
  3. from typing import Any
  4. import torch
  5. import torch.nn as nn
  6. from vllm.config import VllmConfig
  7. from vllm.triton_utils import tl, triton
  8. from vllm.v1.worker.gpu.input_batch import InputBatch
  9. from vllm.v1.worker.gpu.mm.encoder_cache import EncoderCache
  10. from vllm.v1.worker.gpu.model_states.default import DefaultModelState
  11. from vllm.v1.worker.gpu.states import RequestState
  12. @triton.jit
  13. def _gather_lookback_kernel(
  14. lookback_ptr,
  15. idx_mapping_ptr,
  16. num_computed_tokens_ptr,
  17. all_token_ids_ptr,
  18. all_token_ids_stride,
  19. num_reqs,
  20. DEPTH: tl.constexpr,
  21. BLOCK_DEPTH: tl.constexpr,
  22. ):
  23. # One program per lookback row; rows past the batch are filled with -1.
  24. batch_idx = tl.program_id(0)
  25. in_batch = batch_idx < num_reqs
  26. req_state_idx = tl.load(idx_mapping_ptr + batch_idx, mask=in_batch, other=0)
  27. num_computed = tl.load(num_computed_tokens_ptr + req_state_idx)
  28. offs = tl.arange(0, BLOCK_DEPTH)
  29. pos = num_computed - 1 - offs
  30. valid = in_batch & (offs < DEPTH) & (pos >= 0)
  31. ids = tl.load(
  32. all_token_ids_ptr + req_state_idx * all_token_ids_stride + pos,
  33. mask=valid,
  34. other=-1,
  35. )
  36. tl.store(lookback_ptr + batch_idx * DEPTH + offs, ids, mask=offs < DEPTH)
  37. class DeepseekV41ModelState(DefaultModelState):
  38. """DefaultModelState plus the engram lookback window.
  39. The engram n-gram hash needs the ids of the ``depth`` tokens preceding
  40. each request's chunk start (see ``common/engram.py``). The runner keeps
  41. the full token history on device, so the window is gathered there every
  42. step: exact for prompt and generated tokens alike, whatever instance
  43. produced their KV.
  44. """
  45. def __init__(
  46. self,
  47. vllm_config: VllmConfig,
  48. model: nn.Module,
  49. encoder_cache: EncoderCache | None,
  50. device: torch.device,
  51. ):
  52. super().__init__(vllm_config, model, encoder_cache, device)
  53. depth = model.token_lookback_depth
  54. self.lookback_token_ids: torch.Tensor | None = None
  55. if depth > 0:
  56. # Persistent so a captured graph can read it on replay.
  57. self.lookback_token_ids = torch.full(
  58. (self.max_num_reqs, depth), -1, dtype=torch.int32, device=device
  59. )
  60. def prepare_inputs(
  61. self, input_batch: InputBatch, req_states: RequestState
  62. ) -> dict[str, torch.Tensor | None]:
  63. model_inputs = super().prepare_inputs(input_batch, req_states)
  64. window = self.lookback_token_ids
  65. if window is None:
  66. return model_inputs
  67. all_token_ids = req_states.all_token_ids.gpu
  68. depth = window.shape[1]
  69. _gather_lookback_kernel[(window.shape[0],)](
  70. window,
  71. input_batch.idx_mapping,
  72. req_states.num_computed_tokens.gpu,
  73. all_token_ids,
  74. all_token_ids.stride(0),
  75. input_batch.idx_mapping.shape[0],
  76. DEPTH=depth,
  77. BLOCK_DEPTH=triton.next_power_of_2(depth),
  78. )
  79. model_inputs["lookback_token_ids"] = window
  80. return model_inputs
  81. def prepare_dummy_inputs(self, num_reqs: int, num_tokens: int) -> dict[str, Any]:
  82. model_inputs = super().prepare_dummy_inputs(num_reqs, num_tokens)
  83. if self.lookback_token_ids is not None:
  84. # The captured graph reads this buffer; replays refill it in place.
  85. self.lookback_token_ids.fill_(-1)
  86. model_inputs["lookback_token_ids"] = self.lookback_token_ids
  87. return model_inputs