Skip to content

Commit 9d9efea

Browse files
authored
cuda: warp-per-row PTQ1_0 mat-vec for MUL_MAT_ID when K <= 4096 (#415)
The generic loop strides the 128-weight blocks over all threads of the CTA, so at K <= 4096 (<= 32 blocks per row) only the first warp loads. Give each warp its own row and let the lanes stride the blocks, with the same per-row accumulation order and epilogue, so outputs are unchanged.
1 parent 340befd commit 9d9efea

1 file changed

Lines changed: 70 additions & 0 deletions

File tree

‎ggml/src/ggml-cuda/mmvq.cu‎

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,76 @@ static __global__ void mul_mat_vec_q(
789789
}
790790
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
791791

792+
// PTQ1_0 MoE (ids), one column, K small enough for one block per lane: the generic loop below puts one
793+
// 128-weight block on each thread of the whole CTA, so with K <= 4096 only warp 0 loads while warps 1..3 idle.
794+
// Warp-per-row instead: warp w owns row row0+w and its lanes read that row's blocks (planar PT layout).
795+
// With at most 32 blocks per row every lane holds one block and the lane sums then go through the same
796+
// warp_reduce_sum butterfly as the generic path, so the result is unchanged.
797+
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
798+
if constexpr (small_k && type == GGML_TYPE_PTQ1_0 && ncols_dst == 1 && !y_soa && nwarps > 1 && rows_per_cuda_block == nwarps) {
799+
if (ids != nullptr && blocks_per_row_x <= warp_size) {
800+
const int warp = threadIdx.y;
801+
const int lane = threadIdx.x;
802+
const bool row_ok = uint32_t(row0 + warp) < nrows_dst;
803+
804+
float acc = 0.0f;
805+
float acc_gate = 0.0f;
806+
if (row_ok && lane < blocks_per_row_x) {
807+
const int nblk = ptq1_0_pt_nblk(ncols_x);
808+
const char * ycol[1] = { (const char *) y };
809+
const block_ptq1_0 * bq[1] = { (const block_ptq1_0 *) vx + kbx_offset + warp*stride_row_x + lane };
810+
float dots[1][1];
811+
ptq1_0_pt_block_dot<1, 1>(bq, ycol, lane, nblk, dots);
812+
acc += dots[0][0];
813+
if constexpr (has_fusion && has_gate) {
814+
const block_ptq1_0 * bg[1] = { (const block_ptq1_0 *) vgate + kbx_offset + warp*stride_row_x + lane };
815+
ptq1_0_pt_block_dot<1, 1>(bg, ycol, lane, nblk, dots);
816+
acc_gate += dots[0][0];
817+
}
818+
}
819+
acc = warp_reduce_sum<warp_size>(acc);
820+
if constexpr (has_fusion && has_gate) {
821+
acc_gate = warp_reduce_sum<warp_size>(acc_gate);
822+
}
823+
if (lane == 0 && row_ok) {
824+
float * dst_row = dst + sample_dst*stride_sample_dst + channel_dst*stride_channel_dst + row0 + warp;
825+
[[maybe_unused]] const uint32_t channel_bias = ids ? channel_x : channel_dst;
826+
[[maybe_unused]] const int64_t bias_off = sample_dst*stride_sample_dst + channel_bias*stride_channel_dst + row0 + warp;
827+
float result = acc;
828+
if constexpr (has_fusion) {
829+
if (use_bias) {
830+
result += ((const float *) fusion.x_bias)[bias_off];
831+
}
832+
if constexpr (has_gate) {
833+
float gate_value = acc_gate;
834+
if (use_gate_bias) {
835+
gate_value += ((const float *) fusion.gate_bias)[bias_off];
836+
}
837+
switch (active_glu) {
838+
case GGML_GLU_OP_SWIGLU:
839+
result *= ggml_cuda_op_silu_single(gate_value);
840+
break;
841+
case GGML_GLU_OP_GEGLU:
842+
result *= ggml_cuda_op_gelu_single(gate_value);
843+
break;
844+
case GGML_GLU_OP_SWIGLU_OAI:
845+
result = ggml_cuda_op_swiglu_oai_single(gate_value, result);
846+
break;
847+
default:
848+
result = result * gate_value;
849+
break;
850+
}
851+
}
852+
}
853+
dst_row[0] = result;
854+
}
855+
GGML_UNUSED_VARS(use_gate, use_scale, use_gate_scale, gate_bias, x_bias, x_scale, gate_scale, x_scales,
856+
gate_scales, x_biases, gate_biases, tmp, tmp_gate, vec_dot_q_cuda, blocks_per_iter);
857+
return;
858+
}
859+
}
860+
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
861+
792862
if constexpr ((type == GGML_TYPE_Q1_0 || type == GGML_TYPE_Q2_0 || type == GGML_TYPE_PQ2_0) &&
793863
table_id == MMVQ_PARAMETERS_GB10) {
794864
using block_t = std::conditional_t<type == GGML_TYPE_Q1_0, block_q1_0,

0 commit comments

Comments
 (0)