liangsu9988 commited on
Commit
0569825
·
verified ·
1 Parent(s): d99b6d3

Uploaded using `kernel-builder`.

Browse files
benchmarks/benchmark.py CHANGED
@@ -10,11 +10,21 @@ from fa2_seqused_runtime import allocate_outputs, allocate_workspace, forward_st
10
 
11
 
12
  SHAPES = [
13
- (1, 1, 512, 8, 2, 128),
14
- (1, 16, 1024, 16, 4, 128),
15
- (1, 49, 2520, 24, 4, 128),
16
- (1, 64, 4096, 32, 8, 128),
17
- (1, 1024, 1024, 32, 8, 128),
 
 
 
 
 
 
 
 
 
 
18
  ]
19
 
20
 
@@ -39,8 +49,13 @@ def main():
39
  parser.add_argument("--dtype", choices=("bf16", "fp16"), default="bf16")
40
  args = parser.parse_args()
41
  dtype = torch.bfloat16 if args.dtype == "bf16" else torch.float16
42
- print("B,Sq,Sk,Hq,Hkv,D,FlashRT_us,SDPA_expandedGQA_us,Speedup")
43
- for batch, sq, sk, hq, hkv, dim in SHAPES:
 
 
 
 
 
44
  q = torch.randn(batch, sq, hq, dim, device="cuda", dtype=dtype)
45
  k = torch.randn(batch, sk, hkv, dim, device="cuda", dtype=dtype)
46
  v = torch.randn_like(k)
@@ -50,18 +65,40 @@ def main():
50
  vr = v.repeat_interleave(hq // hkv, dim=2)
51
 
52
  def flashrt():
53
- forward_static(q, k, v, out=out, softmax_lse=lse, workspace=workspace)
 
 
 
 
 
 
 
 
54
 
55
  def sdpa():
56
- F.scaled_dot_product_attention(
57
  q.permute(0, 2, 1, 3),
58
  kr.permute(0, 2, 1, 3),
59
  vr.permute(0, 2, 1, 3),
 
60
  )
61
 
62
  flashrt_us = time_us(flashrt)
63
  sdpa_us = time_us(sdpa)
64
- print(f"{batch},{sq},{sk},{hq},{hkv},{dim},{flashrt_us:.3f},{sdpa_us:.3f},{sdpa_us / flashrt_us:.3f}")
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
 
67
  if __name__ == "__main__":
 
10
 
11
 
12
  SHAPES = [
13
+ # GROOT DiT self/cross attention.
14
+ ("groot-dit-self", 1, 51, 51, 32, 32, 48, False),
15
+ ("groot-dit-cross", 1, 51, 1024, 32, 32, 48, False),
16
+ # GROOT N1.7 ViT/VL and SigLIP vision attention.
17
+ ("groot-n17-vit", 1, 256, 256, 16, 16, 64, False),
18
+ ("groot-siglip", 2, 256, 256, 16, 16, 72, False),
19
+ # Qwen2.5-VL/LingBot vision attention.
20
+ ("vl-vision", 1, 256, 256, 16, 16, 80, False),
21
+ # Generic runtime/GQA rows.
22
+ ("gqa-decode", 1, 1, 512, 8, 2, 128, False),
23
+ ("gqa-short", 1, 16, 1024, 16, 4, 128, False),
24
+ ("vla-gqa", 1, 49, 2520, 24, 4, 128, False),
25
+ ("gqa-long-kv", 1, 64, 4096, 32, 8, 128, False),
26
+ ("qwen-causal", 1, 1024, 1024, 32, 8, 128, True),
27
+ ("qwen36-causal", 1, 512, 512, 24, 4, 256, True),
28
  ]
29
 
30
 
 
49
  parser.add_argument("--dtype", choices=("bf16", "fp16"), default="bf16")
50
  args = parser.parse_args()
51
  dtype = torch.bfloat16 if args.dtype == "bf16" else torch.float16
52
+ print(
53
+ "Workload,Mode,B,Sq,Sk,Hq,Hkv,D,FlashRT_us,SDPA_expandedGQA_us,Speedup,"
54
+ "MaxAbs,P99Abs,MeanAbs,Cosine"
55
+ )
56
+ for name, batch, sq, sk, hq, hkv, dim, causal in SHAPES:
57
+ if causal and dtype == torch.float16:
58
+ continue
59
  q = torch.randn(batch, sq, hq, dim, device="cuda", dtype=dtype)
60
  k = torch.randn(batch, sk, hkv, dim, device="cuda", dtype=dtype)
61
  v = torch.randn_like(k)
 
65
  vr = v.repeat_interleave(hq // hkv, dim=2)
66
 
67
  def flashrt():
68
+ forward_static(
69
+ q,
70
+ k,
71
+ v,
72
+ out=out,
73
+ softmax_lse=lse,
74
+ workspace=workspace,
75
+ causal=causal,
76
+ )
77
 
78
  def sdpa():
79
+ return F.scaled_dot_product_attention(
80
  q.permute(0, 2, 1, 3),
81
  kr.permute(0, 2, 1, 3),
82
  vr.permute(0, 2, 1, 3),
83
+ is_causal=causal,
84
  )
85
 
86
  flashrt_us = time_us(flashrt)
87
  sdpa_us = time_us(sdpa)
88
+ actual = out.float()
89
+ reference = sdpa().permute(0, 2, 1, 3).float()
90
+ error = (actual - reference).abs()
91
+ cosine = torch.nn.functional.cosine_similarity(
92
+ actual.flatten(), reference.flatten(), dim=0
93
+ ).item()
94
+ print(
95
+ f"{name},{'causal' if causal else 'noncausal'},"
96
+ f"{batch},{sq},{sk},{hq},{hkv},{dim},"
97
+ f"{flashrt_us:.3f},{sdpa_us:.3f},{sdpa_us / flashrt_us:.3f},"
98
+ f"{error.max().item():.9f},"
99
+ f"{torch.quantile(error, 0.99).item():.9f},"
100
+ f"{error.mean().item():.9f},{cosine:.10f}"
101
+ )
102
 
103
 
104
  if __name__ == "__main__":
build/torch211-cxx11-cu128-x86_64-linux/__init__.py CHANGED
@@ -11,8 +11,9 @@ import torch
11
  from ._ops import add_op_namespace_prefix, ops
12
 
13
 
14
- SUPPORTED_HEAD_DIMS = (64, 96, 128, 256)
15
- SPLIT_HEAD_DIMS = (96, 128, 256)
 
16
 
17
 
18
  @dataclass(frozen=True)
@@ -43,7 +44,7 @@ def recommended_num_splits(
43
  if any(int(v) <= 0 for v in values):
44
  raise ValueError("all shape values and num_sms must be positive")
45
  if int(head_dim) not in SUPPORTED_HEAD_DIMS:
46
- raise ValueError(f"head_dim must be one of {SUPPORTED_HEAD_DIMS}")
47
  block_n = 256 if head_dim <= 64 else (128 if head_dim <= 128 else 64)
48
  n_blocks = _ceildiv(seqlen_k, block_n)
49
  m_blocks = _ceildiv(seqlen_q, 64)
@@ -82,8 +83,8 @@ def allocate_workspace(
82
 
83
  if q.ndim != 4 or k.ndim != 4:
84
  raise ValueError("q and k must have shape (B, S, H, D)")
85
- if q.shape[-1] not in SPLIT_HEAD_DIMS:
86
- return None
87
  if num_sms is None:
88
  num_sms = torch.cuda.get_device_properties(q.device).multi_processor_count
89
  splits = recommended_num_splits(
@@ -96,8 +97,9 @@ def allocate_workspace(
96
  device=q.device,
97
  dtype=torch.float32,
98
  )
 
99
  out = torch.empty(
100
- (splits, q.shape[0], q.shape[2], q.shape[1], q.shape[3]),
101
  device=q.device,
102
  dtype=torch.float32,
103
  )
@@ -273,6 +275,7 @@ def forward(
273
 
274
  __all__ = [
275
  "FA2Workspace",
 
276
  "SPLIT_HEAD_DIMS",
277
  "SUPPORTED_HEAD_DIMS",
278
  "allocate_outputs",
 
11
  from ._ops import add_op_namespace_prefix, ops
12
 
13
 
14
+ SUPPORTED_HEAD_DIMS = tuple(range(8, 257, 8))
15
+ COMPILED_HEAD_DIM_BUCKETS = (64, 96, 128, 256)
16
+ SPLIT_HEAD_DIMS = SUPPORTED_HEAD_DIMS
17
 
18
 
19
  @dataclass(frozen=True)
 
44
  if any(int(v) <= 0 for v in values):
45
  raise ValueError("all shape values and num_sms must be positive")
46
  if int(head_dim) not in SUPPORTED_HEAD_DIMS:
47
+ raise ValueError("head_dim must be a positive multiple of 8 at most 256")
48
  block_n = 256 if head_dim <= 64 else (128 if head_dim <= 128 else 64)
49
  n_blocks = _ceildiv(seqlen_k, block_n)
50
  m_blocks = _ceildiv(seqlen_q, 64)
 
83
 
84
  if q.ndim != 4 or k.ndim != 4:
85
  raise ValueError("q and k must have shape (B, S, H, D)")
86
+ if q.shape[-1] not in SUPPORTED_HEAD_DIMS:
87
+ raise ValueError("head_dim must be a positive multiple of 8 at most 256")
88
  if num_sms is None:
89
  num_sms = torch.cuda.get_device_properties(q.device).multi_processor_count
90
  splits = recommended_num_splits(
 
97
  device=q.device,
98
  dtype=torch.float32,
99
  )
100
+ d_rounded = (q.shape[3] + 31) & ~31
101
  out = torch.empty(
102
+ (splits, q.shape[0], q.shape[2], q.shape[1], d_rounded),
103
  device=q.device,
104
  dtype=torch.float32,
105
  )
 
275
 
276
  __all__ = [
277
  "FA2Workspace",
278
+ "COMPILED_HEAD_DIM_BUCKETS",
279
  "SPLIT_HEAD_DIMS",
280
  "SUPPORTED_HEAD_DIMS",
281
  "allocate_outputs",
build/torch211-cxx11-cu128-x86_64-linux/{_fa2_seqused_runtime_cuda_61bef7e.abi3.so → _fa2_seqused_runtime_cuda_99d26a1.abi3.so} RENAMED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:aa60c53d1b376ba1f39d721b93dfb427f911b120e11d60a857205d1c346e2c58
3
- size 391476840
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:824df1266b7f0c7859f9132a97e3f034a9d8b1e434a340386d21a5b533986977
3
+ size 422846752
build/torch211-cxx11-cu128-x86_64-linux/_ops.py CHANGED
@@ -1,9 +1,9 @@
1
  import torch
2
- from . import _fa2_seqused_runtime_cuda_61bef7e
3
- ops = torch.ops._fa2_seqused_runtime_cuda_61bef7e
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
- return f"_fa2_seqused_runtime_cuda_61bef7e::{op_name}"
 
1
  import torch
2
+ from . import _fa2_seqused_runtime_cuda_99d26a1
3
+ ops = torch.ops._fa2_seqused_runtime_cuda_99d26a1
4
 
5
  def add_op_namespace_prefix(op_name: str):
6
  """
7
  Prefix op by namespace.
8
  """
9
+ return f"_fa2_seqused_runtime_cuda_99d26a1::{op_name}"
build/torch211-cxx11-cu128-x86_64-linux/metadata.json CHANGED
@@ -1,6 +1,6 @@
1
  {
2
  "name": "fa2-seqused-runtime",
3
- "id": "_fa2_seqused_runtime_cuda_61bef7e",
4
  "version": 1,
5
  "license": "BSD-3-Clause",
6
  "python-depends": [],
@@ -16,9 +16,9 @@
16
  "digest": {
17
  "algorithm": "sha256",
18
  "files": {
19
- "__init__.py": "ck4+/aHijqRRXtVYRzkkIj7bHwvMxxOEnRIKVQSkd6k=",
20
- "_fa2_seqused_runtime_cuda_61bef7e.abi3.so": "qmDFPRs3a6HznXIbk9+0J/kRsSDhHWCoVyBdHDRuLFg=",
21
- "_ops.py": "S5eXSORqSBWo6D7FltYgk8ttuDlbt6lSeHd0GmU8q6U=",
22
  "fa2_seqused_runtime/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
23
  }
24
  }
 
1
  {
2
  "name": "fa2-seqused-runtime",
3
+ "id": "_fa2_seqused_runtime_cuda_99d26a1",
4
  "version": 1,
5
  "license": "BSD-3-Clause",
6
  "python-depends": [],
 
16
  "digest": {
17
  "algorithm": "sha256",
18
  "files": {
19
+ "__init__.py": "zaIQDw3dhB5xbCQPrZ9tGWr/Z559+ooyZOaGIa2/+LQ=",
20
+ "_fa2_seqused_runtime_cuda_99d26a1.abi3.so": "gk3xJmt/DHhZ+RMql+PwNKnYseQ0o0A4bSGltTOYaXc=",
21
+ "_ops.py": "3zmyZsIXRYN9PWXNasLSKultcD9S0IaBbtFEFMbUth0=",
22
  "fa2_seqused_runtime/__init__.py": "DFYPlrhXwYjEqCl/8n0SmWGZV8NFml5DPhMjKfv98GY="
23
  }
24
  }