A high-throughput and memory-efficient inference and serving engine for LLMs
Mirrored from https://github.com/tduncan-lum/Nvidia-Optimization-Stack---VLLM.git
Synced Nov 15, 22:15 UTC
[Hardware][Gaudi][Feature] Support Contiguous Cache Fetch (#12139)
Signed-off-by: yuzhou <yuzhou@habana.ai> Signed-off-by: zhouyu5 <yu.zhou@intel.com> Co-authored-by: Cody Yu <hao.yu.cody@gmail.com>
Yu-Zhou committed
Feb 19, 2025 at 11:40 UTC
d0a7a2769d92619afdcdc3b91c78098eaa9e38c0
4 files changed
+81
-48
vllm/attention/backends/hpu_attn.py
+1
-5
@@ -118,12 +118,8 @@ class HPUAttentionImpl(AttentionImpl, torch.nn.Module):
118
self.matmul_av = Matmul()
119
self.batch2block_matmul = Matmul()
120
self.block2batch_matmul = Matmul()
121
- # NOTE(kzawora): Contiguous PA is off until model runner supports it
121
self.k_cache = VLLMKVCache()
123
- self.k_cache.use_contiguous_pa = False
122
self.v_cache = VLLMKVCache()
125
- self.v_cache.use_contiguous_pa = False
126
- # NOTE(kzawora): Pipelined PA is off until model runner supports it
123
ops.pa_impl = ops.pa
124
125
self.num_kv_heads = num_heads if num_kv_heads is None else num_kv_heads
@@ -249,7 +245,7 @@ class HPUAttentionImpl(AttentionImpl, torch.nn.Module):
245
block_mapping=attn_metadata.block_mapping,
246
block_bias=attn_metadata.attn_bias,
247
block_scales=attn_metadata.block_scales,
252
- block_groups=None,
248
+ block_groups=attn_metadata.block_groups,
249
scale=self.scale,
250
matmul_qk_op=self.matmul_qk,
251
matmul_av_op=self.matmul_av,
vllm/attention/ops/hpu_paged_attn.py
+1
@@ -23,6 +23,7 @@ class HPUPagedAttentionMetadata:
23
block_indices: Optional[torch.Tensor]
24
block_offsets: Optional[torch.Tensor]
25
block_scales: Optional[torch.Tensor]
26
+ block_groups: Optional[torch.Tensor]
27
28
29
class HPUPagedAttention:
vllm/envs.py
+8
@@ -89,6 +89,7 @@ if TYPE_CHECKING:
89
VLLM_RAY_PER_WORKER_GPUS: float = 1.0
90
VLLM_RAY_BUNDLE_INDICES: str = ""
91
VLLM_CUDART_SO_PATH: Optional[str] = None
92
+ VLLM_USE_HPU_CONTIGUOUS_CACHE_FETCH: bool = True
93
94
95
def get_default_cache_root():
@@ -585,6 +586,13 @@ environment_variables: Dict[str, Callable[[], Any]] = {
586
# specify the path through environment variable VLLM_CUDART_SO_PATH.
587
"VLLM_CUDART_SO_PATH":
588
lambda: os.getenv("VLLM_CUDART_SO_PATH", None),
589
+
590
+ # Contiguous cache fetching to avoid using costly gather operation on
591
+ # Gaudi3. This is only applicable to HPU contiguous cache. If set to true,
592
+ # contiguous cache fetch will be used.
593
+ "VLLM_USE_HPU_CONTIGUOUS_CACHE_FETCH":
594
+ lambda: os.environ.get("VLLM_CONTIGUOUS_PA", "true").lower() in
595
+ ("1", "true"),
596
}
597
598
# end-env-vars-definition
vllm/worker/hpu_model_runner.py
+71
-43
@@ -25,9 +25,11 @@ import habana_frameworks.torch.internal.bridge_config as bc
25
import torch
26
import torch.nn as nn
27
from vllm_hpu_extension.ops import LoraMask as LoraMask
28
+from vllm_hpu_extension.ops import batch2block, block2batch
29
from vllm_hpu_extension.profiler import (HabanaHighLevelProfiler,
30
HabanaMemoryProfiler, format_bytes)
31
32
+import vllm.envs as envs
33
from vllm.attention import AttentionMetadata, get_attn_backend
34
from vllm.config import DeviceConfig, VllmConfig
35
from vllm.distributed.parallel_state import get_world_group
@@ -260,10 +262,19 @@ def setup_profiler():
262
return profiler
263
264
263
-def pad_list(list, k, v):
264
- target_len = round_up(len(list), k)
265
- padding = target_len - len(list)
266
- return list + [v] * padding
265
+def pad_list(input, k, v):
266
+ input_len = len(input)
267
+ target_len = round_up(input_len, k)
268
+ padding = target_len - input_len
269
+ return input + [v] * padding
270
+
271
+
272
+def gather_list(input, indices, v):
273
+ return [input[i] if i is not None else v for i in indices]
274
+
275
+
276
+def flatten(in_list):
277
+ return list(itertools.chain(*in_list))
278
279
280
def precompute_indices_and_offsets(block_size, slot_mapping, is_prompt):
@@ -334,13 +345,23 @@ class HpuModelAdapter:
345
mask = mask >= metadata.block_usage.unsqueeze(-1)
346
attn_bias = (torch.zeros_like(mask, dtype=dtype).masked_fill_(
347
mask, -math.inf))
337
- block_mapping = torch.nn.functional.one_hot(metadata.block_mapping,
348
+ block_mapping = torch.nn.functional.one_hot(metadata.block_groups,
349
num_classes=batch_size)
350
block_mapping = block_mapping.to(dtype)
351
metadata = metadata._replace(block_mapping=block_mapping,
352
attn_bias=attn_bias)
353
return metadata
354
355
+ def _set_block_scales(self, metadata, device):
356
+ block_mapping = metadata.block_mapping
357
+ ones = torch.ones((block_mapping.size(0), ),
358
+ device=device,
359
+ dtype=block_mapping.dtype)
360
+ sums = batch2block(block2batch(ones, block_mapping), block_mapping)
361
+ block_scales = torch.reciprocal(torch.maximum(ones, sums))
362
+ metadata = metadata._replace(block_scales=block_scales)
363
+ return metadata
364
+
365
def _update_metadata(self, attn_metadata, batch_size, seq_len, device,
366
dtype):
367
if attn_metadata.is_prompt:
@@ -351,6 +372,7 @@ class HpuModelAdapter:
372
meta = attn_metadata
373
attn_metadata = self._set_block_mapping(meta, batch_size, device,
374
dtype)
375
+ attn_metadata = self._set_block_scales(attn_metadata, device)
376
return attn_metadata
377
378
def forward(self, *args, **kwargs):
@@ -586,6 +608,7 @@ class HPUModelRunnerBase(ModelRunnerBase[TModelInputForHPU]):
608
self.bucketing_global_state = HPUBucketingGlobalState()
609
self._setup_buckets()
610
self._set_gc_threshold()
611
+ self.use_contiguous_pa = envs.VLLM_USE_HPU_CONTIGUOUS_CACHE_FETCH
612
613
def _set_gc_threshold(self) -> None:
614
# Read https://docs.python.org/3/library/gc.html#gc.set_threshold
@@ -911,6 +934,7 @@ class HPUModelRunnerBase(ModelRunnerBase[TModelInputForHPU]):
934
block_indices=block_indices,
935
block_offsets=block_offsets,
936
block_scales=None,
937
+ block_groups=None,
938
attn_bias=None,
939
seq_lens_tensor=seq_lens_tensor,
940
num_prefills=real_num_seqs,
@@ -1008,65 +1032,69 @@ class HPUModelRunnerBase(ModelRunnerBase[TModelInputForHPU]):
1032
1033
num_decode_tokens = sum(seq_lens)
1034
1011
- blocks_used = [len(bt) for bt in block_tables if bt]
1012
- block_list = []
1013
- block_scales = []
1014
- for i, bt in enumerate(block_tables):
1015
- block_list.extend(bt)
1016
- blocks_in_group = len(bt)
1017
- if blocks_in_group > 0:
1018
- scale = 1.0 / blocks_in_group
1019
- block_scales.extend([scale] * blocks_in_group)
1020
-
1021
- block_mapping_nested: List[List[int]] = [
1022
- [i] * b_u for i, b_u in enumerate(blocks_used)
1035
+ last_block_usage = [
1036
+ slot[0] % self.block_size + 1 for slot in slot_mapping
1037
]
1024
- block_mapping: List[int] = list(
1025
- itertools.chain.from_iterable(block_mapping_nested))
1038
+ block_groups = [[i] * len(bt) for i, bt in enumerate(block_tables)]
1039
+ block_usage = [[self.block_size] * (len(bt) - 1) + [lbu]
1040
+ for bt, lbu in zip(block_tables, last_block_usage)
1041
+ if bt]
1042
+
1043
+ block_list = flatten(block_tables)
1044
+ block_groups = flatten(block_groups)
1045
+ block_usage = flatten(block_usage)
1046
+
1047
+ assert len(block_list) == len(block_groups)
1048
+ assert len(block_list) == len(block_usage)
1049
+
1050
+ padding_fn = None
1051
+ if self.use_contiguous_pa:
1052
+ block_bucket_size = max(max(block_list) + 1, len(block_list))
1053
+ block_bucket_size = find_bucket(
1054
+ block_bucket_size,
1055
+ self.bucketing_global_state.decode_block_bucket_cfg)
1056
+ indices: List[Any]
1057
+ indices = [None] * block_bucket_size
1058
+ for i, bid in enumerate(block_list):
1059
+ indices[bid] = i
1060
+ padding_fn = lambda tensor, pad_value: gather_list(
1061
+ tensor, indices, pad_value)
1062
+ else:
1063
+ block_bucket_size = find_bucket(
1064
+ len(block_list),
1065
+ self.bucketing_global_state.decode_block_bucket_cfg)
1066
+ padding_fn = lambda tensor, pad_value: pad_list(
1067
+ tensor, block_bucket_size, pad_value)
1068
1027
- last_block = [
1028
- sl % self.block_size + 1 for sl in itertools.chain(*slot_mapping)
1029
- ]
1030
- block_usage = [[self.block_size] * (b_u - 1) + [lb]
1031
- for b_u, lb in zip(blocks_used, last_block)]
1032
- block_usage = list(itertools.chain(*block_usage))
1033
-
1034
- block_bucket_size = find_bucket(
1035
- len(block_list),
1036
- self.bucketing_global_state.decode_block_bucket_cfg)
1037
- block_list = pad_list(block_list, block_bucket_size, _PAD_BLOCK_ID)
1038
- block_mapping = pad_list(block_mapping, block_bucket_size, -1)
1039
- block_usage = pad_list(block_usage, block_bucket_size, 1)
1040
- block_scales = pad_list(block_scales, block_bucket_size, 0.0)
1069
+ block_list = padding_fn(block_list, _PAD_BLOCK_ID)
1070
+ block_groups = padding_fn(block_groups, -1)
1071
+ block_usage = padding_fn(block_usage, 1)
1072
1073
block_list = torch.tensor(block_list,
1074
dtype=torch.int,
1075
device=self.device)
1045
- block_mapping = torch.tensor(block_mapping,
1046
- dtype=torch.long,
1047
- device=self.device)
1076
+ block_groups = torch.tensor(block_groups,
1077
+ dtype=torch.int,
1078
+ device=self.device)
1079
block_usage = torch.tensor(block_usage,
1080
dtype=self.model_config.dtype,
1081
device=self.device)
1051
-
1082
slot_mapping = torch.tensor(slot_mapping,
1083
dtype=torch.long,
1084
device=self.device)
1085
1086
block_indices, block_offsets = precompute_indices_and_offsets(
1087
self.block_size, slot_mapping, False)
1058
- block_scales = torch.tensor(block_scales,
1059
- dtype=self.model_config.dtype,
1060
- device=self.device)
1088
1089
attn_metadata = self.attn_backend.make_metadata(
1090
is_prompt=False,
1091
block_list=block_list,
1065
- block_mapping=block_mapping,
1092
+ block_mapping=None,
1093
block_usage=block_usage,
1094
block_indices=block_indices,
1095
block_offsets=block_offsets,
1069
- block_scales=block_scales,
1096
+ block_scales=None,
1097
+ block_groups=block_groups,
1098
attn_bias=None,
1099
seq_lens_tensor=None,
1100
num_prefills=0,
@@ -1280,7 +1308,7 @@ class HPUModelRunnerBase(ModelRunnerBase[TModelInputForHPU]):
1308
attention_metadata = subtuple(metadata, 'TrimmedAttentionMetadata', [
1309
'attn_bias', 'seq_lens_tensor', 'block_list', 'block_mapping',
1310
'block_usage', 'slot_mapping', 'is_prompt', 'block_indices',
1283
- 'block_offsets', 'block_scales'
1311
+ 'block_offsets', 'block_scales', 'block_groups'
1312
])
1313
return attention_metadata
1314