main
py 747 lines 27 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 # Copyright (c) 2023, Tri Dao.
4 # ruff: noqa: E501
5
6
7 import torch
8
9 # isort: off
10 # We need to import the CUDA kernels after importing torch
11 # Use relative import to support build-from-source installation in vLLM
12
13 try:
14 from . import _vllm_fa2_C # type: ignore[attr-defined] # noqa: F401
15
16 FA2_UNAVAILABLE_REASON = None
17 FA2_AVAILABLE = True
18 except ImportError as e:
19 FA2_UNAVAILABLE_REASON = str(e)
20 FA2_AVAILABLE = False
21
22 try:
23 from . import _vllm_fa3_C # type: ignore[attr-defined] # noqa: F401
24
25 FA3_UNAVAILABLE_REASON = None
26 FA3_AVAILABLE = True
27 except ImportError as e:
28 FA3_UNAVAILABLE_REASON = str(e)
29 FA3_AVAILABLE = False
30
31
32 try:
33 import os
34
35 _cute_interface_path = os.path.join(
36 os.path.dirname(__file__), "cute", "interface.py"
37 )
38 if not os.path.exists(_cute_interface_path):
39 raise ImportError("vllm.vllm_flash_attn.cute.interface not found")
40
41 FA4_UNAVAILABLE_REASON = None
42 FA4_AVAILABLE = True
43 except (ImportError, ModuleNotFoundError) as e:
44 FA4_UNAVAILABLE_REASON = str(e)
45 FA4_AVAILABLE = False
46
47 # isort: on
48
49 DEFAULT_FA_VERSION = 2
50
51
52 def _is_fa2_supported() -> tuple[bool, str | None]:
53 if not FA2_AVAILABLE:
54 return False, f"FA2 is unavailable due to: {FA2_UNAVAILABLE_REASON}"
55 from vllm.platforms import current_platform
56
57 if not current_platform.has_device_capability(80):
58 return False, "FA2 is only supported on devices with compute capability >= 8"
59 return True, None
60
61
62 def _is_fa3_supported() -> tuple[bool, str | None]:
63 if not FA3_AVAILABLE:
64 return False, f"FA3 is unavailable due to: {FA3_UNAVAILABLE_REASON}"
65 from vllm.platforms import current_platform
66
67 if not current_platform.is_device_capability_family(90):
68 return False, "FA3 is only supported on devices with compute capability 9.x"
69 return True, None
70
71
72 def _is_fa4_supported() -> tuple[bool, str | None]:
73 if not FA4_AVAILABLE:
74 return False, f"FA4 is unavailable due to: {FA4_UNAVAILABLE_REASON}"
75 from vllm.platforms import current_platform
76
77 if not (
78 current_platform.is_device_capability_family(90)
79 or current_platform.is_device_capability_family(100)
80 or current_platform.is_device_capability_family(110)
81 ):
82 return (
83 False,
84 "FA4 is only supported on devices with compute capability 9.x, 10.x, or 11.x",
85 )
86 return True, None
87
88
89 def is_fa_version_supported(fa_version: int) -> bool:
90 if fa_version == 2:
91 return _is_fa2_supported()[0]
92 elif fa_version == 3:
93 return _is_fa3_supported()[0]
94 elif fa_version == 4:
95 return _is_fa4_supported()[0]
96 else:
97 raise ValueError(f"Unsupported FA version: {fa_version}")
98
99
100 def fa_version_unsupported_reason(fa_version: int) -> str | None:
101 if fa_version == 2:
102 return _is_fa2_supported()[1]
103 elif fa_version == 3:
104 return _is_fa3_supported()[1]
105 elif fa_version == 4:
106 return _is_fa4_supported()[1]
107 else:
108 raise ValueError(f"Unsupported FA version: {fa_version}")
109
110
111 #
112 # For vLLM we only care about `flash_attn_varlen_func` and
113 # `flash_attn_with_kvcache` so we only maintain wrappers for these two.
114 #
115
116
117 def maybe_contiguous(x):
118 return x.contiguous() if x is not None and x.stride(-1) != 1 else x
119
120
121 # NOTE only used in FA3
122 def get_scheduler_metadata(
123 batch_size,
124 max_seqlen_q,
125 max_seqlen_k,
126 num_heads_q,
127 num_heads_kv,
128 headdim,
129 cache_seqlens: torch.Tensor,
130 qkv_dtype=torch.bfloat16,
131 headdim_v=None,
132 cu_seqlens_q: torch.Tensor | None = None,
133 cu_seqlens_k_new: torch.Tensor | None = None,
134 cache_leftpad: torch.Tensor | None = None,
135 page_size: int | None = None,
136 max_seqlen_k_new=0,
137 causal=False,
138 window_size=(-1, -1), # -1 means infinite context window
139 has_softcap=False,
140 num_splits=0, # Can be tuned for speed
141 pack_gqa=None, # Can be tuned for speed
142 sm_margin=0, # Can be tuned if some SMs are used for communication
143 ):
144 cache_seqlens = maybe_contiguous(cache_seqlens)
145 if headdim_v is None:
146 headdim_v = headdim
147 scheduler_metadata = torch.ops._vllm_fa3_C.get_scheduler_metadata(
148 batch_size,
149 max_seqlen_q,
150 max_seqlen_k,
151 num_heads_q,
152 num_heads_kv,
153 headdim,
154 headdim_v,
155 qkv_dtype,
156 cache_seqlens,
157 cu_seqlens_q,
158 None, # cu_seqlens_k
159 cu_seqlens_k_new,
160 None, # seqused_q
161 cache_leftpad,
162 page_size,
163 max_seqlen_k_new,
164 causal,
165 window_size[0],
166 window_size[1],
167 has_softcap,
168 num_splits,
169 pack_gqa,
170 sm_margin,
171 )
172
173 return scheduler_metadata
174
175
176 def flash_attn_varlen_func(
177 q,
178 k,
179 v,
180 max_seqlen_q,
181 cu_seqlens_q,
182 max_seqlen_k,
183 cu_seqlens_k=None, # only used for non-paged prefill
184 seqused_k=None,
185 q_v=None,
186 dropout_p=0.0,
187 softmax_scale=None,
188 causal=False,
189 window_size: list[int] | None = None,
190 softcap=0.0, # 0.0 means deactivated
191 alibi_slopes=None,
192 deterministic=False,
193 return_attn_probs=False,
194 block_table=None,
195 return_softmax_lse=False,
196 out=None,
197 # FA3 Only
198 scheduler_metadata=None,
199 q_descale=None,
200 k_descale=None,
201 v_descale=None,
202 num_splits: int = 0,
203 # FA4 Only
204 output_scale=None,
205 # Version selector
206 fa_version: int = DEFAULT_FA_VERSION,
207 s_aux=None,
208 cp_world_size=1,
209 cp_rank=0,
210 cp_tot_seqused_k=None,
211 # FA4 only
212 mask_mod=None,
213 block_sparse_tensors=None,
214 aux_tensors=None,
215 aux_tensor_leading_dims=None,
216 dynamic_causal: "torch.Tensor | None" = None,
217 ):
218 """dropout_p should be set to 0.0 during evaluation
219 Supports multi-query and grouped-query attention (MQA/GQA) by passing in K, V with fewer heads
220 than Q. Note that the number of heads in Q must be divisible by the number of heads in KV.
221 For example, if Q has 6 heads and K, V have 2 heads, head 0, 1, 2 of Q will attention to head
222 0 of K, V, and head 3, 4, 5 of Q will attention to head 1 of K, V.
223
224 If causal=True, the causal mask is aligned to the bottom right corner of the attention matrix.
225 For example, if seqlen_q = 2 and seqlen_k = 5, the causal mask (1 = keep, 0 = masked out) is:
226 1 1 1 1 0
227 1 1 1 1 1
228 If seqlen_q = 5 and seqlen_k = 2, the causal mask is:
229 0 0
230 0 0
231 0 0
232 1 0
233 1 1
234 If the row of the mask is all zero, the output will be zero.
235
236 If window_size != (-1, -1), implements sliding window local attention. Query at position i
237 will only attend to keys between
238 [i + seqlen_k - seqlen_q - window_size[0], i + seqlen_k - seqlen_q + window_size[1]] inclusive.
239
240 Arguments:
241 q: (total_q, nheads, headdim), where total_q = total number of query tokens in the batch.
242 k: (total_k, nheads_k, headdim), where total_k = total number of key tokens in the batch.
243 v: (total_k, nheads_k, headdim), where total_k = total number of key tokens in the batch.
244 cu_seqlens_q: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths
245 of the sequences in the batch, used to index into q.
246 cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths
247 of the sequences in the batch, used to index into kv.
248 max_seqlen_q: int. Maximum query sequence length in the batch.
249 max_seqlen_k: int. Maximum key sequence length in the batch.
250 dropout_p: float. Dropout probability.
251 softmax_scale: float. The scaling of QK^T before applying softmax.
252 Default to 1 / sqrt(headdim).
253 causal: bool. Whether to apply causal attention mask (e.g., for auto-regressive modeling).
254 window_size: (left, right). If not (-1, -1), implements sliding window local attention.
255 softcap: float. Anything > 0 activates softcapping attention.
256 alibi_slopes: (nheads,) or (batch_size, nheads), fp32. A bias of
257 (-alibi_slope * |i + seqlen_k - seqlen_q - j|)
258 is added to the attention score of query i and key j.
259 deterministic: bool. Whether to use the deterministic implementation of the backward pass,
260 which is slightly slower and uses more memory. The forward pass is always deterministic.
261 return_attn_probs: bool. Whether to return the attention probabilities. This option is for
262 testing only. The returned probabilities are not guaranteed to be correct
263 (they might not have the right scaling).
264 seqused_k: (batch_size,), dtype torch.int32. Actual number of key tokens per
265 sequence. Mutually exclusive with cu_seqlens_k, and required when
266 block_table is given.
267 q_v: optional value tensor fused with q. FA3 only.
268 block_table: (batch_size, max_blocks_per_seq), dtype torch.int32. Paged KV
269 cache block table. Requires seqused_k.
270 return_softmax_lse: bool. Whether to also return softmax_lse.
271 out: optional tensor to write the output into.
272 scheduler_metadata: precomputed scheduling metadata. Not supported by FA2.
273 q_descale: descale factor for FP8 q. Not supported by FA2, and ignored by
274 FA4 when the inputs are not FP8.
275 k_descale: descale factor for FP8 k. Same constraints as q_descale.
276 v_descale: descale factor for FP8 v. Same constraints as q_descale.
277 num_splits: int. Number of splits for the split-KV kernel; 0 lets the kernel
278 choose. FA2 only supports 0 or 1.
279 output_scale: scale for fused FP8 output quantization. FA4 only.
280 fa_version: int. FlashAttention major version to dispatch to.
281 s_aux: learnable per-head attention sink logits. Not supported by FA2.
282 cp_world_size: int. Context parallel world size.
283 cp_rank: int. Rank of this shard within the context parallel group.
284 cp_tot_seqused_k: (batch_size,), dtype torch.int32. Key lengths across the
285 whole context parallel group.
286 mask_mod: optional callable applying a custom mask. Not supported by FA2.
287 block_sparse_tensors: block-sparse index tensors. FA4 only, and must
288 materialize full_block_cnt and full_block_idx.
289 aux_tensors: auxiliary tensors consumed by mask_mod. FA4 only.
290 aux_tensor_leading_dims: leading dimensions of each entry in aux_tensors.
291 dynamic_causal: optional per-sequence causal offsets. FA4 only.
292
293 Return:
294 out: (total, nheads, headdim).
295 softmax_lse [optional, if return_softmax_lse=True]: (nheads, total_q_seqlen). The
296 logsumexp of each row of the matrix QK^T * scaling (e.g., log of the softmax
297 normalization factor).
298
299 """
300 assert cu_seqlens_k is not None or seqused_k is not None, (
301 "cu_seqlens_k or seqused_k must be provided"
302 )
303 assert cu_seqlens_k is None or seqused_k is None, (
304 "cu_seqlens_k and seqused_k cannot be provided at the same time"
305 )
306 assert block_table is None or seqused_k is not None, (
307 "seqused_k must be provided if block_table is provided"
308 )
309
310 assert output_scale is None or fa_version == 4, (
311 f"Fused FP8 output (output_scale) is only supported by FA4, "
312 f"got fa_version={fa_version}"
313 )
314
315 if softmax_scale is None:
316 softmax_scale = q.shape[-1] ** (-0.5)
317 # custom op does not support non-tuple input
318 real_window_size: tuple[int, int]
319 if window_size is None:
320 real_window_size = (-1, -1)
321 else:
322 assert len(window_size) == 2
323 real_window_size = (window_size[0], window_size[1])
324 q, k, v = [maybe_contiguous(x) for x in (q, k, v)]
325
326 dummy_cu_seqlens_k = torch.empty_like(cu_seqlens_q)
327
328 if fa_version == 2:
329 if (
330 scheduler_metadata is not None
331 and q_descale is not None
332 and k_descale is not None
333 and v_descale is not None
334 ):
335 raise NotImplementedError(
336 "FA2 does not support scheduler_metadata, q_descale, "
337 "k_descale, v_descale"
338 )
339 if s_aux is not None:
340 raise NotImplementedError("FA2 does not support s_aux")
341 if num_splits > 1:
342 raise NotImplementedError("FA2 does not support num_splits > 1")
343 if mask_mod is not None:
344 raise NotImplementedError("FA2 does not support mask_mod")
345 if aux_tensors is not None:
346 raise NotImplementedError("FA2 does not support aux_tensors")
347 out, softmax_lse = torch.ops._vllm_fa2_C.varlen_fwd(
348 q,
349 k,
350 v,
351 out,
352 cu_seqlens_q,
353 # cu_seqlens_k not used since we use seqused_k, but flash_api.cpp
354 # still wants it so we pass all zeros
355 dummy_cu_seqlens_k if cu_seqlens_k is None else cu_seqlens_k,
356 seqused_k,
357 None,
358 block_table,
359 alibi_slopes,
360 max_seqlen_q,
361 max_seqlen_k,
362 dropout_p,
363 softmax_scale,
364 False,
365 causal,
366 real_window_size[0],
367 real_window_size[1],
368 softcap,
369 return_softmax_lse and dropout_p > 0,
370 num_splits,
371 None,
372 )
373 elif fa_version == 3:
374 assert alibi_slopes is None, "Alibi is not supported in FA3"
375 if mask_mod is not None:
376 raise NotImplementedError("FA3 does not support mask_mod")
377 if aux_tensors is not None:
378 raise NotImplementedError("FA3 does not support aux_tensors")
379 out, softmax_lse, _, _ = torch.ops._vllm_fa3_C.fwd(
380 q,
381 k,
382 v,
383 None,
384 None, # k_new, v_new
385 q_v,
386 out,
387 cu_seqlens_q,
388 cu_seqlens_k, # cu_seqlens_k
389 None, # cu_seqlens_k_new
390 None,
391 seqused_k, # seqused_q, seqused_k
392 max_seqlen_q,
393 max_seqlen_k,
394 block_table,
395 None, # kv_batch_idx
396 None, # leftpad_k
397 None,
398 None,
399 None, # rotary_cos, rotary_sin, seqlens_rotary
400 q_descale,
401 k_descale,
402 v_descale,
403 softmax_scale,
404 causal,
405 real_window_size[0],
406 real_window_size[1],
407 softcap,
408 True, # rotary_interleaved
409 scheduler_metadata,
410 num_splits,
411 None, # pack_gqa
412 0, # sm_margin
413 s_aux, # s_aux
414 cp_world_size,
415 cp_rank,
416 cp_tot_seqused_k,
417 )
418 elif fa_version == 4:
419 assert alibi_slopes is None, "Alibi is not supported in FA4"
420 if block_sparse_tensors is not None:
421 assert block_sparse_tensors.full_block_cnt is not None, (
422 "FA4 block_sparse_tensors must materialize empty full_block_cnt "
423 "instead of passing None"
424 )
425 assert block_sparse_tensors.full_block_idx is not None, (
426 "FA4 block_sparse_tensors must materialize empty full_block_idx "
427 "instead of passing None"
428 )
429
430 # FA4 only accepts descales for FP8 inputs. The attention backends
431 # initialize these tensors even when the inputs are not quantized.
432 if v.dtype not in (torch.float8_e4m3fn, torch.float8_e5m2):
433 q_descale = k_descale = v_descale = None
434
435 from vllm.vllm_flash_attn.cute.interface import _flash_attn_fwd
436
437 # SM90 FA4 fp8-KV path: fp8 e4m3 paged K/V dequantized and the K/V descale folded
438 # in-kernel; accepts bf16/fp16 Q and writes O in its native dtype (no Q cast, no
439 # output copy). Only the (batch, num_kv_heads) f32 K/V descales are forwarded.
440 fa4_fp8_kv_dequant = (
441 k.dtype == torch.float8_e4m3fn
442 and torch.cuda.get_device_capability()[0] == 9
443 )
444
445 out, softmax_lse, _, _ = _flash_attn_fwd(
446 q,
447 k,
448 v,
449 cu_seqlens_q=cu_seqlens_q,
450 cu_seqlens_k=cu_seqlens_k,
451 seqused_k=seqused_k,
452 max_seqlen_q=max_seqlen_q,
453 max_seqlen_k=max_seqlen_k,
454 page_table=block_table,
455 softmax_scale=softmax_scale,
456 causal=causal,
457 dynamic_causal=dynamic_causal,
458 softcap=softcap,
459 window_size_left=real_window_size[0] if real_window_size[0] >= 0 else None,
460 window_size_right=real_window_size[1] if real_window_size[1] >= 0 else None,
461 num_splits=num_splits,
462 return_lse=return_softmax_lse,
463 out=out,
464 learnable_sink=s_aux,
465 mask_mod=mask_mod,
466 block_sparse_tensors=block_sparse_tensors,
467 aux_tensors=aux_tensors,
468 aux_tensor_leading_dims=aux_tensor_leading_dims,
469 q_descale=None if fa4_fp8_kv_dequant else q_descale,
470 k_descale=k_descale,
471 v_descale=v_descale,
472 output_scale=output_scale,
473 fp8_kv_dequant=fa4_fp8_kv_dequant,
474 )
475 else:
476 raise ValueError(f"Unsupported FA version: {fa_version}")
477 return (out, softmax_lse) if return_softmax_lse else out
478
479
480 def compile_flash_attn_varlen_func_from_specs(
481 *,
482 q_shape: tuple[int, ...],
483 k_shape: tuple[int, ...],
484 v_shape: tuple[int, ...],
485 q_dtype: torch.dtype,
486 v_stride: tuple[int, ...] | None = None,
487 k_stride: tuple[int, ...] | None = None,
488 cu_seqlens_q_shape: tuple[int, ...] | None = None,
489 cu_seqlens_k_shape: tuple[int, ...] | None = None,
490 max_seqlen_q: int | None = None,
491 max_seqlen_k: int | None = None,
492 dropout_p: float = 0.0,
493 softmax_scale=None,
494 causal=False,
495 window_size: list[int] | None = None,
496 deterministic=False,
497 return_softmax_lse=False,
498 num_splits: int = 0,
499 fa_version: int = DEFAULT_FA_VERSION,
500 seqused_k_shape: tuple[int, ...] | None = None,
501 page_table_shape: tuple[int, ...] | None = None,
502 softcap: float | None = None,
503 ) -> None:
504 if fa_version != 4:
505 raise ValueError(
506 f"Compile-only FlashAttention is only supported for FA4, got FA{fa_version}"
507 )
508 if dropout_p != 0.0:
509 raise NotImplementedError("FA4 compile-only wrapper does not support dropout")
510 del deterministic
511
512 from vllm.vllm_flash_attn.cute.interface import (
513 _flash_attn_fwd,
514 _make_compile_only_tensor_spec,
515 )
516
517 real_window_size: tuple[int, int]
518 if window_size is None:
519 real_window_size = (-1, -1)
520 else:
521 assert len(window_size) == 2
522 real_window_size = (window_size[0], window_size[1])
523
524 if softmax_scale is None:
525 softmax_scale = q_shape[-1] ** (-0.5)
526
527 q = _make_compile_only_tensor_spec(q_shape, q_dtype)
528 k = _make_compile_only_tensor_spec(k_shape, q_dtype, stride=k_stride)
529 v = _make_compile_only_tensor_spec(v_shape, q_dtype, stride=v_stride)
530 cu_seqlens_q = _make_compile_only_tensor_spec(cu_seqlens_q_shape, torch.int32, 4)
531 out = _make_compile_only_tensor_spec(
532 (*q_shape[:-1], v_shape[-1]),
533 q_dtype,
534 )
535 lse = None
536 if return_softmax_lse:
537 assert q is not None
538 if cu_seqlens_q_shape is None:
539 lse_shape = (*q.shape[:-3], q.shape[-2], q.shape[-3])
540 lse_stride = None
541 else:
542 lse_shape = (q.shape[-2], q.shape[0])
543 lse_stride = (None, 1)
544 lse = _make_compile_only_tensor_spec(
545 lse_shape,
546 torch.float32,
547 4,
548 stride=lse_stride,
549 )
550
551 _flash_attn_fwd(
552 q=q,
553 k=k,
554 v=v,
555 cu_seqlens_q=cu_seqlens_q,
556 cu_seqlens_k=_make_compile_only_tensor_spec(cu_seqlens_k_shape, torch.int32, 4),
557 seqused_k=_make_compile_only_tensor_spec(seqused_k_shape, torch.int32, 4),
558 page_table=_make_compile_only_tensor_spec(page_table_shape, torch.int32, 4),
559 max_seqlen_q=max_seqlen_q,
560 max_seqlen_k=max_seqlen_k,
561 softmax_scale=softmax_scale,
562 causal=causal,
563 softcap=softcap,
564 window_size_left=real_window_size[0],
565 window_size_right=real_window_size[1],
566 num_splits=num_splits,
567 return_lse=return_softmax_lse,
568 out=out,
569 lse=lse,
570 compile_only=True,
571 )
572
573
574 def sparse_attn_func(
575 q,
576 k,
577 v,
578 block_count,
579 block_offset,
580 column_count,
581 column_index,
582 dropout_p=0.0,
583 softmax_scale=None,
584 causal=False,
585 softcap=0.0, # 0.0 means deactivated
586 alibi_slopes=None,
587 deterministic=False,
588 return_attn_probs=False,
589 *,
590 return_softmax_lse=False,
591 out=None,
592 ):
593 """Compute attention with vertical and slash sparsity patterns.
594 Most Arguments are the same with the flash_attn_func interface, except for 4 extra args:
595 block_count and block_offset for slash sparsity patterns, and
596 column_count and column_index for vertical sparsity patterns.
597 For more details please refer to Appendix C.4.2 of paper https://arxiv.org/abs/2407.02490.
598
599 Arguments:
600 q: (batch_size, seqlen, nheads, headdim)
601 k: (batch_size, seqlen, nheads_k, headdim)
602 v: (batch_size, seqlen, nheads_k, headdim)
603 block_count: (batch_size, nheads, cdiv(seqlen, BLOCK_M))
604 block_offset: (batch_size, nheads, cdiv(seqlen, BLOCK_M), NNZ_S)
605 column_count: (batch_size, nheads, cdiv(seqlen, BLOCK_M))
606 column_index: (batch_size, nheads, cdiv(seqlen, BLOCK_M), NNZ_V)
607 dropout_p: float. Dropout probability.
608 softmax_scale: float. The scaling of QK^T before applying softmax.
609 Default to 1 / sqrt(headdim).
610 causal: bool. Whether to apply causal attention mask (e.g., for auto-regressive modeling).
611 alibi_slopes: (nheads,) or (batch_size, nheads), fp32. A bias of
612 (-alibi_slope * |i + seqlen_k - seqlen_q - j|)
613 is added to the attention score of query i and key j.
614 deterministic: bool. Whether to use the deterministic implementation of the backward pass,
615 which is slightly slower and uses more memory. The forward pass is always deterministic.
616 return_attn_probs: bool. Whether to return the attention probabilities. This option is for
617 testing only. The returned probabilities are not guaranteed to be correct
618 (they might not have the right scaling).
619 softcap: float. Anything > 0 activates softcapping attention.
620 return_softmax_lse: bool. Whether to also return softmax_lse.
621 out: optional tensor to write the output into.
622
623 Return:
624 out: (batch_size, seqlen, nheads, headdim).
625 softmax_lse [optional, if return_softmax_lse=True]: (batch_size, nheads, seqlen). The
626 logsumexp of each row of the matrix QK^T * scaling (e.g., log of the softmax
627 normalization factor).
628
629 """
630 if softmax_scale is None:
631 softmax_scale = q.shape[-1] ** (-0.5)
632
633 q, k, v = [maybe_contiguous(x) for x in (q, k, v)]
634 out, softmax_lse = torch.ops._vllm_fa2_C.fwd_sparse(
635 q,
636 k,
637 v,
638 block_count,
639 block_offset,
640 column_count,
641 column_index,
642 out,
643 alibi_slopes,
644 dropout_p,
645 softmax_scale,
646 causal,
647 softcap,
648 return_attn_probs and dropout_p > 0,
649 None,
650 )
651 return (out, softmax_lse) if return_softmax_lse else out
652
653
654 def sparse_attn_varlen_func(
655 q,
656 k,
657 v,
658 block_count,
659 block_offset,
660 column_count,
661 column_index,
662 cu_seqlens_q,
663 cu_seqlens_k,
664 max_seqlen_q,
665 max_seqlen_k,
666 dropout_p=0.0,
667 softmax_scale=None,
668 causal=False,
669 softcap=0.0, # 0.0 means deactivated
670 alibi_slopes=None,
671 deterministic=False,
672 return_attn_probs=False,
673 *,
674 return_softmax_lse=False,
675 out=None,
676 ):
677 """Compute attention with vertical and slash sparsity patterns.
678 Most Arguments are the same with the flash_attn_varlen_func interface, except for 4 extra args:
679 block_count and block_offset for slash sparsity patterns, and
680 column_count and column_index for vertical sparsity patterns.
681 For more details please refer to Appendix C.4.2 of paper https://arxiv.org/abs/2407.02490.
682
683 Arguments:
684 q: (total_q, nheads, headdim), where total_q = total number of query tokens in the batch.
685 k: (total_k, nheads_k, headdim), where total_k = total number of key tokens in the batch.
686 v: (total_k, nheads_k, headdim), where total_k = total number of key tokens in the batch.
687 block_count: (batch_size, nheads, cdiv(seqlen, BLOCK_M))
688 block_offset: (batch_size, nheads, cdiv(seqlen, BLOCK_M), NNZ_S)
689 column_count: (batch_size, nheads, cdiv(seqlen, BLOCK_M))
690 column_index: (batch_size, nheads, cdiv(seqlen, BLOCK_M), NNZ_V)
691 cu_seqlens_q: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths
692 of the sequences in the batch, used to index into q.
693 cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths
694 of the sequences in the batch, used to index into kv.
695 max_seqlen_q: int. Maximum query sequence length in the batch.
696 max_seqlen_k: int. Maximum key sequence length in the batch.
697 dropout_p: float. Dropout probability.
698 softmax_scale: float. The scaling of QK^T before applying softmax.
699 Default to 1 / sqrt(headdim).
700 causal: bool. Whether to apply causal attention mask (e.g., for auto-regressive modeling).
701 softcap: float. Anything > 0 activates softcapping attention.
702 alibi_slopes: (nheads,) or (batch_size, nheads), fp32. A bias of
703 (-alibi_slope * |i + seqlen_k - seqlen_q - j|)
704 is added to the attention score of query i and key j.
705 deterministic: bool. Whether to use the deterministic implementation of the backward pass,
706 which is slightly slower and uses more memory. The forward pass is always deterministic.
707 return_attn_probs: bool. Whether to return the attention probabilities. This option is for
708 testing only. The returned probabilities are not guaranteed to be correct
709 (they might not have the right scaling).
710 return_softmax_lse: bool. Whether to also return softmax_lse.
711 out: optional tensor to write the output into.
712
713 Return:
714 out: (total, nheads, headdim).
715 softmax_lse [optional, if return_softmax_lse=True]: (nheads, total_q_seqlen). The
716 logsumexp of each row of the matrix QK^T * scaling (e.g., log of the softmax
717 normalization factor).
718
719 """
720 if softmax_scale is None:
721 softmax_scale = q.shape[-1] ** (-0.5)
722
723 q, k, v = [maybe_contiguous(x) for x in (q, k, v)]
724 out, softmax_lse = torch.ops._vllm_fa2_C.varlen_fwd_sparse(
725 q,
726 k,
727 v,
728 block_count,
729 block_offset,
730 column_count,
731 column_index,
732 out,
733 cu_seqlens_q,
734 cu_seqlens_k,
735 None,
736 alibi_slopes,
737 max_seqlen_q,
738 max_seqlen_k,
739 dropout_p,
740 softmax_scale,
741 False,
742 causal,
743 softcap,
744 return_attn_probs and dropout_p > 0,
745 None,
746 )
747 return (out, softmax_lse) if return_softmax_lse else out