Skip to content

Commit 083c7f2

Browse files
committed
add draft test for simple gemm kernel
1 parent b210b5c commit 083c7f2

7 files changed

Lines changed: 472 additions & 81 deletions

File tree

bitsandbytes/backends/xpu/ops.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ def _gemv_4bit_impl(
7474
blocksize: int,
7575
out: torch.Tensor,
7676
) -> None:
77-
m = ct.c_int32(1)
77+
import pdb
78+
pdb.set_trace()
79+
m = ct.c_int32(*A.shape[:-1])
7880
n = ct.c_int32(shapeB[0])
7981
k = ct.c_int32(shapeB[1])
8082

@@ -180,7 +182,7 @@ def _(
180182
blocksize: int,
181183
) -> torch.Tensor:
182184
shape = (*A.shape[:-1], shapeB[0])
183-
out = torch.empty(shape, device=A.device, dtype=A.dtype)
185+
out = torch.empty(shape, device=A.device, dtype=torch.float32)
184186
_gemv_4bit_impl(A, B, shapeB, absmax, code, blocksize, out=out)
185187
return out
186188

bitsandbytes/functional.py

Lines changed: 33 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,39 +1630,39 @@ def gemv_4bit(
16301630
raise ValueError("state cannot be None. gemv_4bit() requires the state from quantize_4bit()")
16311631

16321632
absmax = state.absmax
1633-
if state.nested:
1634-
absmax = dequantize_blockwise(absmax, state.state2) + state.offset
1635-
1636-
if getattr(state, "ipex", False) and state.quant_type == "nf4":
1637-
# compute_dtype: 1 indicates fp16, 2 indicates bf16
1638-
compute_dtype = 2 if A.dtype == torch.bfloat16 else 1
1639-
out = torch.ops.torch_ipex.woq_linear(
1640-
A,
1641-
B,
1642-
"nf4",
1643-
state.shape,
1644-
state.new_scales,
1645-
state.new_zeros,
1646-
None,
1647-
None,
1648-
state.blocksize,
1649-
compute_dtype,
1650-
1,
1651-
state.compensation,
1652-
)
1653-
return out
1654-
1655-
if out is not None:
1656-
torch.ops.bitsandbytes.gemv_4bit.out(
1657-
A,
1658-
B,
1659-
state.shape,
1660-
absmax,
1661-
state.code,
1662-
state.blocksize,
1663-
out=out,
1664-
)
1665-
return out
1633+
#if state.nested:
1634+
# absmax = dequantize_blockwise(absmax, state.state2) + state.offset
1635+
1636+
#if getattr(state, "ipex", False) and state.quant_type == "nf4":
1637+
# # compute_dtype: 1 indicates fp16, 2 indicates bf16
1638+
# compute_dtype = 2 if A.dtype == torch.bfloat16 else 1
1639+
# out = torch.ops.torch_ipex.woq_linear(
1640+
# A,
1641+
# B,
1642+
# "nf4",
1643+
# state.shape,
1644+
# state.new_scales,
1645+
# state.new_zeros,
1646+
# None,
1647+
# None,
1648+
# state.blocksize,
1649+
# compute_dtype,
1650+
# 1,
1651+
# state.compensation,
1652+
# )
1653+
# return out
1654+
1655+
#if out is not None:
1656+
# torch.ops.bitsandbytes.gemv_4bit.out(
1657+
# A,
1658+
# B,
1659+
# state.shape,
1660+
# absmax,
1661+
# state.code,
1662+
# state.blocksize,
1663+
# out=out,
1664+
# )
1665+
# return out
16661666

16671667
return torch.ops.bitsandbytes.gemv_4bit.default(
16681668
A,

build_xpu.sh

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
cmake -DCMAKE_CXX_STANDARD=17 -DSYCL_INTEL_TARGET=ON -DENABLE_INTEL_XMX=ON -DCUTLASS_ENABLE_SYCL=ON -DCOMPUTE_BACKEND=xpu -S .
2+
#cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS_DEBUG="-O0 -g" -DCMAKE_CXX_STANDARD=17 -DSYCL_INTEL_TARGET=ON -DENABLE_INTEL_XMX=ON -DCUTLASS_ENABLE_SYCL=ON -DCOMPUTE_BACKEND=xpu -S .
3+
#cmake -DCOMPUTE_BACKEND=xpu -DCMAKE_BUILD_TYPE=Debug -DCMAKE_CXX_FLAGS_DEBUG="-O0 -g" -S .
4+
#cmake --build . --config Release -j
5+
make
6+
pip install -e .

csrc/pythonInterface.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -375,12 +375,12 @@ void gemv_4bit_inference_fp16(
375375
int m, int n, int k, sycl::half * A, unsigned char* B, float *absmax, float *datatype, sycl::half * out,
376376
int lda, int ldb, int ldc, int blocksize, sycl::queue* stream
377377
) {
378-
gemv_4bit_inference<sycl::half, 16>(m, n, k, A, B, absmax, datatype, out, lda, ldb, ldc, blocksize, stream);
378+
//gemv_4bit_inference<sycl::half, 16>(m, n, k, A, B, absmax, datatype, out, lda, ldb, ldc, blocksize, stream);
379379
}
380380

381381
void gemv_4bit_inference_bf16(
382-
int m, int n, int k, sycl::ext::oneapi::bfloat16 * A, unsigned char* B, float *absmax, float *datatype,
383-
sycl::ext::oneapi::bfloat16 * out, int lda, int ldb, int ldc, int blocksize, sycl::queue* stream
382+
int m, int n, int k, sycl::ext::oneapi::bfloat16 * A, sycl::ext::oneapi::bfloat16* B, float *absmax, float *datatype,
383+
float * out, int lda, int ldb, int ldc, int blocksize, sycl::queue* stream
384384
) {
385385
gemv_4bit_inference<sycl::ext::oneapi::bfloat16, 16>(m, n, k, A, B, absmax, datatype, out, lda, ldb, ldc, blocksize, stream);
386386
}
@@ -389,7 +389,7 @@ void gemv_4bit_inference_fp32(
389389
int m, int n, int k, float * A, unsigned char* B, float *absmax, float *datatype, float * out, int lda,
390390
int ldb, int ldc, int blocksize, sycl::queue* stream
391391
) {
392-
gemv_4bit_inference<float, 32>(m, n, k, A, B, absmax, datatype, out, lda, ldb, ldc, blocksize, stream);
392+
//gemv_4bit_inference<float, 32>(m, n, k, A, B, absmax, datatype, out, lda, ldb, ldc, blocksize, stream);
393393
}
394394

395395
#endif
@@ -811,8 +811,8 @@ void cgemv_4bit_inference_fp16(
811811
}
812812

813813
void cgemv_4bit_inference_bf16(
814-
int m, int n, int k, sycl::ext::oneapi::bfloat16 * A, unsigned char* B, float *absmax, float *datatype,
815-
sycl::ext::oneapi::bfloat16 * out, int lda, int ldb, int ldc, int blocksize, sycl::queue* stream
814+
int m, int n, int k, sycl::ext::oneapi::bfloat16 * A, sycl::ext::oneapi::bfloat16* B, float *absmax, float *datatype,
815+
float * out, int lda, int ldb, int ldc, int blocksize, sycl::queue* stream
816816
) {
817817
gemv_4bit_inference_bf16(m, n, k, A, B, absmax, datatype, out, lda, ldb, ldc, blocksize, stream);
818818
}

csrc/xpu_cutlass.cpp

Lines changed: 46 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#include <sycl/sycl.hpp>
77

88
template <typename T, int BITS>
9-
void gemv_4bit_inference(int m, int n, int k, T *A, unsigned char *B,
10-
float *absmax, float *datatype, T *out, int lda,
9+
void gemv_4bit_inference(int m, int n, int k, T *A, T *B,
10+
float *absmax, float *datatype, float *out, int lda,
1111
int ldb, int ldc, int blocksize, sycl::queue *stream) {
1212
std::cout<<"this is gemv_4bit_inference path !!!\n";
1313

@@ -24,22 +24,6 @@ void gemv_4bit_inference(int m, int n, int k, T *A, unsigned char *B,
2424
typename TiledMMAHelper<MMA_Atom<XE_8x16x16_F32BF16BF16F32_TT>, Layout<TileShape>,
2525
Layout<Shape<_8, _4, _1>, Stride<_4, _1, _0>>>::TiledMMA;
2626

27-
// GEMM Mainloop - iteration over blocks in K dimension
28-
using CollectiveMainloop = cutlass::gemm::collective::CollectiveMma<
29-
cutlass::gemm::MainloopIntelPVC<2>, //use PipelineStages = 2
30-
TileShape,
31-
bfloat16_t, // data_type of input: A
32-
cutlass::gemm::TagToStrideA_t<cutlass::layout::RowMajor>, // Convert CUTLASS 2.x to CUTLASS 3.x representation
33-
bfloat16_t, // data_type of input: B
34-
cutlass::gemm::TagToStrideB_t<cutlass::layout::RowMajor>, // Convert CUTLASS 2.x to CUTLASS 3.x representation
35-
TiledMma,
36-
XE_2D_U16x32x32_LD_N, // 2D block copy operations used for A
37-
void, void, cute::identity,
38-
XE_2D_U16x32x32_LD_V, // 2D block copy operations used for B
39-
void, void, cute::identity
40-
>;
41-
42-
//TODO: Remove the Epilogue as BNB may not need it.
4327
// Create the Epilogue
4428
using EpilogueOp = cutlass::epilogue::fusion::LinearCombination<float /*data_type of GEMM output*/, ElementComputeEpilogue, ElementAccumulator, ElementAccumulator, cutlass::FloatRoundStyle::round_to_nearest>;
4529

@@ -58,20 +42,35 @@ void gemv_4bit_inference(int m, int n, int k, T *A, unsigned char *B,
5842
XE_2D_U32x8x16_ST_N, // The copy atom used to store matrix D
5943
void, void>;
6044

45+
// GEMM Mainloop - iteration over blocks in K dimension
46+
using CollectiveMainloop = cutlass::gemm::collective::CollectiveMma<
47+
cutlass::gemm::MainloopIntelPVC<2>, //use PipelineStages = 2
48+
TileShape,
49+
bfloat16_t, // data_type of input: A
50+
cutlass::gemm::TagToStrideA_t<cutlass::layout::RowMajor>, // Convert CUTLASS 2.x to CUTLASS 3.x representation
51+
bfloat16_t, // data_type of input: B
52+
cutlass::gemm::TagToStrideB_t<cutlass::layout::RowMajor>, // Convert CUTLASS 2.x to CUTLASS 3.x representation
53+
TiledMma,
54+
XE_2D_U16x32x32_LD_N, // 2D block copy operations used for A
55+
void, void, cute::identity,
56+
XE_2D_U16x32x32_LD_V, // 2D block copy operations used for B
57+
void, void, cute::identity
58+
>;
59+
6160
// Define the whole kernel (mainloop and epilogue)
6261
using GemmKernel = cutlass::gemm::kernel::GemmUniversal<
6362
Shape<int, int, int, int>, // Defer global problem shape definition to runtime
6463
CollectiveMainloop,
6564
CollectiveEpilogue
6665
>;
6766

68-
auto problem_size = typename GemmKernel::ProblemShape{m, n, k, ldb};
67+
auto problem_size = typename GemmKernel::ProblemShape{m, n, k, 1};
6968
auto [M, N, K, L] = cute::append<4>(problem_size, 1);
7069

7170
typename GemmKernel::StrideA stride_A = cutlass::make_cute_packed_stride(typename GemmKernel::StrideA{}, cute::make_shape(M, K, L));
7271
typename GemmKernel::StrideB stride_B = cutlass::make_cute_packed_stride(typename GemmKernel::StrideB{}, cute::make_shape(N, K, L));
7372
typename GemmKernel::StrideC stride_C = cutlass::make_cute_packed_stride(typename GemmKernel::StrideC{}, cute::make_shape(M, N, L));
74-
typename GemmKernel::StrideD stride_D = cutlass::make_cute_packed_stride(typename GemmKernel::StrideD{}, cute::make_shape(M, N, L));
73+
//typename GemmKernel::StrideD stride_D = cutlass::make_cute_packed_stride(typename GemmKernel::StrideD{}, cute::make_shape(M, N, L));
7574

7675
//
7776
// Data members
@@ -80,12 +79,12 @@ void gemv_4bit_inference(int m, int n, int k, T *A, unsigned char *B,
8079
cutlass::DeviceAllocation<typename Gemm::ElementA> block_A;
8180
cutlass::DeviceAllocation<typename Gemm::ElementB> block_B;
8281
cutlass::DeviceAllocation<typename Gemm::ElementC> block_C;
83-
cutlass::DeviceAllocation<typename CollectiveEpilogue::ElementOutput> block_D;
82+
//cutlass::DeviceAllocation<typename CollectiveEpilogue::ElementOutput> block_D;
8483

8584
block_A.reset(M * K * L);
8685
block_B.reset(K * N * L);
8786
block_C.reset(M * N * L);
88-
block_D.reset(M * N * L);
87+
//block_D.reset(M * N * L);
8988

9089
//TODO: check whether need the fake data?
9190
uint64_t seed = 0;
@@ -95,40 +94,49 @@ void gemv_4bit_inference(int m, int n, int k, T *A, unsigned char *B,
9594

9695
cutlass::KernelHardwareInfo hw_info;
9796
hw_info.sm_count = cutlass::KernelHardwareInfo::query_device_multiprocessor_count(hw_info.device_id);
98-
97+
std::cout<<"log1 ...\n";
9998
float alpha=1.0; //Maybe will not be used by BNB, just keep it temporarily.
10099
float beta=0.f; //Maybe will not be used by BNB, just keep it temporarily.
101100
typename GemmKernel::Arguments arguments{
102101
cutlass::gemm::GemmUniversalMode::kGemm,
103102
problem_size,
103+
#if 1
104+
{(bfloat16_t*)A, stride_A, (bfloat16_t*)B, stride_B},
105+
{{alpha, beta}, nullptr, stride_C, out, stride_C}, hw_info};
106+
#else
104107
{block_A.get(), stride_A, block_B.get(), stride_B},
105-
{{alpha, beta}, block_C.get(), stride_C, block_D.get(), stride_D}, hw_info};
108+
{{alpha, beta}, nullptr, stride_C, block_C.get(), stride_C}, hw_info};
109+
#endif
106110

111+
std::cout<<"log2 ...\n";
107112
Gemm gemm_op;
108113

109114
size_t workspace_size = Gemm::get_workspace_size(arguments);
110115
cutlass::device_memory::allocation<uint8_t> workspace(workspace_size);
111116

112117
CUTLASS_CHECK(gemm_op.initialize(arguments, workspace.get()));
113-
118+
std::cout<<"log3 ...\n";
114119
// Run the GEMM
115120
CUTLASS_CHECK(gemm_op.run());
116121

122+
std::cout<<"log4 ...\n";
117123
syclcompat::wait();
124+
125+
//out = (T*)out;
118126
}
119127

120-
template void gemv_4bit_inference<sycl::half, 16>(
121-
int m, int n, int k, sycl::half *A, unsigned char *B, float *absmax,
122-
float *datatype, sycl::half *out, int lda, int ldb, int ldc, int blocksize,
123-
sycl::queue *stream);
128+
//template void gemv_4bit_inference<sycl::half, 16>(
129+
// int m, int n, int k, sycl::half *A, unsigned char *B, float *absmax,
130+
// float *datatype, sycl::half *out, int lda, int ldb, int ldc, int blocksize,
131+
// sycl::queue *stream);
124132
template void gemv_4bit_inference<sycl::ext::oneapi::bfloat16, 16>(
125-
int m, int n, int k, sycl::ext::oneapi::bfloat16 *A, unsigned char *B,
126-
float *absmax, float *datatype, sycl::ext::oneapi::bfloat16 *out, int lda,
133+
int m, int n, int k, sycl::ext::oneapi::bfloat16 *A, sycl::ext::oneapi::bfloat16 *B,
134+
float *absmax, float *datatype, float *out, int lda,
127135
int ldb, int ldc, int blocksize, sycl::queue *stream);
128-
template void gemv_4bit_inference<float, 32>(int m, int n, int k, float *A,
129-
unsigned char *B, float *absmax,
130-
float *datatype, float *out,
131-
int lda, int ldb, int ldc,
132-
int blocksize,
133-
sycl::queue *stream);
134-
136+
//template void gemv_4bit_inference<float, 32>(int m, int n, int k, float *A,
137+
// unsigned char *B, float *absmax,
138+
// float *datatype, float *out,
139+
// int lda, int ldb, int ldc,
140+
// int blocksize,
141+
// sycl::queue *stream);
142+
//

csrc/xpu_cutlass.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,6 @@ class kgemv_4bit_inference_cutlass {
7171
#endif
7272

7373
template <typename T, int BITS>
74-
void gemv_4bit_inference(int m, int n, int k, T *A, unsigned char *B,
75-
float *absmax, float *datatype, T *out, int lda,
74+
void gemv_4bit_inference(int m, int n, int k, T *A, T *B,
75+
float *absmax, float *datatype, float *out, int lda,
7676
int ldb, int ldc, int blocksize, sycl::queue *stream);

0 commit comments

Comments
 (0)