# SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project # Copyright (c) Microsoft Corporation and Jiarui Fang # SPDX-License-Identifier: Apache-2.0 # DeepSpeed Team & Jiarui Fang # Adapted from # https://github.com/feifeibear/long-context-attention/blob/main/yunchang/attention/layer.py import torch import torch.nn as nn from vllm_omni.diffusion.attention.backends.abstract import AttentionMetadata from vllm_omni.diffusion.attention.parallel import build_parallel_attention_strategy from vllm_omni.diffusion.attention.selector import get_attn_backend class Attention(nn.Module): def __init__( self, num_heads: int, head_size: int, causal: bool, softmax_scale: float, num_kv_heads: int | None = None, prefix: str = "", # ulysses attention scatter_idx: int = 2, gather_idx: int = 1, use_sync: bool = False, ): super().__init__() self.attn_backend = get_attn_backend(-1) self.attn_impl_cls = self.attn_backend.get_impl_cls() self.attention = self.attn_impl_cls( num_heads=num_heads, head_size=head_size, softmax_scale=softmax_scale, causal=causal, num_kv_heads=num_kv_heads, ) self.softmax_scale = softmax_scale self.scatter_idx = scatter_idx self.gather_idx = gather_idx self.use_sync = use_sync # Parallel attention (communication / resharding) is a pluggable strategy. # This keeps the attention kernel backend selection orthogonal. self.parallel = build_parallel_attention_strategy( scatter_idx=scatter_idx, gather_idx=gather_idx, use_sync=use_sync, ) def forward( self, query: torch.Tensor, key: torch.Tensor, value: torch.Tensor, attn_metadata: AttentionMetadata = None, ) -> torch.Tensor: # Parallel strategy may reshard/communicate QKV before the attention kernel. query, key, value, attn_metadata, ctx = self.parallel.pre_attention(query, key, value, attn_metadata) # shape: (batch_size, seq_len, num_heads, head_size) attn_output = self.attention.forward(query, key, value, attn_metadata) if isinstance(attn_output, tuple): attn_output = attn_output[0] # Parallel strategy may need to reverse resharding after the kernel. return self.parallel.post_attention(attn_output, ctx)