Skip to content

Commit 8f4099d

Browse files
authored
[CUDA] Guard qmm_naive scale and bias loads at tile boundaries (#3509)
1 parent 0778926 commit 8f4099d

2 files changed

Lines changed: 31 additions & 8 deletions

File tree

mlx/backend/cuda/quantized/qmm/qmm_naive.cu

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ void qmm_naive_kernel(
4646
Tensor mC_mnl = make_tensor(make_gmem_ptr(C), select<0,1,3>(shape_MNKL), dC); // (M,N,L)
4747

4848
Tensor mS_nkl = make_tensor(make_gmem_ptr(S), S_layout); // (N,(group_size,K/group_size),L)
49-
Tensor mZ_nkl = make_tensor(make_gmem_ptr(Z), S_layout); // (N,(group_size,K/group_size),L)
5049

5150
// For gather, use index lookup for input batch slicing.
5251
uint32_t a_batch = lhs_indices ? lhs_indices[l_coord] : l_coord;
@@ -58,7 +57,6 @@ void qmm_naive_kernel(
5857
Tensor mC = mC_mnl(_,_,l_coord); // (M,N)
5958

6059
Tensor mS = mS_nkl(_,_,b_batch); // (N,(group_size,K/group_size))
61-
Tensor mZ = mZ_nkl(_,_,b_batch); // (N,(group_size,K/group_size))
6260

6361
// Get the appropriate blocks for this thread block.
6462
auto cta_coord = make_coord(m_coord, n_coord, _); // (m,n,k)
@@ -67,7 +65,16 @@ void qmm_naive_kernel(
6765
Tensor gC = local_tile(mC, cta_tiler, cta_coord, Step<_1,_1, X>{}); // (BLK_M,BLK_N)
6866

6967
Tensor gS = local_tile(mS, cta_tiler, cta_coord, Step< X,_1,_1>{}); // (BLK_N,BLK_K,k)
70-
Tensor gZ = local_tile(mZ, cta_tiler, cta_coord, Step< X,_1,_1>{}); // (BLK_N,BLK_K,k)
68+
auto gZ = [&]() {
69+
if constexpr (quant_has_bias_v<Quant>) {
70+
Tensor mZ_nkl = make_tensor(make_gmem_ptr(Z), S_layout); // (N,(group_size,K/group_size),L)
71+
Tensor mZ = mZ_nkl(_,_,b_batch); // (N,(group_size,K/group_size))
72+
return local_tile(mZ, cta_tiler, cta_coord, Step< X,_1,_1>{}); // (BLK_N,BLK_K,k)
73+
} else {
74+
// Dummy tensor; no-bias paths never offset or load gZ.
75+
return gS;
76+
}
77+
}();
7178

7279
// Compute tile residues for predication.
7380
int m_max_coord = size<0>(shape_MNKL) - size<0>(cta_tiler) * m_coord; // M - BLK_M * m_coord

mlx/backend/cuda/quantized/qmm/qmm_naive.cuh

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ CUTE_DEVICE void qmm_naive_mainloop(
114114
gB.data() = recast_ptr<Quant>(raw_pointer_cast(gB.data()) + gB.layout()(0, k_residue, 0) * cuda::std::min(8, sizeof_bits_v<Quant>) / 8);
115115
}
116116
gS = domain_offset(make_coord(0, k_residue, 0), gS);
117-
gZ = domain_offset(make_coord(0, k_residue, 0), gZ);
117+
if constexpr (quant_has_bias_v<Quant>) {
118+
gZ = domain_offset(make_coord(0, k_residue, 0), gZ);
119+
}
118120

119121
// Define smem layouts.
120122
auto [sA_layout, sB_layout] = make_smem_layouts(cta_tiler);
@@ -177,8 +179,15 @@ CUTE_DEVICE void qmm_naive_mainloop(
177179
auto fetch_gmem = [&](int tile) {
178180
copy_if(copy_a, tApA, tAgA(_,_,_,tile), tArA);
179181
copy_if(copy_b, tBpB, tBgB(_,_,_,tile), tBrB);
180-
copy(tBgS(_,_,_,tile), tBrS);
181-
copy(tBgZ(_,_,_,tile), tBrZ);
182+
CUTE_UNROLL
183+
for (int n = 0; n < size<1>(tBrS); ++n) {
184+
if (tBpB(n,0)) {
185+
copy(tBgS(_,n,_,tile), tBrS(_,n,_));
186+
if constexpr (quant_has_bias_v<Quant>) {
187+
copy(tBgZ(_,n,_,tile), tBrZ(_,n,_));
188+
}
189+
}
190+
}
182191
};
183192
// RMEM => SMEM.
184193
auto store_smem = [&]() {
@@ -219,8 +228,15 @@ CUTE_DEVICE void qmm_naive_mainloop(
219228
for (int k = 0; k < size<2>(tBrB); ++k) {
220229
if (get<1>(tBcB(0,0,k)) >= -k_residue) {
221230
copy_if(copy_b, tBpB(_,k), tBgB_k(_,_,k), tBrB(_,_,k));
222-
copy(tBgS_k(_,_,k), tBrS(_,_,k));
223-
copy(tBgZ_k(_,_,k), tBrZ(_,_,k));
231+
CUTE_UNROLL
232+
for (int n = 0; n < size<1>(tBrS); ++n) {
233+
if (tBpB(n,k)) {
234+
copy(tBgS_k(_,n,k), tBrS(_,n,k));
235+
if constexpr (quant_has_bias_v<Quant>) {
236+
copy(tBgZ_k(_,n,k), tBrZ(_,n,k));
237+
}
238+
}
239+
}
224240
}
225241
}
226242
} else {

0 commit comments

Comments
 (0)