Skip to content

Commit 104cda4

Browse files
committed
Refactor process input for torch.compile
1 parent 41751ad commit 104cda4

8 files changed

Lines changed: 309 additions & 147 deletions

File tree

humming/csrc/launcher/launcher.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -348,14 +348,18 @@ COMMON_TORCH_LIBRARY(humming, m) {
348348
m.def("register_process_input_kernel(str cubin_path) -> (int, str)");
349349
m.def("get_kernel_smem_size(int kernel_id) -> int");
350350
m.def(
351-
"launch_process_input(Tensor configs, Tensor inputs, Tensor? outputs, Tensor? group_scales, "
352-
"Tensor? token_scales, Tensor? expert_layout, Tensor? indices, bool inplace) "
353-
"-> (Tensor, Tensor?, Tensor?)");
351+
"launch_process_input(Tensor configs, Tensor inputs, Tensor(a!) outputs, "
352+
"Tensor(b!)? group_scales, Tensor(c!)? token_scales, Tensor? expert_layout, "
353+
"Tensor? indices) -> ()");
354+
m.def(
355+
"launch_process_input.inplace(Tensor configs, Tensor(a!) inputs, "
356+
"Tensor? expert_layout, Tensor? indices) -> ()");
354357
};
355358

356359
COMMON_TORCH_LIBRARY_IMPL(humming, CUDA, m) {
357360
m.impl("launch_kernel", COMMON_TORCH_BOX(&launch_kernel));
358361
m.impl("launch_process_input", COMMON_TORCH_BOX(&launch_process_input));
362+
m.impl("launch_process_input.inplace", COMMON_TORCH_BOX(&launch_process_input_inplace));
359363
m.impl("launch_kernel.out", COMMON_TORCH_BOX(&launch_kernel_out));
360364
};
361365

@@ -367,4 +371,6 @@ COMMON_TORCH_LIBRARY_IMPL(humming, Undefined, m) {
367371

368372
COMMON_TORCH_LIBRARY_IMPL(humming, Meta, m) {
369373
m.impl("launch_kernel.out", COMMON_TORCH_BOX(&launch_kernel_out));
374+
m.impl("launch_process_input", COMMON_TORCH_BOX(&launch_process_input));
375+
m.impl("launch_process_input.inplace", COMMON_TORCH_BOX(&launch_process_input_inplace));
370376
};

humming/csrc/launcher/process_input.h

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -251,19 +251,6 @@ inline std::vector<int64_t> process_input_output_shape(
251251
return {shape.num_output_rows, columns};
252252
}
253253

254-
inline std::vector<int64_t> process_input_leading_shape(
255-
const ProcessInputKernelData &data, const Tensor &inputs, const ProcessInputShape &shape) {
256-
if (data.layout == 0) {
257-
std::vector<int64_t> leading_shape;
258-
leading_shape.reserve(inputs.dim() - 1);
259-
for (int64_t dimension = 0; dimension + 1 < inputs.dim(); dimension++)
260-
leading_shape.push_back(inputs.size(dimension));
261-
return leading_shape;
262-
}
263-
if (data.layout == 3) return {shape.num_experts, shape.max_tokens_per_expert};
264-
return {shape.num_output_rows};
265-
}
266-
267254
inline Tensor prepare_process_input_output(
268255
const ProcessInputKernelData &data,
269256
const Tensor &inputs,
@@ -278,7 +265,7 @@ inline Tensor prepare_process_input_output(
278265
ASSERT_CHECK(!outputs.has_value() || outputs->data_ptr() == inputs.data_ptr(), "inplace output must alias inputs");
279266
outputs = inputs;
280267
}
281-
if (!outputs.has_value()) return torch_empty(expected_shape, dtype, inputs.device());
268+
ASSERT_CHECK(outputs.has_value(), "outputs must be allocated by prepare_process_input");
282269
check_process_input_tensor(*outputs, "outputs", inputs.get_device(), dtype);
283270
ASSERT_CHECK(outputs->dim() == static_cast<int64_t>(expected_shape.size()), "invalid output rank");
284271
for (size_t dimension = 0; dimension < expected_shape.size(); dimension++)
@@ -302,18 +289,7 @@ inline std::optional<Tensor> prepare_process_input_group_scales(
302289
if (data.scale_layout == 2) elements = shape.group_scale_stride * CEIL_DIV(groups, 4) * 4;
303290
ScalarType dtype = dtype_id_to_tensor_dtype(data.group_scale_dtype_id);
304291
bool allow_byte = data.group_scale_dtype_id == 20080800;
305-
if (!scales.has_value()) {
306-
std::vector<int64_t> scale_shape;
307-
if (data.scale_layout == 0) {
308-
scale_shape = process_input_leading_shape(data, inputs, shape);
309-
scale_shape.push_back(groups);
310-
} else if (data.scale_layout == 1) {
311-
scale_shape = {groups, shape.group_scale_stride};
312-
} else {
313-
scale_shape = {CEIL_DIV(groups, 4), shape.group_scale_stride, 4};
314-
}
315-
return torch_empty(scale_shape, dtype, inputs.device());
316-
}
292+
ASSERT_CHECK(scales.has_value(), "group_scales must be allocated by prepare_process_input");
317293
check_process_input_tensor(*scales, "group_scales", inputs.get_device(), dtype, allow_byte);
318294
ASSERT_CHECK(scales->numel() == elements, "invalid group_scales size");
319295
return scales;
@@ -331,11 +307,7 @@ inline std::optional<Tensor> prepare_process_input_token_scales(
331307
return std::nullopt;
332308
}
333309
int64_t elements = static_scale ? shape.num_experts : shape.num_output_rows;
334-
if (!scales.has_value()) {
335-
ASSERT_CHECK(dynamic_scale, "static token_scales is required");
336-
auto scale_shape = process_input_leading_shape(data, inputs, shape);
337-
return torch_empty(scale_shape, ScalarType::Float, inputs.device());
338-
}
310+
ASSERT_CHECK(scales.has_value(), "token_scales must be allocated by prepare_process_input");
339311
check_process_input_tensor(*scales, "token_scales", inputs.get_device(), ScalarType::Float);
340312
ASSERT_CHECK(scales->numel() == elements, "invalid token_scales size");
341313
return scales;
@@ -457,7 +429,7 @@ inline void launch_process_input_finalizer(
457429
check_curesult(cuLaunchKernelEx(&config, data.func, kernel_args, nullptr), "cuLaunchKernelEx");
458430
}
459431

460-
inline std::tuple<Tensor, std::optional<Tensor>, std::optional<Tensor>> launch_process_input(
432+
inline void launch_process_input_impl(
461433
Tensor configs_tensor,
462434
Tensor inputs,
463435
std::optional<Tensor> outputs,
@@ -524,5 +496,29 @@ inline std::tuple<Tensor, std::optional<Tensor>, std::optional<Tensor>> launch_p
524496
secondary, intermediate, *group_scales, *token_scales, expert_layout, indices, shape);
525497
}
526498
}
527-
return std::make_tuple(prepared_output, group_scales, token_scales);
499+
}
500+
501+
inline void launch_process_input(
502+
Tensor configs_tensor,
503+
Tensor inputs,
504+
Tensor outputs,
505+
std::optional<Tensor> group_scales,
506+
std::optional<Tensor> token_scales,
507+
std::optional<Tensor> expert_layout,
508+
std::optional<Tensor> indices) {
509+
if (!inputs.is_cuda()) return;
510+
launch_process_input_impl(
511+
configs_tensor, inputs, outputs, group_scales, token_scales,
512+
expert_layout, indices, false);
513+
}
514+
515+
inline void launch_process_input_inplace(
516+
Tensor configs_tensor,
517+
Tensor inputs,
518+
std::optional<Tensor> expert_layout,
519+
std::optional<Tensor> indices) {
520+
if (!inputs.is_cuda()) return;
521+
launch_process_input_impl(
522+
configs_tensor, inputs, inputs, std::nullopt, std::nullopt,
523+
expert_layout, indices, true);
528524
}

humming/forward.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ def _resolve_use_pdl(
2525

2626

2727
def _prepare_input_scale(config: LayerConfig, input_scale: torch.Tensor) -> torch.Tensor:
28-
if str(config.as_dtype) == "float8e8m0" and input_scale.dtype != torch.int32:
28+
mx_scale_dtype = str(config.as_dtype) in ("float8e4m3", "float8e8m0")
29+
grouped_mxmma = config.mma_type == MmaType.MXMMA and config.input_scale_group_size > 0
30+
if mx_scale_dtype and grouped_mxmma and input_scale.dtype != torch.int32:
2931
packed_scale = input_scale.view(torch.int32)
3032
if input_scale.ndim == 3:
3133
packed_scale = packed_scale.reshape(input_scale.size(0), input_scale.size(1))

humming/kernel/process_input.py

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -227,16 +227,9 @@ def spec_key(spec):
227227
secondary_id = kernels[spec_key(secondary)].kernel_id
228228
plan_kernel_ids[plan] = primary_id, secondary_id
229229

230-
compiled_intervals = []
231-
for first, last, plan in intervals:
232-
kernel_ids = plan_kernel_ids[plan]
233-
if compiled_intervals and compiled_intervals[-1][2] == kernel_ids:
234-
compiled_intervals[-1] = compiled_intervals[-1][0], last, kernel_ids
235-
else:
236-
compiled_intervals.append((first, last, kernel_ids))
237-
238230
launch_configs = []
239-
for first, last, (primary_id, secondary_id) in compiled_intervals:
231+
for first, last, plan in intervals:
232+
primary_id, secondary_id = plan_kernel_ids[plan]
240233
launch_configs.extend((first - 1, last, primary_id, secondary_id))
241234
result = torch.tensor(launch_configs, dtype=torch.int64, device="cpu")
242235
if cache_key is not None:

humming/ops/input/hadamard.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,26 @@ def hadamard_quant_input(
4444
global_scale: torch.Tensor | None = None,
4545
use_pdl: bool = False,
4646
) -> tuple[torch.Tensor, torch.Tensor]:
47-
if group_size is None or group_size == 0:
47+
channelwise = group_size is None or group_size == 0
48+
if channelwise and scales is None and scale_dtype == "float32" and global_scale is None:
49+
quantized, _, result_token_scales = process_input(
50+
inputs,
51+
outputs=outputs,
52+
quant_mode=QuantizationMode.DynamicToken,
53+
quant_dtype=quant_dtype,
54+
hadamard_block_size=block_size,
55+
use_pdl=use_pdl,
56+
)
57+
assert result_token_scales is not None
58+
return quantized, result_token_scales.unsqueeze(-1)
59+
60+
if channelwise:
4861
group_size = inputs.size(-1)
4962

5063
group_scale_layout = GroupScaleLayout.RowMajor
5164
if m_major_scale:
5265
group_scale_layout = GroupScaleLayout.MMajor
53-
if scale_dtype == "float8e8m0":
66+
if scale_dtype in ("float8e4m3", "float8e8m0"):
5467
group_scale_layout = GroupScaleLayout.MxPacked
5568

5669
quant_mode = QuantizationMode.DynamicGroup

0 commit comments

Comments
 (0)