dwehr's picture
Migrate action viewer to local Cosmos generation
9f818c5
Raw
History Blame Contribute Delete
13.4 kB
# SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: OpenMDW-1.1
"""
Imaginaire4 Attention Subpackage:
Unified implementation for all Attention implementations.
Frontend APIs
"""
import torch
from cosmos_framework.model.attention.flash2.checks import flash2_attention_check
from cosmos_framework.model.attention.flash3.checks import flash3_attention_check
from cosmos_framework.model.attention.masks import CausalType
from cosmos_framework.model.attention.natten.checks import natten_attention_check, natten_multi_dim_attention_check
from cosmos_framework.model.attention.utils import get_arch_tag
from cosmos_framework.model.attention.utils.environment import (
filter_attention_backends,
filter_multi_dim_attention_backends,
)
from cosmos_framework.model.attention.utils.safe_ops import log
from cosmos_framework.model.attention.utils.safe_ops.functools import lru_cache
BACKEND_CHECK_MAP = {
"natten": natten_attention_check,
"flash2": flash2_attention_check,
"flash3": flash3_attention_check,
}
BACKEND_MULTI_DIM_CHECK_MAP = {
"natten": natten_multi_dim_attention_check,
}
def is_backend_compatible(
backend: str,
query_shape: torch.Size,
key_shape: torch.Size,
value_shape: torch.Size,
dtype: torch.dtype,
device: torch.device,
requires_grad: bool,
is_causal: bool,
causal_type: CausalType | None,
is_varlen: bool,
deterministic: bool = False,
raise_error: bool = False,
) -> bool:
"""
Input validation function a specified backend.
Runs the common and backend-specific checks. Returns False if any checks fail, otherwise True.
Parameters:
backend (str): selected backend.
query_shape (torch.Size): Shape of 4-D query tensor (`[batch, seqlen, heads, head_dim]`).
key_shape (torch.Size): Shape of 4-D key tensor (`[batch, seqlen_kv, heads_kv, head_dim]`).
value_shape (torch.Size): Shape of 4-D value tensor (`[batch, seqlen_kv, heads_kv, head_dim_v]`).
dtype (torch.dtype): Data type of tensors.
device (torch.device): Device of tensors.
requires_grad (bool): Whether tensors require gradients (training vs inference).
is_causal (bool): whether or not causal masking is enabled.
causal_type (CausalType): causal masking mode. Choices: `CausalType.TopLeft`,
`CausalType.BottomRight`. Required when `is_causal = True`.
is_varlen (bool): whether or not a variable length (varlen) use case. Must be inferred
beforehand based on arguments such as seqlens_{Q,KV} or cumulative_seqlen_{Q,KV} being
passed.
deterministic (bool): Deterministic backward pass required.
raise_error (bool): whether to raise an error if any checks fail or no backend is selected,
instead of just returning False. Default is False.
Returns:
success (bool): whether use case is compatible with the backend.
"""
if backend is None:
raise ValueError("Cannot pass None backend to is_backend_compatible.")
if backend not in BACKEND_CHECK_MAP:
raise ValueError(f"Unrecognized backend name {backend}.")
return BACKEND_CHECK_MAP[backend](
query_shape=query_shape,
key_shape=key_shape,
value_shape=value_shape,
dtype=dtype,
device=device,
requires_grad=requires_grad,
is_causal=is_causal,
causal_type=causal_type,
is_varlen=is_varlen,
deterministic=deterministic,
raise_error=raise_error,
)
def get_backend_list(arch_tag: int) -> list[str]:
"""
Returns list of supported backends according to arch tag (attention.utils.get_arch_tag).
Backends are ordered based on their known performance levels, so that the best-performing
compatible backend is selected.
The returned list can be filtered via environment variable.
See `filter_attention_backends` for details.
Parameters:
arch_tag (int): Arch tag for the current CUDA device. Example: 80 for A100, 90 for H100.
Returns:
backend_list (list[str]): a list of backend names (string). Empty if device is not supported.
"""
if arch_tag < 75:
log.debug(f"Minimum architecture supported for Attention is 75, got {arch_tag=}.")
return []
default_backends = []
if arch_tag == 90:
default_backends = [
"flash3",
"natten",
"flash2",
]
elif arch_tag in [100, 103]:
default_backends = [
"natten",
"flash2",
]
elif arch_tag >= 80:
default_backends = [
"flash2",
"natten",
]
else:
default_backends = ["natten"]
# Apply environment variable filtering
return filter_attention_backends(default_backends)
@lru_cache
def choose_backend(
query_shape: torch.Size,
key_shape: torch.Size,
value_shape: torch.Size,
dtype: torch.dtype,
device: torch.device,
requires_grad: bool,
is_causal: bool,
causal_type: CausalType | None,
is_varlen: bool,
deterministic: bool = False,
backend: str | None = None,
raise_error: bool = True,
) -> str | None:
"""
Selects a compatible backend, unless one is already selected, which runs its corresponding
checks.
Parameters:
query_shape (torch.Size): Shape of 4-D query tensor (`[batch, seqlen, heads, head_dim]`).
key_shape (torch.Size): Shape of 4-D key tensor (`[batch, seqlen_kv, heads_kv, head_dim]`).
value_shape (torch.Size): Shape of 4-D value tensor (`[batch, seqlen_kv, heads_kv, head_dim_v]`).
dtype (torch.dtype): Data type of tensors.
device (torch.device): Device of tensors.
requires_grad (bool): Whether tensors require gradients (training vs inference).
is_causal (bool): whether or not causal masking is enabled.
causal_type (CausalType): causal masking mode. Choices: `CausalType.TopLeft`,
`CausalType.BottomRight`. Required when `is_causal = True`.
is_varlen (bool): whether or not a variable length (varlen) use case. Must be inferred
beforehand based on arguments such as seqlens_{Q,KV} or cumulative_seqlen_{Q,KV} being
passed.
deterministic (bool): Deterministic backward pass required.
backend (str | None): selected backend, if any.
raise_error (bool): whether to raise an error if any checks fail or no backend is selected,
instead of just returning False. Default is **True**.
Returns:
backend (str | None): selected backend, or None if no backends are compatible.
"""
if backend is not None:
if is_backend_compatible(
backend=backend,
query_shape=query_shape,
key_shape=key_shape,
value_shape=value_shape,
dtype=dtype,
device=device,
requires_grad=requires_grad,
is_causal=is_causal,
causal_type=causal_type,
is_varlen=is_varlen,
deterministic=deterministic,
raise_error=raise_error,
):
return backend
return None
arch_tag = get_arch_tag(device)
backend_list = get_backend_list(arch_tag)
for backend in backend_list:
if is_backend_compatible(
backend=backend,
query_shape=query_shape,
key_shape=key_shape,
value_shape=value_shape,
dtype=dtype,
device=device,
requires_grad=requires_grad,
is_causal=is_causal,
causal_type=causal_type,
is_varlen=is_varlen,
deterministic=deterministic,
raise_error=False,
):
return backend
if not raise_error:
return None
raise ValueError(
"Could not find a compatible Attention backend for this use case / device. "
"Try running with debug logs to find out why."
)
def is_multi_dim_backend_compatible(
backend: str,
query_shape: torch.Size,
key_shape: torch.Size,
value_shape: torch.Size,
dtype: torch.dtype,
device: torch.device,
requires_grad: bool,
deterministic: bool = False,
raise_error: bool = False,
) -> bool:
"""
Input validation function a specified multi-dimensional backend.
Runs the common and backend-specific checks. Returns False if any checks fail, otherwise True.
Parameters:
backend (str): selected backend.
query_shape (torch.Size): Shape of 4-D, 5-D, or 6-D query tensor (`[batch, *token_layout_shape, heads, head_dim]`).
key_shape (torch.Size): Shape of 4-D, 5-D, or 6-D key tensor (`[batch, *token_layout_shape, heads_kv, head_dim]`).
value_shape (torch.Size): Shape of 4-D, 5-D, or 6-D value tensor (`[batch, *token_layout_shape, heads_kv, head_dim_v]`).
dtype (torch.dtype): Data type of tensors.
device (torch.device): Device of tensors.
requires_grad (bool): Whether tensors require gradients (training vs inference).
deterministic (bool): Deterministic backward pass required.
raise_error (bool): whether to raise an error if any checks fail or no backend is selected,
instead of just returning False. Default is False.
Returns:
success (bool): whether use case is compatible with the backend.
"""
if backend is None:
raise ValueError("Cannot pass None backend to is_backend_compatible.")
if backend not in BACKEND_MULTI_DIM_CHECK_MAP:
raise ValueError(f"Unrecognized backend name {backend}.")
return BACKEND_MULTI_DIM_CHECK_MAP[backend](
query_shape=query_shape,
key_shape=key_shape,
value_shape=value_shape,
dtype=dtype,
device=device,
requires_grad=requires_grad,
deterministic=deterministic,
raise_error=raise_error,
)
def get_multi_dim_backend_list(arch_tag: int) -> list[str]:
"""
Returns list of supported multi-dimensional backends according to arch tag (attention.utils.get_arch_tag).
Backends are ordered based on their known performance levels, so that the best-performing
compatible backend is selected.
The returned list can be filtered via environment variable.
See `filter_multi_dim_attention_backends` for details.
Parameters:
arch_tag (int): Arch tag for the current CUDA device. Example: 80 for A100, 90 for H100.
Returns:
backend_list (list[str]): a list of backend names (string). Empty if device is not supported.
"""
if arch_tag < 75:
log.debug(f"Minimum architecture supported for Multi-Dimensional Attention is 75, got {arch_tag=}.")
return []
# NATTEN is the only supported backend for now
default_backends = ["natten"]
# Apply environment variable filtering
return filter_multi_dim_attention_backends(default_backends)
@lru_cache
def choose_multi_dim_backend(
query_shape: torch.Size,
key_shape: torch.Size,
value_shape: torch.Size,
dtype: torch.dtype,
device: torch.device,
requires_grad: bool,
deterministic: bool = False,
backend: str | None = None,
) -> str:
"""
Selects a compatible multi-dimensional backend, unless one is already selected, which runs its
corresponding checks.
Parameters:
query_shape (torch.Size): Shape of 4-D, 5-D, or 6-D query tensor (`[batch, *token_layout_shape, heads, head_dim]`).
key_shape (torch.Size): Shape of 4-D, 5-D, or 6-D key tensor (`[batch, *token_layout_shape, heads_kv, head_dim]`).
value_shape (torch.Size): Shape of 4-D, 5-D, or 6-D value tensor (`[batch, *token_layout_shape, heads_kv, head_dim_v]`).
dtype (torch.dtype): Data type of tensors.
device (torch.device): Device of tensors.
requires_grad (bool): Whether tensors require gradients (training vs inference).
deterministic (bool): Deterministic backward pass required.
backend (str | None): selected backend, if any.
Returns:
backend (str): selected backend.
"""
if backend is not None:
assert is_multi_dim_backend_compatible(
backend=backend,
query_shape=query_shape,
key_shape=key_shape,
value_shape=value_shape,
dtype=dtype,
device=device,
requires_grad=requires_grad,
deterministic=deterministic,
raise_error=True,
)
return backend
arch_tag = get_arch_tag(device)
backend_list = get_multi_dim_backend_list(arch_tag)
for backend in backend_list:
if is_multi_dim_backend_compatible(
backend=backend,
query_shape=query_shape,
key_shape=key_shape,
value_shape=value_shape,
dtype=dtype,
device=device,
requires_grad=requires_grad,
deterministic=deterministic,
raise_error=False,
):
return backend
raise ValueError(
"Could not find a compatible Multi-Dimensional Attention backend for this use case / device. "
"Try running with debug logs to find out why."
)