vllm-pack
vllm/vllm/v1/worker/gpu_model_runner.py · ef9339e · L1923–2064 · 固定 commit 上游
这是固定版本源码的只读摘录;可在线阅读,也可通过上游链接查看原文件。
1923 def _prepare_inputs(
1924 self,
1925 scheduler_output: "SchedulerOutput",
1926 num_scheduled_tokens: np.ndarray,
1927 ) -> tuple[
1928 torch.Tensor,
1929 SpecDecodeMetadata | None,
1930 int,
1931 ]:
1932 """Returns:
1933 tuple[logits_indices, spec_decode_metadata, max_num_sampled_tokens]
1934
1935 """
1936 total_num_scheduled_tokens = scheduler_output.total_num_scheduled_tokens
1937 assert total_num_scheduled_tokens > 0
1938 num_reqs = self.input_batch.num_reqs
1939 assert num_reqs > 0
1940
1941 # OPTIMIZATION: Start copying the block table first.
1942 # This way, we can overlap the copy with the following CPU operations.
1943 self.input_batch.block_table.commit_block_table(num_reqs)
1944
1945 # Get request indices.
1946 # E.g., [2, 5, 3] -> [0, 0, 1, 1, 1, 1, 1, 2, 2, 2]
1947 req_indices = np.repeat(self.arange_np[:num_reqs], num_scheduled_tokens)
1948
1949 # cu_num_tokens: [2, 5, 3] -> [2, 7, 10]
1950 # self.query_pos.np[:10]: [0, 1, 0, 1, 2, 3, 4, 0, 1, 2]
1951 cu_num_tokens = self._get_cumsum_and_arange(
1952 num_scheduled_tokens, self.query_pos.np
1953 )
1954
1955 # Get positions.
1956 positions_np = (
1957 self.input_batch.num_computed_tokens_cpu[req_indices]
1958 + self.query_pos.np[: cu_num_tokens[-1]]
1959 )
1960
1961 # Calculate M-RoPE positions.
1962 # Only relevant for models using M-RoPE (e.g, Qwen2-VL)
1963 if self.uses_mrope:
1964 self._calc_mrope_positions(scheduler_output)
1965
1966 # Get token indices.
1967 # E.g., [0, 1, 0, 1, 2, 3, 4, 0, 1, 2]
1968 # -> [0, 1, M, M + 1, M + 2, M + 3, M + 4, 2 * M, 2 * M + 1, 2 * M + 2]
1969 # where M is the max_model_len.
1970 token_indices = (
1971 positions_np + req_indices * self.input_batch.token_ids_cpu.shape[1]
1972 )
1973 token_indices_tensor = torch.from_numpy(token_indices)
1974
1975 # NOTE(woosuk): We use torch.index_select instead of np.take here
1976 # because torch.index_select is much faster than np.take for large
1977 # tensors.
1978 torch.index_select(
1979 self.input_batch.token_ids_cpu_tensor.flatten(),
1980 0,
1981 token_indices_tensor,
1982 out=self.input_ids.cpu[:total_num_scheduled_tokens],
1983 )
1984 if self.enable_prompt_embeds:
1985 is_token_ids = self.input_batch.is_token_ids_tensor.flatten()
1986 torch.index_select(
1987 is_token_ids,
1988 0,
1989 token_indices_tensor,
1990 out=self.is_token_ids.cpu[:total_num_scheduled_tokens],
1991 )
1992
1993 # Because we did not pre-allocate a massive prompt_embeds CPU tensor on
1994 # the InputBatch, we need to fill in the prompt embeds into the expected
1995 # spots in the GpuModelRunner's pre-allocated prompt_embeds tensor.
1996 if self.input_batch.req_prompt_embeds:
1997 output_idx = 0
1998 for req_idx in range(num_reqs):
1999 num_sched = num_scheduled_tokens[req_idx]
2000
2001 # Skip if this request doesn't have embeddings
2002 if req_idx not in self.input_batch.req_prompt_embeds:
2003 output_idx += num_sched
2004 continue
2005
2006 # Skip if no tokens scheduled
2007 if num_sched <= 0:
2008 output_idx += num_sched
2009 continue
2010
2011 req_embeds = self.input_batch.req_prompt_embeds[req_idx]
2012 start_pos = self.input_batch.num_computed_tokens_cpu[req_idx]
2013
2014 # Skip if trying to read beyond available embeddings
2015 if start_pos >= req_embeds.shape[0]:
2016 output_idx += num_sched
2017 continue
2018
2019 # Copy available embeddings
2020 end_pos = start_pos + num_sched
2021 actual_end = min(end_pos, req_embeds.shape[0])
2022 actual_num_sched = actual_end - start_pos
2023
2024 if actual_num_sched > 0:
2025 self.inputs_embeds.cpu[
2026 output_idx : output_idx + actual_num_sched
2027 ].copy_(req_embeds[start_pos:actual_end])
2028
2029 output_idx += num_sched
2030
2031 # Prepare the attention metadata.
2032 self.query_start_loc.np[0] = 0
2033 self.query_start_loc.np[1 : num_reqs + 1] = cu_num_tokens
2034 # Note: pad query_start_loc to be non-decreasing, as kernels
2035 # like FlashAttention requires that
2036 self.query_start_loc.np[num_reqs + 1 :].fill(cu_num_tokens[-1])
2037 self.query_start_loc.copy_to_gpu()
2038 query_start_loc = self.query_start_loc.gpu[: num_reqs + 1]
2039
2040 # Compute optimistic seq_lens (assumes all draft tokens from previous
2041 # iteration accepted). Store in optimistic_seq_lens_cpu for use by
2042 # _build_attention_metadata (max_seq_len) and discard_request_mask.
2043 # seq_lens (GPU) will be computed later using the same optimistic values.
2044 torch.add(
2045 self.input_batch.num_computed_tokens_cpu_tensor[:num_reqs],
2046 torch.from_numpy(num_scheduled_tokens),
2047 out=self.optimistic_seq_lens_cpu[:num_reqs],
2048 )
2049 self.optimistic_seq_lens_cpu[num_reqs:].fill_(0)
2050
2051 # Build prev_positions mapping: current pos -> prev pos (-1 if new).
2052 # Used for gathering from previous iteration's GPU tensors.
2053 prev_req_id_to_index = self.input_batch.prev_req_id_to_index
2054 self._compute_prev_positions(num_reqs)
2055
2056 num_tokens = [self.requests[r].num_tokens for r in self.input_batch.req_ids]
2057 num_tokens_np = np.array(num_tokens, dtype=np.int32)
2058
2059 # Record which requests should not be sampled,
2060 # so that we could clear the sampled tokens before returning
2061 self.discard_request_mask.np[:num_reqs] = (
2062 self.optimistic_seq_lens_cpu[:num_reqs].numpy() < num_tokens_np
2063 )
2064 self.discard_request_mask.copy_to_gpu(num_reqs)