Skip to content

Commit 39cb816

Browse files
authored
Fix cat cpp wrapper kernel path, cat dtype mismatch, and rwkv_mm_sparsity precision (#5388)
1 parent f92b65d commit 39cb816

3 files changed

Lines changed: 91 additions & 62 deletions

File tree

cpp/ctests/test_triton_rwkv_mm_sparsity.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ TEST(rwkv_op_test, rwkv_mm_sparsity) {
2525
torch::Tensor k = torch::relu(torch::randn({n}, device));
2626
torch::Tensor v = torch::randn({n, d}, device);
2727

28-
torch::Tensor ref_k = flag_gems::accuracy_utils::to_reference(k, false);
29-
torch::Tensor ref_v = flag_gems::accuracy_utils::to_reference(v, false);
28+
torch::Tensor ref_k = flag_gems::accuracy_utils::to_reference(k, true);
29+
torch::Tensor ref_v = flag_gems::accuracy_utils::to_reference(v, true);
3030

3131
torch::Tensor k2d = ref_k.view({1, n});
3232
torch::Tensor out_triton = flag_gems::rwkv_mm_sparsity(k, v);

cpp/lib/cat.cpp

Lines changed: 81 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -112,67 +112,96 @@ at::Tensor cat(const at::TensorList& tensors, int64_t dim) {
112112
out_shape_vec[dim] = cat_dim_size;
113113
at::Tensor out = at::empty(out_shape_vec, ref_tensor->options().dtype(out_dtype));
114114

115-
std::vector<int64_t> storage_offsets;
116-
int64_t current_storage_offset = 0;
117-
storage_offsets.push_back(current_storage_offset);
118-
int64_t out_stride_for_dim = out.stride(dim);
119-
for (size_t i = 0; i < tensors.size() - 1; ++i) {
120-
current_storage_offset += cat_dim_size_of(tensors[i], dim) * out_stride_for_dim;
121-
storage_offsets.push_back(current_storage_offset);
115+
int64_t dim_prod_post = 1;
116+
for (int64_t d = dim + 1; d < ndim; ++d) {
117+
dim_prod_post *= out_shape_vec[d];
122118
}
119+
int64_t dim_size_out = out_shape_vec[dim];
123120

124-
const TritonJITFunction& copy_kernel_func =
125-
TritonJITFunction::get_instance(std::string(utils::get_triton_src_path() / "cat_copy.py"),
126-
"strided_copy_kernel");
121+
const TritonJITFunction& kernel =
122+
TritonJITFunction::get_instance(std::string(utils::get_flag_gems_src_path() / "ops" / "cat.py"),
123+
"cat_copy_func_kernel_4");
127124
c10::DeviceGuard guard(out.device());
128125
backend::StreamType stream = backend::getCurrentStream();
129126
backend::RawStreamType raw_stream = backend::getRawStream(stream);
130127

131-
for (size_t i = 0; i < tensors.size(); ++i) {
132-
const auto& input_tensor = tensors[i];
133-
if (input_tensor.numel() == 0) continue;
128+
constexpr int BLOCK = 1024;
129+
constexpr int NUM_WARPS = 4;
130+
constexpr int NUM_STAGES = 1;
131+
132+
int64_t dim_offset = 0;
133+
size_t ti = 0;
134+
while (ti < tensors.size()) {
135+
at::Tensor batch_tensors[4];
136+
int64_t dim_sizes[4] = {0, 0, 0, 0};
137+
int64_t dim_offsets[4] = {0, 0, 0, 0};
138+
int64_t total_elements[4] = {0, 0, 0, 0};
139+
int num_in_batch = 0;
140+
141+
while (ti < tensors.size() && num_in_batch < 4) {
142+
const auto& t = tensors[ti];
143+
int64_t dim_size = cat_dim_size_of(t, dim);
144+
145+
if (!is_unconstrained_empty(t) && t.numel() > 0) {
146+
at::Tensor src = t;
147+
if (src.scalar_type() != out_dtype) {
148+
src = src.to(out_dtype);
149+
}
150+
src = src.contiguous();
151+
batch_tensors[num_in_batch] = src;
152+
dim_sizes[num_in_batch] = dim_size;
153+
dim_offsets[num_in_batch] = dim_offset;
154+
total_elements[num_in_batch] = src.numel();
155+
num_in_batch++;
156+
}
157+
158+
dim_offset += dim_size;
159+
ti++;
160+
}
161+
162+
if (num_in_batch == 0) continue;
163+
164+
for (int j = num_in_batch; j < 4; ++j) {
165+
batch_tensors[j] = batch_tensors[0];
166+
dim_sizes[j] = 0;
167+
dim_offsets[j] = 0;
168+
total_elements[j] = 0;
169+
}
134170

135-
at::Tensor src_tensor = input_tensor;
136-
if (input_tensor.scalar_type() != out_dtype) {
137-
src_tensor = input_tensor.to(out_dtype);
171+
int64_t max_elements = 0;
172+
for (int j = 0; j < num_in_batch; ++j) {
173+
max_elements = std::max(max_elements, total_elements[j]);
138174
}
139175

140-
at::Tensor output_view = at::as_strided(out, src_tensor.sizes(), out.strides(), storage_offsets[i]);
141-
142-
auto options = torch::TensorOptions().device(src_tensor.device()).dtype(torch::kInt64);
143-
at::Tensor in_strides = torch::tensor(src_tensor.strides(), options);
144-
at::Tensor out_strides = torch::tensor(output_view.strides(), options);
145-
at::Tensor shapes = torch::tensor(src_tensor.sizes(), options);
146-
147-
int64_t ndim_val = src_tensor.dim();
148-
int64_t num_elements = src_tensor.numel();
149-
150-
constexpr int BLOCK_SIZE = 256;
151-
constexpr int MAX_DIMS = 8;
152-
TORCH_CHECK(ndim_val <= MAX_DIMS,
153-
"Tensor dimension ",
154-
ndim_val,
155-
" exceeds the maximum supported by the kernel (",
156-
MAX_DIMS,
157-
")");
158-
159-
unsigned int grid_x = (num_elements + BLOCK_SIZE - 1) / BLOCK_SIZE;
160-
161-
copy_kernel_func(raw_stream,
162-
grid_x,
163-
1,
164-
1,
165-
4,
166-
2,
167-
src_tensor,
168-
output_view,
169-
in_strides,
170-
out_strides,
171-
shapes,
172-
ndim_val,
173-
num_elements,
174-
BLOCK_SIZE,
175-
MAX_DIMS);
176+
unsigned int grid_x = (max_elements + BLOCK - 1) / BLOCK;
177+
unsigned int grid_y = num_in_batch;
178+
179+
kernel(raw_stream,
180+
grid_x,
181+
grid_y,
182+
1,
183+
NUM_WARPS,
184+
NUM_STAGES,
185+
out,
186+
batch_tensors[0],
187+
batch_tensors[1],
188+
batch_tensors[2],
189+
batch_tensors[3],
190+
dim_sizes[0],
191+
dim_sizes[1],
192+
dim_sizes[2],
193+
dim_sizes[3],
194+
dim_size_out,
195+
dim_prod_post,
196+
dim_offsets[0],
197+
dim_offsets[1],
198+
dim_offsets[2],
199+
dim_offsets[3],
200+
total_elements[0],
201+
total_elements[1],
202+
total_elements[2],
203+
total_elements[3],
204+
BLOCK);
176205
}
177206
return out;
178207
}

src/flag_gems/ops/cat.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,24 +80,24 @@ def cat_copy_func_kernel_4(
8080

8181
if pid_y == 0:
8282
in_ptr = in_ptr_a
83-
dim_size_in = dim_size_in_a
83+
dim_size_in = tl.cast(dim_size_in_a, tl.int64)
8484
dim_offset = tl.cast(dim_offset_a, tl.int64)
85-
total_elements = total_elements_a
85+
total_elements = tl.cast(total_elements_a, tl.int64)
8686
elif pid_y == 1:
8787
in_ptr = in_ptr_b
88-
dim_size_in = dim_size_in_b
88+
dim_size_in = tl.cast(dim_size_in_b, tl.int64)
8989
dim_offset = tl.cast(dim_offset_b, tl.int64)
90-
total_elements = total_elements_b
90+
total_elements = tl.cast(total_elements_b, tl.int64)
9191
elif pid_y == 2:
9292
in_ptr = in_ptr_c
93-
dim_size_in = dim_size_in_c
93+
dim_size_in = tl.cast(dim_size_in_c, tl.int64)
9494
dim_offset = tl.cast(dim_offset_c, tl.int64)
95-
total_elements = total_elements_c
95+
total_elements = tl.cast(total_elements_c, tl.int64)
9696
else:
9797
in_ptr = in_ptr_d
98-
dim_size_in = dim_size_in_d
98+
dim_size_in = tl.cast(dim_size_in_d, tl.int64)
9999
dim_offset = tl.cast(dim_offset_d, tl.int64)
100-
total_elements = total_elements_d
100+
total_elements = tl.cast(total_elements_d, tl.int64)
101101

102102
block_start = pid_x * BLOCK_X
103103
offsets = tl.arange(0, BLOCK_X)

0 commit comments

Comments
 (0)