Skip to content

Commit e0b8796

Browse files
SolitaryThinkerjzhang38RandNMR73
committed
[feat]: Attn-QAT inference + training backends (deadcode) (Attn-QAT 4/12)
Add fastvideo/attention/backends/attn_qat_{infer,train}.py extracted from PR hao-ai-lab#1225. Backends not yet registered in the selector — full deadcode until activation (slice 12). Attn-QAT-Stack: 4/12 Co-Authored-By: jzhang38 <42993249+jzhang38@users.noreply.github.com> Co-Authored-By: RandNMR73 <99706358+RandNMR73@users.noreply.github.com>
1 parent 460f6e3 commit e0b8796

2 files changed

Lines changed: 275 additions & 0 deletions

File tree

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
import importlib
4+
import sys
5+
from collections.abc import Callable
6+
from pathlib import Path
7+
8+
import torch
9+
10+
from fastvideo.attention.backends.abstract import (
11+
AttentionBackend,
12+
AttentionImpl,
13+
AttentionMetadata,
14+
AttentionMetadataBuilder,
15+
)
16+
from fastvideo.logger import init_logger
17+
18+
logger = init_logger(__name__)
19+
20+
_project_root = Path(__file__).resolve().parent.parent.parent.parent
21+
_kernel_root = _project_root / "fastvideo-kernel"
22+
_kernel_python_root = _kernel_root / "python"
23+
_attn_qat_infer: Callable[..., torch.Tensor] | None = None
24+
_attn_qat_infer_import_attempted = False
25+
26+
27+
def _ensure_kernel_paths() -> None:
28+
for path in (_project_root, _kernel_root, _kernel_python_root):
29+
path_str = str(path)
30+
if path_str not in sys.path:
31+
sys.path.insert(0, path_str)
32+
33+
34+
def _get_attn_qat_infer() -> Callable[..., torch.Tensor] | None:
35+
global _attn_qat_infer
36+
global _attn_qat_infer_import_attempted
37+
38+
if _attn_qat_infer_import_attempted:
39+
return _attn_qat_infer
40+
41+
_attn_qat_infer_import_attempted = True
42+
_ensure_kernel_paths()
43+
44+
try:
45+
# Prefer the in-repo kernel implementation during local development.
46+
_attn_qat_infer = importlib.import_module("attn_qat_infer").sageattn_blackwell
47+
except ImportError:
48+
_attn_qat_infer = None
49+
50+
return _attn_qat_infer
51+
52+
53+
def is_attn_qat_infer_available() -> bool:
54+
return _get_attn_qat_infer() is not None
55+
56+
57+
class AttnQatInferBackend(AttentionBackend):
58+
59+
accept_output_buffer: bool = True
60+
61+
@staticmethod
62+
def get_supported_head_sizes() -> list[int]:
63+
return [64, 128]
64+
65+
@staticmethod
66+
def get_name() -> str:
67+
return "ATTN_QAT_INFER"
68+
69+
@staticmethod
70+
def get_impl_cls() -> type["AttnQatInferImpl"]:
71+
return AttnQatInferImpl
72+
73+
@staticmethod
74+
def get_metadata_cls() -> type["AttentionMetadata"]:
75+
raise NotImplementedError
76+
77+
@staticmethod
78+
def get_builder_cls() -> type["AttentionMetadataBuilder[AttentionMetadata]"]:
79+
raise NotImplementedError
80+
81+
82+
class AttnQatInferImpl(AttentionImpl[AttentionMetadata]):
83+
84+
def __init__(
85+
self,
86+
num_heads: int,
87+
head_size: int,
88+
causal: bool,
89+
softmax_scale: float,
90+
num_kv_heads: int | None = None,
91+
prefix: str = "",
92+
**extra_impl_args,
93+
) -> None:
94+
self.causal = causal
95+
self.softmax_scale = softmax_scale
96+
dropout_p = extra_impl_args.get("dropout_p", 0.0)
97+
if dropout_p > 0:
98+
raise NotImplementedError(f"attn_qat_infer does not support dropout (got dropout_p={dropout_p}). "
99+
"The QAT inference kernel applies no stochastic dropout.")
100+
101+
def forward(
102+
self,
103+
query: torch.Tensor,
104+
key: torch.Tensor,
105+
value: torch.Tensor,
106+
attn_metadata: AttentionMetadata,
107+
) -> torch.Tensor:
108+
attn_qat_infer = _get_attn_qat_infer()
109+
if attn_qat_infer is None:
110+
raise ImportError("attn_qat_infer is not available. Please ensure the "
111+
"attn_qat_infer kernel package is installed.")
112+
113+
query = query.transpose(1, 2).contiguous()
114+
key = key.transpose(1, 2).contiguous()
115+
value = value.transpose(1, 2).contiguous()
116+
117+
output = attn_qat_infer(
118+
query,
119+
key,
120+
value,
121+
attn_mask=None,
122+
is_causal=self.causal,
123+
sm_scale=self.softmax_scale,
124+
)
125+
return output.transpose(1, 2).contiguous()
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
import importlib
4+
import sys
5+
from collections.abc import Callable
6+
from pathlib import Path
7+
8+
import torch
9+
10+
from fastvideo.attention.backends.abstract import (
11+
AttentionBackend,
12+
AttentionImpl,
13+
AttentionMetadata,
14+
AttentionMetadataBuilder,
15+
)
16+
from fastvideo.logger import init_logger
17+
18+
logger = init_logger(__name__)
19+
20+
_project_root = Path(__file__).resolve().parent.parent.parent.parent
21+
_kernel_root = _project_root / "fastvideo-kernel"
22+
_kernel_python_root = _kernel_root / "python"
23+
_attn_qat_train_attention: Callable[..., torch.Tensor] | None = None
24+
_attn_qat_train_import_attempted = False
25+
26+
27+
def _ensure_kernel_paths() -> None:
28+
for path in (_project_root, _kernel_root, _kernel_python_root):
29+
path_str = str(path)
30+
if path_str not in sys.path:
31+
sys.path.insert(0, path_str)
32+
33+
34+
def _get_attn_qat_train_attention() -> Callable[..., torch.Tensor] | None:
35+
global _attn_qat_train_attention
36+
global _attn_qat_train_import_attempted
37+
38+
if _attn_qat_train_import_attempted:
39+
return _attn_qat_train_attention
40+
41+
_attn_qat_train_import_attempted = True
42+
_ensure_kernel_paths()
43+
44+
try:
45+
_attn_qat_train_attention = importlib.import_module("fastvideo_kernel.triton_kernels.attn_qat_train").attention
46+
except ImportError:
47+
_attn_qat_train_attention = None
48+
49+
return _attn_qat_train_attention
50+
51+
52+
def attn_qat_train(q_BLHD: torch.Tensor,
53+
k_BLHD: torch.Tensor,
54+
v_BLHD: torch.Tensor,
55+
is_causal: bool = False,
56+
sm_scale: float | None = None) -> torch.Tensor:
57+
attention = _get_attn_qat_train_attention()
58+
if attention is None:
59+
raise ImportError("fastvideo_kernel.triton_kernels.attn_qat_train is not available. "
60+
"Please ensure the FastVideo kernel package is installed.")
61+
62+
q_BHLD = q_BLHD.permute(0, 2, 1, 3).contiguous()
63+
k_BHLD = k_BLHD.permute(0, 2, 1, 3).contiguous()
64+
v_BHLD = v_BLHD.permute(0, 2, 1, 3).contiguous()
65+
66+
use_qat_qkv_backward = True
67+
smooth_k = False
68+
warp_specialize = True
69+
is_qat = True
70+
two_level_quant_p_sage3 = False
71+
fake_quant_p_bwd = True
72+
use_high_prec_o = True
73+
smooth_q = False
74+
if sm_scale is None:
75+
sm_scale = 1.0 / (q_BHLD.shape[-1]**0.5)
76+
use_global_sf_qkv = False
77+
use_global_sf_p = False
78+
79+
o_BHLD = attention(
80+
q_BHLD,
81+
k_BHLD,
82+
v_BHLD,
83+
is_causal,
84+
sm_scale,
85+
use_qat_qkv_backward,
86+
smooth_k,
87+
warp_specialize,
88+
is_qat,
89+
two_level_quant_p_sage3,
90+
fake_quant_p_bwd,
91+
use_high_prec_o,
92+
smooth_q,
93+
use_global_sf_p,
94+
use_global_sf_qkv,
95+
)
96+
return o_BHLD.permute(0, 2, 1, 3).contiguous()
97+
98+
99+
class AttnQatTrainBackend(AttentionBackend):
100+
101+
accept_output_buffer: bool = True
102+
103+
@staticmethod
104+
def get_supported_head_sizes() -> list[int]:
105+
return [64, 96, 128, 160, 192, 224, 256]
106+
107+
@staticmethod
108+
def get_name() -> str:
109+
return "ATTN_QAT_TRAIN"
110+
111+
@staticmethod
112+
def get_impl_cls() -> type["AttnQatTrainImpl"]:
113+
return AttnQatTrainImpl
114+
115+
@staticmethod
116+
def get_metadata_cls() -> type["AttentionMetadata"]:
117+
raise NotImplementedError
118+
119+
@staticmethod
120+
def get_builder_cls() -> type["AttentionMetadataBuilder[AttentionMetadata]"]:
121+
raise NotImplementedError
122+
123+
124+
class AttnQatTrainImpl(AttentionImpl[AttentionMetadata]):
125+
126+
def __init__(
127+
self,
128+
num_heads: int,
129+
head_size: int,
130+
causal: bool,
131+
softmax_scale: float,
132+
num_kv_heads: int | None = None,
133+
prefix: str = "",
134+
**extra_impl_args,
135+
) -> None:
136+
self.causal = causal
137+
self.softmax_scale = softmax_scale
138+
dropout_p = extra_impl_args.get("dropout_p", 0.0)
139+
if dropout_p > 0:
140+
raise NotImplementedError(f"attn_qat_train does not support dropout (got dropout_p={dropout_p}). "
141+
"The QAT training kernel applies no stochastic dropout.")
142+
143+
def forward(
144+
self,
145+
query: torch.Tensor,
146+
key: torch.Tensor,
147+
value: torch.Tensor,
148+
attn_metadata: AttentionMetadata,
149+
) -> torch.Tensor:
150+
return attn_qat_train(query, key, value, is_causal=self.causal, sm_scale=self.softmax_scale)

0 commit comments

Comments
 (0)