main
cuh 84 lines 3.13 KB
Raw
1 #pragma once
2
3 #include "machete_prepack_kernel.cuh"
4 #include "libtorch_stable/cutlass_extensions/torch_utils.hpp"
5 #include "core/scalar_type.hpp"
6 #include "libtorch_stable/torch_utils.h"
7
8 #include <torch/csrc/stable/tensor.h>
9 #include <torch/headeronly/core/ScalarType.h>
10
11 #include <optional>
12
13 namespace machete {
14
15 struct PrepackBArgs {
16 torch::stable::Tensor const& B;
17 torch::headeronly::ScalarType a_type;
18 vllm::ScalarType b_type;
19 std::optional<torch::headeronly::ScalarType> maybe_group_scales_type;
20 };
21
22 template <typename PrepackedLayoutB>
23 torch::stable::Tensor prepack_impl(torch::stable::Tensor const& B) {
24 const torch::stable::accelerator::DeviceGuard device_guard(
25 B.get_device_index());
26 using ElementB = typename PrepackedLayoutB::ElementB;
27 using PPBlockShape_NK = typename PrepackedLayoutB::PPBlockShape_NK;
28
29 auto device = B.device();
30 auto stream = get_current_cuda_stream(device.index());
31 auto B_ptr = static_cast<ElementB const*>(B.const_data_ptr());
32 // elements per storage item for B
33 auto eles_per_storage =
34 (B.element_size() * 8) / cute::sizeof_bits_v<ElementB>;
35
36 // torch B passed in is/should be (packed_K,N), the kernel expects (N,K,L) (to
37 // match cutlass using (N,K,L) for B), so we transpose B to (N,packed_K,L)
38 auto Bt_packed = torch::stable::transpose(B, 0, 1);
39
40 STD_TORCH_CHECK(
41 (B.size(0) * eles_per_storage) % size<1>(PPBlockShape_NK{}) == 0,
42 "B.shape[0] (in terms of unpacked elements) must be a multiple of ",
43 size<1>(PPBlockShape_NK{}));
44 STD_TORCH_CHECK(B.size(1) % size<0>(PPBlockShape_NK{}) == 0,
45 "B.shape[1] must be a multiple of ",
46 size<0>(PPBlockShape_NK{}));
47
48 using StrideB = cutlass::detail::TagToStrideB_t<cutlass::layout::ColumnMajor>;
49 auto const l_Bt_packed = make_cute_layout<StrideB>(Bt_packed, "B");
50
51 // convert (N,packed_K,L) layout to (N,K,L) layout
52 // in effect we want to do: blocked_product(layout_Bt_packed,
53 // make_ordered_layout(make_shape(_1{}, eles_per_storage, _1{}),
54 // Step<_1, _0, _2>{}));
55 // but blocked_product does not support dynamic strides so we implement the
56 // equivalent manually,
57 // new_shape = (N, packed_K, L) * (1, eles_per_storage, 1) -> (N, K, L)
58 // new_stride = (s0, s1, s2) * (eles_per_storage, 1, eles_per_storage)
59 // when s1 == 1
60 STD_TORCH_CHECK(stride<1>(l_Bt_packed) == 1);
61 // clang-format off
62 auto const layout_Bt = make_layout(
63 transform_with_idx(l_Bt_packed.shape(), [&](auto ele, auto idx) {
64 return idx == 1 ? ele * eles_per_storage : ele;
65 }),
66 transform_with_idx(l_Bt_packed.stride(), [&](auto ele, auto idx) {
67 return idx != 1 ? ele * eles_per_storage : ele;
68 }));
69 // clang-format on
70
71 // Allocate output
72 torch::stable::Tensor D = torch::stable::empty(
73 B.sizes(), B.scalar_type(), std::nullopt, B.device(), std::nullopt,
74 torch::headeronly::MemoryFormat::Contiguous);
75
76 prepack_B_template<PrepackedLayoutB>(
77 stream, B_ptr, layout_Bt, static_cast<ElementB*>(D.mutable_data_ptr()));
78
79 return D;
80 };
81
82 torch::stable::Tensor prepack_B_dispatch(PrepackBArgs args);
83
84 }; // namespace machete