-
Notifications
You must be signed in to change notification settings - Fork 1.2k
[Feat] Single Batch Overlap (SBO): Overlaping of Down GEMM with Combine Send #183
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 65 commits
9ac3853
79b5a45
6cf6ca1
1e2c135
a5d23b0
48c741a
9a2d3e5
03f61d2
e86f1f9
e7ebff1
8037369
55c7943
99cc43b
4bfed47
4a14a40
701751c
8035121
02edd31
0fcd03c
2ec7414
a63152f
92b29f6
be21bf6
ffa1140
4802c62
6271138
57bb435
d6e63a3
a21c96f
51740cf
656fe10
7e385a9
8a138ad
2dfdce5
21da45d
cd062ad
387f068
aa81d53
e252aaa
1d0a364
8c2e6b8
3517989
a086212
e6c6977
7af0f7a
2c9fa44
96cdc90
11eeed6
debb196
7ee0480
0c0eac8
af77de9
23be492
84526c5
f858cad
ee1a058
ec8b7c1
ad8874a
59dc1aa
5edbbc5
bf0d62a
b78061b
848952b
bbc09d6
4011a8a
b9f37f2
07aa61c
379a913
9f769b4
eb1091f
ede008b
d232a36
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -115,4 +115,4 @@ class LaunchRuntime { | |
| } | ||
| }; | ||
|
|
||
| } // namespace deep_gemm | ||
| } // namespace deep_gemm | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,9 +36,9 @@ template <uint32_t SHAPE_M, uint32_t SHAPE_N, uint32_t SHAPE_K, | |
| uint32_t kNumStages, uint32_t kNumLastStages, | ||
| uint32_t kNumTMAThreads, uint32_t kNumMathThreads, | ||
| uint32_t kNumTMAMulticast, bool kIsTMAMulticastOnA, | ||
| uint32_t kNumSMs, GemmType kGemmType> | ||
| uint32_t kNumSMs, GemmType kGemmType, bool kEnableOverlap> | ||
| __global__ __launch_bounds__(kNumTMAThreads + kNumMathThreads, 1) void | ||
| sm90_fp8_gemm_1d2d_impl(float* sfb, int* grouped_layout, | ||
| sm90_fp8_gemm_1d2d_impl(float* sfb, int* grouped_layout, int* signal, | ||
| uint32_t shape_m, uint32_t shape_n, uint32_t shape_k, | ||
| const __grid_constant__ cute::TmaDescriptor tensor_map_a, | ||
| const __grid_constant__ cute::TmaDescriptor tensor_map_b, | ||
|
|
@@ -428,6 +428,19 @@ sm90_fp8_gemm_1d2d_impl(float* sfb, int* grouped_layout, | |
| cute::tma_store_arrive(); | ||
| } | ||
| __syncwarp(); | ||
|
|
||
| if constexpr (kEnableOverlap) { | ||
| if (threadIdx.x < BLOCK_N / TMA_D_BLOCK_N) { | ||
| cute::tma_store_wait<0>(); | ||
| } | ||
|
|
||
| cutlass::arch::NamedBarrier(kNumMathThreads).sync(); | ||
| __threadfence(); | ||
|
|
||
| if (threadIdx.x == 0) { | ||
| atomicAdd(signal + scheduler.current_group_idx * ceil_div(shape_m, BLOCK_M) + m_block_idx, 1); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. btw I am still a bit worried about this atomicAdd... (the code location issue in sgl-project/sglang#9660 (comment) is already solved and no problem) EDIT: oh I see the
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I will conduct further research and testing on these suggestions.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried using
Testing m-grouped masked GEMM:
Warning: please use at least NVCC 12.9 for the best DeepGEMM performance
> Perf (num_groups=1, expected_m_per_group=1024, n=4096, k=7168, 1D2D, enable_overlap=False): 347 us | 216 TFLOPS | 142 GB/s
> Perf (num_groups=1, expected_m_per_group=1024, n=7168, k=2048, 1D2D, enable_overlap=False): 159 us | 215 TFLOPS | 213 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=4096, k=7168, 1D2D, enable_overlap=False): 348 us | 178 TFLOPS | 216 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=7168, k=2048, 1D2D, enable_overlap=False): 159 us | 191 TFLOPS | 291 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=4096, k=7168, 1D2D, enable_overlap=False): 348 us | 174 TFLOPS | 384 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=7168, k=2048, 1D2D, enable_overlap=False): 217 us | 146 TFLOPS | 353 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=4096, k=7168, 1D2D, enable_overlap=False): 405 us | 153 TFLOPS | 1201 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=7168, k=2048, 1D2D, enable_overlap=False): 172 us | 164 TFLOPS | 1455 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=4096, k=7168, 1D2D, enable_overlap=False): 256 us | 118 TFLOPS | 1865 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=7168, k=2048, 1D2D, enable_overlap=False): 127 us | 115 TFLOPS | 1911 GB/s
> Perf (num_groups=1, expected_m_per_group=1024, n=4096, k=7168, 1D2D, enable_overlap=True): 351 us | 194 TFLOPS | 135 GB/s
> Perf (num_groups=1, expected_m_per_group=1024, n=7168, k=2048, 1D2D, enable_overlap=True): 124 us | 174 TFLOPS | 216 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=4096, k=7168, 1D2D, enable_overlap=True): 351 us | 179 TFLOPS | 215 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=7168, k=2048, 1D2D, enable_overlap=True): 165 us | 183 TFLOPS | 281 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=4096, k=7168, 1D2D, enable_overlap=True): 351 us | 165 TFLOPS | 378 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=7168, k=2048, 1D2D, enable_overlap=True): 165 us | 159 TFLOPS | 444 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=4096, k=7168, 1D2D, enable_overlap=True): 362 us | 159 TFLOPS | 1342 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=7168, k=2048, 1D2D, enable_overlap=True): 215 us | 148 TFLOPS | 1177 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=4096, k=7168, 1D2D, enable_overlap=True): 261 us | 109 TFLOPS | 1829 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=7168, k=2048, 1D2D, enable_overlap=True): 135 us | 108 TFLOPS | 1798 GB/s
Testing m-grouped masked GEMM:
Warning: please use at least NVCC 12.9 for the best DeepGEMM performance
> Perf (num_groups=1, expected_m_per_group=1024, n=4096, k=7168, 1D2D, enable_overlap=False): 347 us | 216 TFLOPS | 142 GB/s
> Perf (num_groups=1, expected_m_per_group=1024, n=7168, k=2048, 1D2D, enable_overlap=False): 159 us | 215 TFLOPS | 213 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=4096, k=7168, 1D2D, enable_overlap=False): 348 us | 178 TFLOPS | 216 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=7168, k=2048, 1D2D, enable_overlap=False): 159 us | 191 TFLOPS | 291 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=4096, k=7168, 1D2D, enable_overlap=False): 348 us | 174 TFLOPS | 384 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=7168, k=2048, 1D2D, enable_overlap=False): 217 us | 146 TFLOPS | 353 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=4096, k=7168, 1D2D, enable_overlap=False): 405 us | 153 TFLOPS | 1202 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=7168, k=2048, 1D2D, enable_overlap=False): 172 us | 164 TFLOPS | 1456 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=4096, k=7168, 1D2D, enable_overlap=False): 256 us | 118 TFLOPS | 1866 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=7168, k=2048, 1D2D, enable_overlap=False): 127 us | 115 TFLOPS | 1909 GB/s
> Perf (num_groups=1, expected_m_per_group=1024, n=4096, k=7168, 1D2D, enable_overlap=True): 350 us | 195 TFLOPS | 136 GB/s
> Perf (num_groups=1, expected_m_per_group=1024, n=7168, k=2048, 1D2D, enable_overlap=True): 123 us | 175 TFLOPS | 217 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=4096, k=7168, 1D2D, enable_overlap=True): 349 us | 180 TFLOPS | 216 GB/s
> Perf (num_groups=2, expected_m_per_group= 512, n=7168, k=2048, 1D2D, enable_overlap=True): 163 us | 184 TFLOPS | 283 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=4096, k=7168, 1D2D, enable_overlap=True): 350 us | 165 TFLOPS | 379 GB/s
> Perf (num_groups=4, expected_m_per_group= 256, n=7168, k=2048, 1D2D, enable_overlap=True): 164 us | 160 TFLOPS | 448 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=4096, k=7168, 1D2D, enable_overlap=True): 359 us | 160 TFLOPS | 1351 GB/s
> Perf (num_groups=16, expected_m_per_group= 64, n=7168, k=2048, 1D2D, enable_overlap=True): 209 us | 152 TFLOPS | 1207 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=4096, k=7168, 1D2D, enable_overlap=True): 259 us | 110 TFLOPS | 1844 GB/s
> Perf (num_groups=16, expected_m_per_group= 32, n=7168, k=2048, 1D2D, enable_overlap=True): 132 us | 111 TFLOPS | 1846 GB/sHowever, after some research, I concluded that release semantics ensure that all memory writes initiated by the same thread executing the atomic instruction before the atomic instruction are visible to other threads that subsequently observe the results of the atomic operation through an acquire operation. In other words, the guarantee of release semantics is bound to the thread executing the atomic operation. However, the thread initiating the TMA operation and the thread executing the write signal are not necessarily the same, so I'm concerned that this may cause problems.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My naive understanding is the following (please correct me if I am wrong!):
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we may apply cuda::atomic_ref and fetch_add instead of atomicAdd @Sulfur6 |
||
| } | ||
| } | ||
| } | ||
| } | ||
| #else | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,20 @@ | ||
| import torch | ||
| from typing import Iterable | ||
|
|
||
| def check_signal(num_local_expert, max_m, block_m, threshold, signal, masked_m): | ||
| ceil_div = lambda a, b: (a + b - 1) // b | ||
|
|
||
| expert_len = max_m // block_m | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| for expert in range(num_local_expert): | ||
| mask = masked_m[expert] | ||
| start = expert * expert_len | ||
| end = expert * expert_len + expert_len | ||
| valid_len = ceil_div(mask, block_m) | ||
| for i in range(start, end): | ||
| if i < start + valid_len: | ||
| assert signal[i] == threshold, f'{i=}, {signal[i]=}, {threshold=}' | ||
| else: | ||
| assert signal[i] == 0, f'{i=}, {signal[i]=}' | ||
|
|
||
| def calc_diff(x: torch.Tensor, y: torch.Tensor): | ||
| x, y = x.double(), y.double() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
one more naive worry:
tma_store_waitseems to correspond tocp.async.bulk.wait_group.read(src: https://github.com/NVIDIA/cutlass/blob/76c96b0be35cb263debe3e3d8418b80911a544ab/include/cute/arch/copy_sm90_tma.hpp#L1251), but it seems that we needcp.async.bulk.wait_group(no ".read"), otherwise the semantics (https://docs.nvidia.com/cuda/parallel-thread-execution/#data-movement-and-conversion-instructions-cp-async-bulk-wait-group) is that, "the tma store has done reading from source, but theWrites being made visible to the executing threadmay not have been done".There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you are right. we may apply "asm volatile("cp.async.bulk.wait_group 0;\n" ::: "memory")" instead of tma_store_wait here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looking forward to the fix