Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 36d5333

Browse files
ckl117ckl117yuanlehome
authored
[LLM INFER] cutlass 3.x gemm on sm90 (PaddlePaddle#9398)
* cutlass 3.x gemm on sm90 * change cutlass to v3.5.1, because v3.5.0 don't support fp8 gemm on hopper * support tune cutlass 3.x FP8 GEMM * auto gen cutlass 3.x FP8 GEMM code * add FP8 docs * change FP8 tune, and remove -O3 * check * check * support dual gemm on sm90 * code check * dual gemm cutlass kernel * code check * code check * setup_cuda.py check * delete invalid gemm config * change gitignore * Update csrc/setup_cuda.py Co-authored-by: Yuanle Liu <[email protected]> --------- Co-authored-by: ckl117 <[email protected]> Co-authored-by: Yuanle Liu <[email protected]>
1 parent d007615 commit 36d5333

26 files changed

Lines changed: 4546 additions & 87 deletions

โ€Ž.gitignoreโ€Ž

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,6 @@ output/
132132

133133
# gen codes
134134
autogen/
135+
136+
# cutlass kernel
137+
!csrc/gpu/cutlass_kernels/gemm/collective/builders

โ€Žcsrc/README.mdโ€Ž

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,11 @@ pip install -r requirements.txt
1414
python setup_cuda.py install
1515
```
1616

17-
## ็”Ÿๆˆ FP8็š„ cutlass ็ฎ—ๅญ
18-
```shell
19-
python utils/auto_gen_fp8_fp8_gemm_fused_kernels.py
20-
21-
python utils/auto_gen_fp8_fp8_dual_gemm_fused_kernels.py
22-
```
23-
2417
### FP8 GEMM ่‡ชๅŠจ่ฐƒไผ˜
18+
19+
็กฎไฟ `cutlass` ๅบ“ๅทฒ็ปๅฎ‰่ฃ…๏ผŒ็„ถๅŽๆ‰ง่กŒไปฅไธ‹ๅ‘ฝไปค่ฟ›่กŒ่‡ชๅŠจ่ฐƒไผ˜ใ€‚
20+
- ๅฏนไบŽ89ๆžถๆž„็š„ GPU๏ผŒCUDA ็‰ˆๆœฌ่‡ณๅฐ‘ไธบ12.4
21+
- ๅฏนไบŽ90ๆžถๆž„็š„ GPU๏ผŒCUDA ็‰ˆๆœฌ่‡ณๅฐ‘ไธบ12.0
2522
```shell
2623
sh tune_fp8_gemm.sh
2724
```

โ€Žcsrc/gpu/cutlass_kernels/fp8_gemm_fused/fp8_fp8_dual_gemm_scale_bias_act.hโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
#include "fp8_common.h"
1818
#include "fuse_dual_gemm_swiglu_template.h"
1919
#include "fuse_dual_gemm_geglu_template.h"
20+
#include "fuse_dual_gemm_act_template_3x.h"
2021

2122
bool fp8_fp8_dual_gemm_scale_bias_act(
2223
DualGemmEpilogueAllParams params);
23-

โ€Žcsrc/gpu/cutlass_kernels/fp8_gemm_fused/fp8_fp8_gemm_scale_bias_act.hโ€Ž

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,6 @@
1919
#include "fuse_gemm_relu_template.h"
2020
#include "fuse_gemm_gelu_template.h"
2121

22-
bool fp8_fp8_gemm_scale_bias_act(GemmEpilogueAllParams params);
22+
#include "fuse_gemm_act_template_3x.h"
2323

24+
bool fp8_fp8_gemm_scale_bias_act(GemmEpilogueAllParams params);
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#pragma once
15+
16+
#include "fp8_common.h"
17+
#include "cutlass/cutlass.h"
18+
#include "cutlass/float8.h"
19+
#include "cutlass/gemm/device/gemm_universal.h"
20+
21+
#include "cutlass/util/packed_stride.hpp"
22+
#include "cutlass/gemm/dispatch_policy.hpp"
23+
#include "cutlass/gemm/collective/collective_builder.hpp"
24+
#include "cutlass/epilogue/collective/collective_builder.hpp"
25+
#include "cutlass/gemm/device/gemm_universal_adapter.h"
26+
#include "cutlass/gemm/kernel/gemm_universal.hpp"
27+
#include "cutlass/gemm/kernel/tile_scheduler.hpp"
28+
#include "cutlass_kernels/gemm/collective/collective_builder_gated.hpp"
29+
#include "cutlass_kernels/gemm/kernel/gemm_universal_gated.hpp"
30+
31+
using namespace cute;
32+
33+
template <typename InputType, typename CTAShape, typename ClusterShape,
34+
typename MainloopScheduleType, typename EpilogueScheduleType, typename TileSchedulerType = void,
35+
template <class /* ElementCompute */> class Activation = cutlass::epilogue::thread::SiLu, bool SwapAB = true>
36+
bool dispatch_dual_gemm_act_sm90(DualGemmEpilogueAllParams params) {
37+
using ElementA = typename std::conditional_t<
38+
std::is_same_v<InputType, phi::dtype::float8_e4m3fn>,
39+
cutlass::float_e4m3_t,
40+
cutlass::float_e5m2_t>;
41+
using LayoutA = cutlass::layout::RowMajor; // Layout type for A matrix operand
42+
static constexpr int AlignmentA
43+
= 128 / cutlass::sizeof_bits<ElementA>::value; // Memory access granularity/alignment of A
44+
// matrix in units of elements (up to 16 bytes)
45+
46+
// B matrix configuration
47+
using ElementB = ElementA; // Element type for B matrix operand
48+
using LayoutB = cutlass::layout::ColumnMajor; // Layout type for B matrix operand
49+
static constexpr int AlignmentB
50+
= 128 / cutlass::sizeof_bits<ElementB>::value; // Memory access granularity/alignment of B
51+
// matrix in units of elements (up to 16 bytes)
52+
53+
using ElementC = ElementA; // Element type for C matrix operands
54+
55+
using LayoutC = cute::conditional_t<SwapAB, cutlass::layout::ColumnMajor, cutlass::layout::RowMajor>;
56+
static constexpr int AlignmentC
57+
= 128 / cutlass::sizeof_bits<ElementC>::value; // Memory access granularity/alignment of C matrices in units of
58+
// elements (up to 16 bytes)
59+
60+
// Output matrix configuration
61+
using ElementOutput = ElementA; // Element type for output matrix operands
62+
// using LayoutOutput = cutlass::layout::RowMajor; // Layout type for output matrix operands
63+
using LayoutOutput = cute::conditional_t<SwapAB, cutlass::layout::ColumnMajor, cutlass::layout::RowMajor>;
64+
static constexpr int AlignmentOutput = 128 / cutlass::sizeof_bits<ElementOutput>::value;
65+
66+
// Multiply-accumulate blocking/pipelining details
67+
using ElementAccumulator = float; // Element type for internal accumulation
68+
using ElementCompute = float; // Element type for compute
69+
using ArchTag = cutlass::arch::Sm90; // Tag indicating the minimum SM that supports the intended feature
70+
using OperatorClass = cutlass::arch::OpClassTensorOp; // Operator class tag
71+
using TileShape = CTAShape; // Threadblock-level tile size
72+
using KernelSchedule = MainloopScheduleType;
73+
using EpilogueSchedule = EpilogueScheduleType;
74+
using TileScheduler = TileSchedulerType;
75+
76+
using EpilogueTileType = cutlass::epilogue::collective::EpilogueTileAuto;
77+
78+
static constexpr auto RoundStyle = cutlass::FloatRoundStyle::round_to_nearest;
79+
using FusionOperation = cutlass::epilogue::fusion::ScaledAcc<ElementOutput, ElementCompute>;
80+
81+
using CollectiveEpilogue = typename cutlass::epilogue::collective::CollectiveBuilder<ArchTag, OperatorClass,
82+
TileShape, ClusterShape, EpilogueTileType, ElementAccumulator, ElementAccumulator, ElementC, LayoutC,
83+
AlignmentC, ElementOutput, LayoutOutput, AlignmentOutput, EpilogueSchedule, FusionOperation>::CollectiveOp;
84+
85+
using CollectiveMainloop = typename cutlass::gemm::collective::CollectiveBuilderGated<ArchTag, OperatorClass,
86+
ElementA, LayoutA, AlignmentA, ElementB, LayoutB, AlignmentB, ElementAccumulator, TileShape, ClusterShape,
87+
cutlass::gemm::collective::StageCountAutoCarveout<static_cast<int>(
88+
sizeof(typename CollectiveEpilogue::SharedStorage))>,
89+
KernelSchedule, Activation, SwapAB>::CollectiveOp;
90+
91+
using GemmKernel = cutlass::gemm::kernel::GemmUniversalGated<Shape<int, int, int, int>, // Indicates ProblemShape
92+
CollectiveMainloop, CollectiveEpilogue, TileScheduler>;
93+
94+
using Gemm = cutlass::gemm::device::GemmUniversalAdapter<GemmKernel>;
95+
96+
using StrideA = typename Gemm::GemmKernel::StrideA;
97+
using StrideB = typename Gemm::GemmKernel::StrideB;
98+
using StrideC = typename Gemm::GemmKernel::StrideC;
99+
using StrideD = typename Gemm::GemmKernel::StrideD;
100+
101+
int arg_m = params.M;
102+
int arg_n = params.N;
103+
ElementA const* ptr_A = reinterpret_cast<ElementA const*>(params.A);
104+
ElementB const* ptr_B0 = reinterpret_cast<ElementB const*>(params.B0);
105+
ElementB const* ptr_B1 = reinterpret_cast<ElementB const*>(params.B1);
106+
if constexpr (SwapAB)
107+
{
108+
arg_m = params.N;
109+
arg_n = params.M;
110+
ptr_A = reinterpret_cast<ElementB const*>(params.B0);
111+
ptr_B0 = reinterpret_cast<ElementA const*>(params.A);
112+
}
113+
StrideA stride_A = cutlass::make_cute_packed_stride(StrideA{}, cute::make_shape(arg_m, params.K, 1));
114+
StrideB stride_B = cutlass::make_cute_packed_stride(StrideB{}, cute::make_shape(arg_n, params.K, 1));
115+
StrideC stride_C;
116+
StrideD stride_D = cutlass::make_cute_packed_stride(StrideD{}, cute::make_shape(arg_m, arg_n, 1));
117+
118+
typename Gemm::Arguments arguments = {cutlass::gemm::GemmUniversalMode::kGemm, {arg_m, arg_n, params.K, 1},
119+
{ptr_A, stride_A, ptr_B0, ptr_B1, stride_B, params.scale0, params.scale1},
120+
{{}, // epilogue.thread
121+
nullptr, stride_C, reinterpret_cast<ElementOutput*>(params.D), stride_D}};
122+
arguments.epilogue.thread.alpha = params.scale_out;
123+
124+
Gemm gemm_op;
125+
126+
cutlass::Status status = gemm_op.can_implement(arguments);
127+
128+
if (status != cutlass::Status::kSuccess) {
129+
std::cerr << "Gemm::can_implement() failed" << std::endl;
130+
return false;
131+
}
132+
133+
size_t workspace_size = Gemm::get_workspace_size(arguments);
134+
phi::Allocator* allocator = paddle::GetAllocator(params.place);
135+
auto workspace = allocator->Allocate(workspace_size);
136+
137+
//
138+
// Run the GEMM
139+
//
140+
status = gemm_op(arguments, workspace->ptr(), params.stream);
141+
if (status != cutlass::Status::kSuccess) {
142+
std::cerr << "Gemm::run() failed" << std::endl;
143+
return false;
144+
}
145+
return true;
146+
}
147+
Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// Copyright (c) 2024 PaddlePaddle Authors. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
#pragma once
15+
16+
#include "fp8_common.h"
17+
18+
#include "cutlass/cutlass.h"
19+
#include "cutlass/epilogue/collective/default_epilogue.hpp"
20+
#include "cutlass/epilogue/thread/linear_combination.h"
21+
#include "cutlass/gemm/dispatch_policy.hpp"
22+
#include "cutlass/gemm/collective/collective_builder.hpp"
23+
#include "cutlass/epilogue/collective/collective_builder.hpp"
24+
#include "cutlass/gemm/device/gemm_universal_adapter.h"
25+
#include "cutlass/gemm/kernel/gemm_universal.hpp"
26+
#include "cutlass/gemm/kernel/tile_scheduler.hpp"
27+
#include "cutlass/util/packed_stride.hpp"
28+
29+
using namespace cute;
30+
31+
template <
32+
typename InputType = phi::dtype::float8_e4m3fn,
33+
typename OutType = phi::dtype::float16,
34+
bool hasbias = false,
35+
template <class> typename Activation = cutlass::epilogue::thread::Identity,
36+
typename TileShape = Shape<_128, _128, _128>,
37+
typename ClusterShape = Shape<_2, _1, _1>,
38+
typename KernelSchedule = cutlass::gemm::KernelTmaWarpSpecializedPingpongFP8FastAccum,
39+
typename EpilogueSchedule = cutlass::epilogue::TmaWarpSpecialized,
40+
typename SM = cutlass::arch::Sm90
41+
>
42+
bool dispatch_fuse_gemm_act_sm90(GemmEpilogueAllParams params){
43+
using ElementA = typename std::conditional_t<std::is_same_v<InputType, phi::dtype::float8_e4m3fn>,
44+
cutlass::float_e4m3_t,
45+
cutlass::float_e5m2_t>;
46+
using ElementB = ElementA;
47+
using ElementD = typename std::conditional_t<std::is_same_v<OutType, phi::dtype::bfloat16>,
48+
cutlass::bfloat16_t,
49+
cutlass::half_t>;
50+
using ElementC = std::conditional_t<
51+
hasbias,
52+
ElementD,
53+
void>;
54+
55+
using LayoutA = cutlass::layout::RowMajor;
56+
using LayoutB = cutlass::layout::ColumnMajor;
57+
using LayoutC = cutlass::layout::RowMajor;
58+
using LayoutD = cutlass::layout::RowMajor;
59+
60+
using ElementAccumulator = float;
61+
using ElementCompute = float;
62+
using ElementScalar = float;
63+
64+
// 16B alignment lets us use TMA
65+
static constexpr int AlignmentA = 16 / sizeof(ElementA);
66+
static constexpr int AlignmentB = 16 / sizeof(ElementB);
67+
static constexpr int AlignmentC = hasbias ? 16 / sizeof(ElementC) : 8;
68+
static constexpr int AlignmentD = 16 / sizeof(ElementD);
69+
70+
static constexpr auto RoundStyle = cutlass::FloatRoundStyle::round_to_nearest;
71+
72+
using FusionOperation = cutlass::epilogue::fusion::LinCombEltAct<Activation, ElementD, ElementCompute, ElementC, ElementScalar, RoundStyle>;
73+
74+
using CollectiveEpilogue = typename cutlass::epilogue::collective::CollectiveBuilder<
75+
SM, cutlass::arch::OpClassTensorOp,
76+
TileShape,
77+
ClusterShape,
78+
cutlass::epilogue::collective::EpilogueTileAuto,
79+
ElementAccumulator, ElementCompute,
80+
ElementC, LayoutC, AlignmentC,
81+
ElementD, LayoutD, AlignmentD,
82+
EpilogueSchedule,
83+
FusionOperation
84+
>::CollectiveOp;
85+
86+
using CollectiveMainloop = typename cutlass::gemm::collective::CollectiveBuilder<
87+
SM, cutlass::arch::OpClassTensorOp,
88+
ElementA, LayoutA, AlignmentA,
89+
ElementB, LayoutB, AlignmentB,
90+
ElementAccumulator,
91+
TileShape,
92+
ClusterShape,
93+
cutlass::gemm::collective::StageCountAutoCarveout<static_cast<int>(sizeof(typename CollectiveEpilogue::SharedStorage))>,
94+
KernelSchedule
95+
>::CollectiveOp;
96+
97+
using GemmKernel = cutlass::gemm::kernel::GemmUniversal<
98+
Shape<int,int,int,int>,
99+
CollectiveMainloop,
100+
CollectiveEpilogue,
101+
cutlass::gemm::PersistentScheduler
102+
>;
103+
104+
using Gemm = cutlass::gemm::device::GemmUniversalAdapter<GemmKernel>;
105+
106+
using ProblemShapeType = typename Gemm::GemmKernel::ProblemShape;
107+
108+
using StrideA = typename Gemm::GemmKernel::StrideA;
109+
using StrideB = typename Gemm::GemmKernel::StrideB;
110+
using StrideC = typename Gemm::GemmKernel::StrideC;
111+
using StrideD = typename Gemm::GemmKernel::StrideD;
112+
113+
//
114+
// Data members
115+
//
116+
117+
/// Initialization
118+
StrideA stride_A{params.lda, cute::Int<1>{}, 0};
119+
StrideB stride_B{params.ldb, cute::Int<1>{}, 0};
120+
StrideC stride_C{0, cute::Int<1>{}, 0};
121+
StrideD stride_D{params.ldd, cute::Int<1>{}, 0};
122+
123+
auto a_ptr = reinterpret_cast<ElementA*>(const_cast<void*>(params.A));
124+
auto b_ptr = reinterpret_cast<ElementB*>(const_cast<void*>(params.B));
125+
auto c_ptr = reinterpret_cast<ElementC*>(const_cast<void*>(params.bias));
126+
auto d_ptr = reinterpret_cast<ElementD*>(params.D);
127+
128+
ProblemShapeType problem_size = ProblemShapeType{params.M, params.N, params.K, 1};
129+
130+
typename Gemm::Arguments arguments{
131+
cutlass::gemm::GemmUniversalMode::kGemm,
132+
problem_size,
133+
{a_ptr, stride_A, b_ptr, stride_B},
134+
{{params.scale}, // epilogue.thread
135+
c_ptr, stride_C, d_ptr, stride_D}
136+
};
137+
if constexpr (hasbias){
138+
arguments.epilogue.thread.beta = 1.0;
139+
}
140+
141+
142+
Gemm gemm_op;
143+
144+
cutlass::Status status = gemm_op.can_implement(arguments);
145+
if (status != cutlass::Status::kSuccess) {
146+
std::cout << "Gemm::can_implement() failed. " << cutlassGetStatusString(status) << std::endl;
147+
return false;
148+
}
149+
size_t workspace_size = Gemm::get_workspace_size(arguments);
150+
phi::Allocator* allocator = paddle::GetAllocator(params.place);
151+
auto workspace = allocator->Allocate(workspace_size);
152+
153+
status = gemm_op(arguments, workspace->ptr(), params.stream);
154+
if (status != cutlass::Status::kSuccess) {
155+
std::cout << "Gemm::run() failed." << cutlassGetStatusString(status) << std::endl;
156+
return false;
157+
}
158+
return true;
159+
}

0 commit comments

Comments
ย (0)