@@ -1012,6 +1012,166 @@ static __device__ __forceinline__ void ggml_cuda_mmq_store_tiles_q4_K_rdna35(
10121012 const uint8_t * m8 = (const uint8_t *) &m32;
10131013 const half2 dm = dm_cache * make_half2 (1 .0f , -1 .0f );
10141014
1015+ #pragma unroll
1016+ for (int l = 0 ; l < int (sizeof (int )); ++l) {
1017+ x_dm[i*sram_stride + sizeof (int )*ksc + l] = dm*make_half2 (sc8[l], m8[l]);
1018+ }
1019+ }
1020+
1021+ template <ggml_type type, int J, bool fallback>
1022+ static __device__ __forceinline__ void ggml_cuda_mmq_load_tiles_q5_K_rdna35 (
1023+ const char * __restrict__ x, int * __restrict__ x_tile, const int kbx0, const int i_max, const int stride) {
1024+ constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
1025+ constexpr int nthreads = ggml_cuda_mmq_get_nthreads (type, J, fallback);
1026+ constexpr int I = ggml_cuda_mmq_get_I (type, J, fallback);
1027+ constexpr int sram_stride = ggml_cuda_mmq_get_sram_stride (type, J, fallback);
1028+ static_assert (warp_size == 32 && nthreads == 128 && I == 64 , " unexpected RDNA3.5 Q5_K MMQ configuration" );
1029+
1030+ int * x_qs = (int *) x_tile;
1031+ half2 * x_dm = (half2 *) (x_qs + 2 *MMQ_TILE_NE_K );
1032+
1033+ const int linear_tid = threadIdx .y *warp_size + threadIdx .x ;
1034+ int i = linear_tid/2 ;
1035+ if (fallback) {
1036+ i = min (i, i_max);
1037+ }
1038+
1039+ const block_q5_K * bxi = (const block_q5_K *) x + kbx0 + i*stride;
1040+ const int * scales = (const int *) bxi->scales ;
1041+ const int ksc = linear_tid % 2 ;
1042+ const int sc32 = unpack_scales_q45_K (scales, ksc);
1043+ const int m32 = unpack_scales_q45_K (scales, ksc + 2 );
1044+ const uint8_t * sc8 = (const uint8_t *) &sc32;
1045+ const uint8_t * m8 = (const uint8_t *) &m32;
1046+ const half2 dm = bxi->dm * make_half2 (1 .0f , -1 .0f );
1047+
1048+ #pragma unroll
1049+ for (int l = 0 ; l < int (sizeof (int )); ++l) {
1050+ x_dm[i*sram_stride + sizeof (int )*ksc + l] = dm*make_half2 (sc8[l], m8[l]);
1051+ }
1052+
1053+ const int txi = threadIdx .x ;
1054+ const int kqs = 16 *(txi/8 ) + txi%8 ;
1055+ const int qh_shift0 = 2 *(txi/8 );
1056+
1057+ #pragma unroll
1058+ for (int i0 = 0 ; i0 < I; i0 += nthreads/warp_size) {
1059+ int row = i0 + threadIdx .y ;
1060+ if (fallback) {
1061+ row = min (row, i_max);
1062+ }
1063+
1064+ const block_q5_K * bxq = (const block_q5_K *) x + kbx0 + row*stride;
1065+ const int qs = ((const int *) bxq->qs )[txi];
1066+ const int qh = ((const int *) bxq->qh )[txi % (QI5_K /4 )];
1067+ int * row_qs = x_qs + row*sram_stride;
1068+ row_qs[kqs] = (qs & 0x0F0F0F0F ) | (((qh >> (qh_shift0 + 0 )) << 4 ) & 0x10101010 );
1069+ row_qs[kqs+8 ] = ((qs >> 4 ) & 0x0F0F0F0F ) | (((qh >> (qh_shift0 + 1 )) << 4 ) & 0x10101010 );
1070+ }
1071+ }
1072+
1073+ template <ggml_type type, int J, bool fallback>
1074+ static __device__ __forceinline__ void ggml_cuda_mmq_prefetch_tiles_q5_K_rdna35 (
1075+ const char * __restrict__ x, const int kbx0, const int i_max, const int stride,
1076+ int (&qs_cache)[ggml_cuda_mmq_get_I(type, J, fallback)/
1077+ (ggml_cuda_mmq_get_nthreads(type, J, fallback)/ggml_cuda_get_physical_warp_size())],
1078+ int (&qh_cache)[ggml_cuda_mmq_get_I(type, J, fallback)*(QI5_K /4 )/
1079+ ggml_cuda_mmq_get_nthreads(type, J, fallback)],
1080+ int (&scales_cache)[3], half2 & dm_cache) {
1081+ constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
1082+ constexpr int nthreads = ggml_cuda_mmq_get_nthreads (type, J, fallback);
1083+ constexpr int nwarps = nthreads / warp_size;
1084+ constexpr int I = ggml_cuda_mmq_get_I (type, J, fallback);
1085+ constexpr int qh_words_per_row = QI5_K /4 ;
1086+ constexpr int qh_cache_size = I*qh_words_per_row/nthreads;
1087+ constexpr int rows_per_warp = I/nwarps;
1088+ static_assert (warp_size == 32 && nthreads == 128 && I == 64 , " unexpected RDNA3.5 Q5_K MMQ configuration" );
1089+ static_assert (qh_cache_size*warp_size == rows_per_warp*qh_words_per_row,
1090+ " Q5_K high bits must be distributed evenly across the warp" );
1091+
1092+ #pragma unroll
1093+ for (int i0 = 0 ; i0 < I; i0 += nwarps) {
1094+ int i = i0 + threadIdx .y ;
1095+ if constexpr (fallback) {
1096+ i = min (i, i_max);
1097+ }
1098+
1099+ const block_q5_K * bxi = (const block_q5_K *) x + kbx0 + i*stride;
1100+ qs_cache[i0/nwarps] = ((const int *) bxi->qs )[threadIdx .x ];
1101+ }
1102+
1103+ #pragma unroll
1104+ for (int l = 0 ; l < qh_cache_size; ++l) {
1105+ const int qh_linear = l*warp_size + threadIdx .x ;
1106+ int i = (qh_linear/qh_words_per_row)*nwarps + threadIdx .y ;
1107+ if constexpr (fallback) {
1108+ i = min (i, i_max);
1109+ }
1110+
1111+ const block_q5_K * bxi = (const block_q5_K *) x + kbx0 + i*stride;
1112+ qh_cache[l] = ((const int *) bxi->qh )[qh_linear % qh_words_per_row];
1113+ }
1114+
1115+ int i = (threadIdx .y *warp_size + threadIdx .x )/2 ;
1116+ if constexpr (fallback) {
1117+ i = min (i, i_max);
1118+ }
1119+
1120+ const block_q5_K * bxi = (const block_q5_K *) x + kbx0 + i*stride;
1121+ #pragma unroll
1122+ for (int l = 0 ; l < 3 ; ++l) {
1123+ scales_cache[l] = ((const int *) bxi->scales )[l];
1124+ }
1125+ dm_cache = bxi->dm ;
1126+
1127+ asm volatile (" " ::: " memory" );
1128+ }
1129+
1130+ template <ggml_type type, int J, bool fallback>
1131+ static __device__ __forceinline__ void ggml_cuda_mmq_store_tiles_q5_K_rdna35 (
1132+ int * __restrict__ x_tile,
1133+ const int (&qs_cache)[ggml_cuda_mmq_get_I(type, J, fallback)/
1134+ (ggml_cuda_mmq_get_nthreads(type, J, fallback)/ggml_cuda_get_physical_warp_size())],
1135+ const int (&qh_cache)[ggml_cuda_mmq_get_I(type, J, fallback)*(QI5_K /4 )/
1136+ ggml_cuda_mmq_get_nthreads(type, J, fallback)],
1137+ const int (&scales_cache)[3], const half2 dm_cache) {
1138+ constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
1139+ constexpr int nthreads = ggml_cuda_mmq_get_nthreads (type, J, fallback);
1140+ constexpr int nwarps = nthreads / warp_size;
1141+ constexpr int I = ggml_cuda_mmq_get_I (type, J, fallback);
1142+ constexpr int sram_stride = ggml_cuda_mmq_get_sram_stride (type, J, fallback);
1143+ constexpr int qh_words_per_row = QI5_K /4 ;
1144+ constexpr int qh_rows_per_slot = warp_size/qh_words_per_row;
1145+ static_assert (warp_size == 32 && nthreads == 128 && I == 64 , " unexpected RDNA3.5 Q5_K MMQ configuration" );
1146+
1147+ int * x_qs = x_tile;
1148+ const int txi = threadIdx .x ;
1149+ const int kqs = 16 *(txi/8 ) + txi%8 ;
1150+ const int qh_shift0 = 2 *(txi/8 );
1151+
1152+ #pragma unroll
1153+ for (int i0 = 0 ; i0 < I; i0 += nwarps) {
1154+ const int row_in_warp = i0/nwarps;
1155+ const int qh_slot = row_in_warp/qh_rows_per_slot;
1156+ const int qh_src_lane = (row_in_warp % qh_rows_per_slot)*qh_words_per_row + txi%qh_words_per_row;
1157+ const int qs = qs_cache[row_in_warp];
1158+ const int qh = __shfl_sync (0xFFFFFFFF , qh_cache[qh_slot], qh_src_lane, warp_size);
1159+ const int i = i0 + threadIdx .y ;
1160+ int * row_qs = x_qs + i*sram_stride;
1161+ row_qs[kqs] = (qs & 0x0F0F0F0F ) | (((qh >> (qh_shift0 + 0 )) << 4 ) & 0x10101010 );
1162+ row_qs[kqs+8 ] = ((qs >> 4 ) & 0x0F0F0F0F ) | (((qh >> (qh_shift0 + 1 )) << 4 ) & 0x10101010 );
1163+ }
1164+
1165+ half2 * x_dm = (half2 *) (x_qs + 2 *MMQ_TILE_NE_K );
1166+ const int linear_tid = threadIdx .y *warp_size + threadIdx .x ;
1167+ const int i = linear_tid/2 ;
1168+ const int ksc = linear_tid%2 ;
1169+ const int sc32 = unpack_scales_q45_K (scales_cache, ksc);
1170+ const int m32 = unpack_scales_q45_K (scales_cache, ksc + 2 );
1171+ const uint8_t * sc8 = (const uint8_t *) &sc32;
1172+ const uint8_t * m8 = (const uint8_t *) &m32;
1173+ const half2 dm = dm_cache * make_half2 (1 .0f , -1 .0f );
1174+
10151175#pragma unroll
10161176 for (int l = 0 ; l < int (sizeof (int )); ++l) {
10171177 x_dm[i*sram_stride + sizeof (int )*ksc + l] = dm*make_half2 (sc8[l], m8[l]);
@@ -1137,6 +1297,11 @@ template <ggml_type type, int J, bool fallback> static __device__ __forceinline_
11371297
11381298template <ggml_type type, int J, bool fallback> static __device__ __forceinline__ void ggml_cuda_mmq_load_tiles_q5_K (
11391299 const char * __restrict__ x, int * __restrict__ x_tile, const int kbx0, const int i_max, const int stride) {
1300+ #if defined(RDNA3_5)
1301+ ggml_cuda_mmq_load_tiles_q5_K_rdna35<type, J, fallback>(x, x_tile, kbx0, i_max, stride);
1302+ return ;
1303+ #endif
1304+
11401305 constexpr int warp_size = ggml_cuda_get_physical_warp_size ();
11411306 constexpr int nwarps = ggml_cuda_mmq_get_nthreads (type, J, fallback) / warp_size;
11421307 constexpr int I = ggml_cuda_mmq_get_I (type, J, fallback);
0 commit comments