@@ -174,8 +174,6 @@ static constexpr __device__ int get_mmq_y_device() {
174174// in terms of 32 bit elements that means K % 2 == 1 for dp4a or K % 8 == 4 for mma.
175175#define MMQ_TILE_NE_K 32
176176
177- #define MMQ_DP4A_TXS_Q1_0 tile_x_sizes{mmq_y*MMQ_TILE_NE_K + mmq_y, mmq_y*MMQ_TILE_NE_K /QI1_0 + mmq_y/QI1_0 , 0 }
178- #define MMQ_DP4A_TXS_Q1_0_g128 tile_x_sizes{mmq_y*MMQ_TILE_NE_K *4 + mmq_y, mmq_y*MMQ_TILE_NE_K *4 /QI1_0_g128 + mmq_y/(QI1_0_g128/4 ), 0 }
179177#define MMQ_DP4A_TXS_Q4_0 tile_x_sizes{mmq_y*MMQ_TILE_NE_K + mmq_y, mmq_y*MMQ_TILE_NE_K /QI4_0 + mmq_y/QI4_0 , 0 }
180178#define MMQ_DP4A_TXS_Q4_1 tile_x_sizes{mmq_y*MMQ_TILE_NE_K + mmq_y, mmq_y*MMQ_TILE_NE_K /QI4_1 + mmq_y/QI4_1 , 0 }
181179#define MMQ_DP4A_TXS_Q8_0 tile_x_sizes{mmq_y*MMQ_TILE_NE_K *2 + mmq_y, mmq_y*MMQ_TILE_NE_K *2 /QI8_0 + mmq_y/(QI8_0 /2 ), 0 }
@@ -189,8 +187,6 @@ static constexpr __device__ int get_mmq_y_device() {
189187
190188static constexpr __host__ __device__ tile_x_sizes mmq_get_dp4a_tile_x_sizes (ggml_type type, int mmq_y) {
191189 switch (type) {
192- case GGML_TYPE_Q1_0 : return MMQ_DP4A_TXS_Q1_0 ;
193- case GGML_TYPE_Q1_0_g128: return MMQ_DP4A_TXS_Q1_0_g128;
194190 case GGML_TYPE_Q4_0 : return MMQ_DP4A_TXS_Q4_0 ;
195191 case GGML_TYPE_Q4_1 : return MMQ_DP4A_TXS_Q4_1 ;
196192 case GGML_TYPE_Q5_0 : return MMQ_DP4A_TXS_Q8_0 ;
@@ -234,7 +230,7 @@ static_assert(MMQ_MMA_TILE_X_K_FP4 == MMQ_MMA_TILE_X_K_Q8_1, "Wrong tile size fo
234230static constexpr __host__ __device__ int mmq_get_mma_tile_x_k (ggml_type type) {
235231 switch (type) {
236232 case GGML_TYPE_Q1_0 : return MMQ_MMA_TILE_X_K_Q8_0 ;
237- case GGML_TYPE_Q1_0_g128: return MMQ_MMA_TILE_X_K_Q8_0_g128 ;
233+ case GGML_TYPE_Q1_0_g128: return MMQ_MMA_TILE_X_K_Q8_0 ;
238234 case GGML_TYPE_Q4_0 : return MMQ_MMA_TILE_X_K_Q8_0 ;
239235 case GGML_TYPE_Q4_1 : return MMQ_MMA_TILE_X_K_Q8_1 ;
240236 case GGML_TYPE_Q5_0 : return MMQ_MMA_TILE_X_K_Q8_0 ;
@@ -309,20 +305,19 @@ static constexpr __device__ int mmq_get_nwarps_device() {
309305
310306template <int mmq_y, bool need_check> static __device__ __forceinline__ void load_tiles_q1_0 (
311307 const char * __restrict__ x, int * __restrict__ x_tile, const int kbx0, const int i_max, const int stride) {
308+ #if !(defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE))
309+ GGML_UNUSED_VARS (x, x_tile, kbx0, i_max, stride, mmq_y, need_check);
310+ NO_DEVICE_CODE ;
311+ #else
312312 constexpr int nwarps = mmq_get_nwarps_device ();
313313 constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
314314
315- #if defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
316- int * x_qs = (int *) x_tile;
317- float * x_df = (float *) (x_qs + MMQ_TILE_NE_K );
318- #else
319- constexpr tile_x_sizes txs = mmq_get_dp4a_tile_x_sizes (GGML_TYPE_Q1_0 , mmq_y);
320315 int * x_qs = (int *) x_tile;
321- float * x_df = (float *) (x_qs + txs.qs );
322- #endif // defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
323-
324- constexpr int threads_per_row = MMQ_ITER_K_Q1_0 / (4 * QR1_0 );
316+ float * x_df = (float *) (x_qs + 2 *MMQ_TILE_NE_K );
317+ constexpr int blocks_per_iter = MMQ_ITER_K / QK1_0 ;
318+ constexpr int threads_per_row = blocks_per_iter * QI1_0 ;
325319 constexpr int nrows = warp_size / threads_per_row;
320+ constexpr int scale_entries_per_row = blocks_per_iter * (QK1_0 / QK8_1 );
326321 const int txi = threadIdx .x % threads_per_row;
327322 const int kbx = txi / QI1_0 ;
328323
@@ -341,7 +336,6 @@ template <int mmq_y, bool need_check> static __device__ __forceinline__ void loa
341336 // Read all 4 bytes safely to avoid alignment issues
342337 const int qs0 = bxi->qs [0 ] | (bxi->qs [1 ] << 8 ) | (bxi->qs [2 ] << 16 ) | (bxi->qs [3 ] << 24 );
343338
344- #if defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
345339 // For MMA: unpack 1-bit values to signed bytes (-1 or +1)
346340 // Process all 32 bits, 4 at a time
347341 int unpacked_bytes[8 ];
@@ -358,34 +352,98 @@ template <int mmq_y, bool need_check> static __device__ __forceinline__ void loa
358352 // Store unpacked values
359353#pragma unroll
360354 for (int j = 0 ; j < 8 ; ++j) {
361- x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kbx*8 + j] = unpacked_bytes[j];
355+ x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + kbx*QI8_0 + j] = unpacked_bytes[j];
362356 }
363- #else
364- // For DP4A: store raw bits, will unpack in vec_dot
365- x_qs[i*(MMQ_TILE_NE_K + 1 ) + txi] = qs0;
366- #endif // defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
367357 }
368358
369- constexpr int blocks_per_tile_x_row = MMQ_TILE_NE_K / QI1_0 ;
370- constexpr int rows_per_warp = warp_size / blocks_per_tile_x_row;
371- const int kbxd = threadIdx .x % blocks_per_tile_x_row;
359+ constexpr int rows_per_warp = warp_size / scale_entries_per_row;
360+ const int kbxd = threadIdx .x % scale_entries_per_row;
372361
373362#pragma unroll
374363 for (int i0 = 0 ; i0 < mmq_y; i0 += nwarps * rows_per_warp) {
375- int i = i0 + threadIdx .y * rows_per_warp + threadIdx .x / blocks_per_tile_x_row ;
364+ int i = i0 + threadIdx .y * rows_per_warp + threadIdx .x / scale_entries_per_row ;
376365
377366 if (need_check) {
378367 i = min (i, i_max);
379368 }
380369
381370 const block_q1_0 * bxi = (const block_q1_0 *) x + kbx0 + i*stride + kbxd;
382371
383- #if defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
384372 x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + kbxd] = bxi->d ;
385- #else
386- x_df[i*(MMQ_TILE_NE_K /QI1_0 ) + i/QI1_0 + kbxd] = bxi->d ;
373+ }
387374#endif // defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
375+ }
376+
377+ template <int mmq_y, bool need_check> static __device__ __forceinline__ void load_tiles_q1_0_g128 (
378+ const char * __restrict__ x, int * __restrict__ x_tile, const int kbx0, const int i_max, const int stride) {
379+ #if !(defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE))
380+ GGML_UNUSED_VARS (x, x_tile, kbx0, i_max, stride, mmq_y, need_check);
381+ NO_DEVICE_CODE ;
382+ #else
383+ constexpr int nwarps = mmq_get_nwarps_device ();
384+ constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
385+
386+ int * x_qs = (int *) x_tile;
387+ float * x_df = (float *) (x_qs + 2 *MMQ_TILE_NE_K );
388+
389+ constexpr int blocks_per_iter = MMQ_ITER_K / QK1_0_g128;
390+ constexpr int threads_per_row = blocks_per_iter * QI1_0_g128;
391+ constexpr int nrows = warp_size / threads_per_row;
392+ constexpr int scale_entries_per_block = QK1_0_g128 / QK8_1 ;
393+ constexpr int scale_entries_per_row = blocks_per_iter * scale_entries_per_block;
394+
395+ const int txi = threadIdx .x % threads_per_row;
396+ const int kbx = txi / QI1_0_g128;
397+ const int kqsx = txi % QI1_0_g128;
398+
399+ #pragma unroll
400+ for (int i0 = 0 ; i0 < mmq_y; i0 += nrows*nwarps) {
401+ int i = i0 + threadIdx .y *nrows + threadIdx .x /threads_per_row;
402+
403+ if (need_check) {
404+ i = min (i, i_max);
405+ }
406+
407+ const block_q1_0_g128 * bxi = (const block_q1_0_g128 *) x + kbx0 + i*stride + kbx;
408+ const int qs_offset = 4 *kqsx;
409+ const int qs0 = bxi->qs [qs_offset + 0 ] | (bxi->qs [qs_offset + 1 ] << 8 ) |
410+ (bxi->qs [qs_offset + 2 ] << 16 ) | (bxi->qs [qs_offset + 3 ] << 24 );
411+
412+ int unpacked_bytes[8 ];
413+ #pragma unroll
414+ for (int j = 0 ; j < 8 ; ++j) {
415+ const int shift = j * 4 ;
416+ const int bits4 = (qs0 >> shift) & 0x0F ;
417+ const int b0 = (bits4 & 0x01 ) ? 1 : -1 ;
418+ const int b1 = (bits4 & 0x02 ) ? 1 : -1 ;
419+ const int b2 = (bits4 & 0x04 ) ? 1 : -1 ;
420+ const int b3 = (bits4 & 0x08 ) ? 1 : -1 ;
421+ unpacked_bytes[j] = (b0 & 0xFF ) | ((b1 & 0xFF ) << 8 ) | ((b2 & 0xFF ) << 16 ) | ((b3 & 0xFF ) << 24 );
422+ }
423+
424+ const int dst_offset = kbx*(scale_entries_per_block*QI8_0 ) + kqsx*QI8_0 ;
425+ #pragma unroll
426+ for (int j = 0 ; j < 8 ; ++j) {
427+ x_qs[i*MMQ_MMA_TILE_X_K_Q8_0 + dst_offset + j] = unpacked_bytes[j];
428+ }
388429 }
430+
431+ const int ksx = threadIdx .x % scale_entries_per_row;
432+ const int scale_block = ksx / scale_entries_per_block;
433+
434+ #pragma unroll
435+ for (int i0 = 0 ; i0 < mmq_y; i0 += nwarps) {
436+ int i = i0 + threadIdx .y ;
437+
438+ if (need_check) {
439+ i = min (i, i_max);
440+ }
441+
442+ const block_q1_0_g128 * bxi = (const block_q1_0_g128 *) x + kbx0 + i*stride + scale_block;
443+
444+ x_df[i*MMQ_MMA_TILE_X_K_Q8_0 + ksx] = bxi->d ;
445+ }
446+ #endif // defined(AMD_MFMA_AVAILABLE) || defined(TURING_MMA_AVAILABLE)
389447}
390448
391449template <int mmq_y, bool need_check> static __device__ __forceinline__ void load_tiles_q4_0 (
@@ -450,38 +508,12 @@ template <int mmq_y, bool need_check> static __device__ __forceinline__ void loa
450508}
451509
452510template <int mmq_x, int mmq_y>
453- static __device__ __forceinline__ void vec_dot_q1_0_q8_1_dp4a (
511+ static __device__ __forceinline__ void vec_dot_q1_mmq_dp4a_disabled (
454512 const int * __restrict__ x, const int * __restrict__ y, float * __restrict__ sum, const int k00) {
455- constexpr int nwarps = mmq_get_nwarps_device ();
456- constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
457-
458- constexpr tile_x_sizes txs = mmq_get_dp4a_tile_x_sizes (GGML_TYPE_Q1_0 , mmq_y);
459- const int * x_qs = (const int *) x;
460- const float * x_df = (const float *) x_qs + txs.qs ;
461- const int * y_qs = (const int *) y + 4 ;
462- const float * y_df = (const float *) y;
463-
464- // #pragma unroll
465- for (int k01 = 0 ; k01 < MMQ_TILE_NE_K ; k01 += VDR_Q1_0_Q8_1_MMQ ) {
466- const int k0 = k00 + k01;
467-
468- #pragma unroll
469- for (int j0 = 0 ; j0 < mmq_x; j0 += nwarps) {
470- const int j = j0 + threadIdx .y ;
471-
472- #pragma unroll
473- for (int i0 = 0 ; i0 < mmq_y; i0 += warp_size) {
474- const int i = i0 + threadIdx .x ;
475-
476- // For MMQ, we have separate float scales, need to combine them into half2 format
477- const half2 ds8 = __floats2half2_rn (y_df[j*MMQ_TILE_Y_K + (k0/QI8_1 ) % (MMQ_TILE_NE_K /QI8_1 )], 0 .0f );
478-
479- sum[j0/nwarps*mmq_y/warp_size + i0/warp_size] += vec_dot_q1_0_q8_1_impl<VDR_Q1_0_Q8_1_MMQ >
480- (&x_qs[i*(MMQ_TILE_NE_K + 1 ) + k0], &y_qs[j*MMQ_TILE_Y_K + k0 % MMQ_TILE_NE_K ],
481- x_df[i*(MMQ_TILE_NE_K /QI1_0 ) + i/QI1_0 + k0/QI1_0 ], ds8);
482- }
483- }
484- }
513+ // Q1_0 and Q1_0_g128 intentionally target the MMA path only on this branch.
514+ // If DP4A support is needed later for older GPUs, it should be reintroduced and validated separately.
515+ GGML_UNUSED_VARS (x, y, sum, k00, mmq_x, mmq_y);
516+ NO_DEVICE_CODE ;
485517}
486518
487519template <int mmq_x, int mmq_y>
@@ -3341,7 +3373,16 @@ struct mmq_type_traits<mmq_x, mmq_y, need_check, GGML_TYPE_Q1_0> {
33413373 static constexpr int vdr = VDR_Q1_0_Q8_1_MMQ ;
33423374 static constexpr load_tiles_mmq_t load_tiles = load_tiles_q1_0<mmq_y, need_check>;
33433375 static constexpr vec_dot_mmq_t vec_dot_mma = vec_dot_q8_0_q8_1_mma<mmq_x, mmq_y, MMQ_Q8_1_DS_LAYOUT_D4 >;
3344- static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q1_0_q8_1_dp4a<mmq_x, mmq_y>;
3376+ static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q1_mmq_dp4a_disabled<mmq_x, mmq_y>;
3377+ };
3378+
3379+ template <int mmq_x, int mmq_y, bool need_check>
3380+ struct mmq_type_traits <mmq_x, mmq_y, need_check, GGML_TYPE_Q1_0_g128> {
3381+ static constexpr int vdr = VDR_Q1_0_g128_Q8_1_MMQ;
3382+ static constexpr load_tiles_mmq_t load_tiles = load_tiles_q1_0_g128<mmq_y, need_check>;
3383+ static constexpr vec_dot_mmq_t vec_dot_mma = vec_dot_q8_0_q8_1_mma<mmq_x, mmq_y, MMQ_Q8_1_DS_LAYOUT_D4 >;
3384+ // The DP4A path is intentionally disabled; keep the MMA path as the validated route.
3385+ static constexpr vec_dot_mmq_t vec_dot_dp4a = vec_dot_q1_mmq_dp4a_disabled<mmq_x, mmq_y>;
33453386};
33463387
33473388template <int mmq_x, int mmq_y, bool need_check>
@@ -4199,8 +4240,8 @@ void mul_mat_q_case(ggml_backend_cuda_context & ctx, const mmq_args & args, cuda
41994240#define DECL_MMQ_CASE (type ) \
42004241 template void mul_mat_q_case<type>(ggml_backend_cuda_context & ctx, const mmq_args & args, cudaStream_t stream) \
42014242
4202- // extern DECL_MMQ_CASE(GGML_TYPE_Q1_0); // disabled, cuBLAS fallback used
4203- // extern DECL_MMQ_CASE(GGML_TYPE_Q1_0_g128); // disabled, cuBLAS fallback used
4243+ extern DECL_MMQ_CASE (GGML_TYPE_Q1_0 );
4244+ extern DECL_MMQ_CASE (GGML_TYPE_Q1_0_g128);
42044245extern DECL_MMQ_CASE (GGML_TYPE_Q4_0 );
42054246extern DECL_MMQ_CASE (GGML_TYPE_Q4_1 );
42064247extern DECL_MMQ_CASE (GGML_TYPE_Q5_0 );
0 commit comments