Skip to content

Commit 7a55d72

Browse files
jeffli-xilinxclaude
andcommitted
RDNA 3.5 MMVQ/fattn optimizations for gfx1151
Add RDNA 3.5 (gfx1151) specific parameter tuning and kernel optimizations for decode throughput on LPDDR5X-based APUs (Radeon 8060S). Key changes: - MMVQ parameter table: add MMVQ_PARAMETERS_RDNA3_5 with nwarps=1 (single wave per block, optimal for wave32 on 40 CU APU) - Bias defusion: run bias-only fused kernels through non-fused template + separate bias-add kernel (24% per-kernel speedup) - Split-K for low-row-count MMVQ: split K-dimension across multiple waves with atomicAdd when waves_per_cu < 80 (improves LPDDR5X BW utilization from 76% to 89%) - Q8_1 cache: avoid redundant activation quantization when the same src1 pointer is reused across fused MMVQ dispatches - RMS norm + quantize fusion: fused kernel combining RMS normalization, weight multiplication, and Q8_1 quantization in a single pass - Flash attention tile configs: add RDNA 3.5 specific tile configurations for head dimensions 72 and 80 Benchmarked on Radeon 8060S (gfx1151, 40 CUs, LPDDR5X): Qwen3.5-9B Q4_0, 128 token decode: 38.1 -> 39.0 t/s (+2.3%) Co-Authored-By: Claude Opus 4 <noreply@anthropic.com>
1 parent cc66d2c commit 7a55d72

6 files changed

Lines changed: 344 additions & 12 deletions

File tree

ggml/src/ggml-cuda/common.cuh

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1499,19 +1499,53 @@ struct ggml_backend_cuda_context {
14991499
ggml_cuda_pool & pool() {
15001500
return pool(device);
15011501
}
1502+
1503+
struct q8_1_cache_entry {
1504+
const void * src1_data = nullptr;
1505+
void * q8_1_buf = nullptr;
1506+
size_t buf_size = 0;
1507+
};
1508+
q8_1_cache_entry q8_1_cache;
1509+
1510+
void * q8_1_cache_get_or_alloc(const void * src1_data, size_t needed_size, bool * cache_hit) {
1511+
if (q8_1_cache.src1_data == src1_data && q8_1_cache.q8_1_buf) {
1512+
*cache_hit = true;
1513+
return q8_1_cache.q8_1_buf;
1514+
}
1515+
if (q8_1_cache.buf_size < needed_size) {
1516+
if (q8_1_cache.q8_1_buf) {
1517+
CUDA_CHECK(cudaFree(q8_1_cache.q8_1_buf));
1518+
}
1519+
CUDA_CHECK(cudaMalloc(&q8_1_cache.q8_1_buf, needed_size));
1520+
q8_1_cache.buf_size = needed_size;
1521+
}
1522+
q8_1_cache.src1_data = src1_data;
1523+
*cache_hit = false;
1524+
return q8_1_cache.q8_1_buf;
1525+
}
1526+
1527+
void q8_1_cache_invalidate() {
1528+
q8_1_cache.src1_data = nullptr;
1529+
}
15021530
};
15031531

15041532
struct ggml_cuda_mm_fusion_args_host {
15051533
const ggml_tensor * x_bias = nullptr;
15061534
const ggml_tensor * gate = nullptr;
15071535
const ggml_tensor * gate_bias = nullptr;
15081536
ggml_glu_op glu_op;
1537+
const ggml_tensor * rms_norm_src = nullptr;
1538+
const ggml_tensor * rms_norm_weights = nullptr;
1539+
float rms_norm_eps = 0.0f;
15091540
};
15101541
struct ggml_cuda_mm_fusion_args_device {
15111542
const void * x_bias = nullptr;
15121543
const void * gate = nullptr;
15131544
const void * gate_bias = nullptr;
15141545
ggml_glu_op glu_op;
1546+
const void * rms_norm_src = nullptr;
1547+
const void * rms_norm_weights = nullptr;
1548+
float rms_norm_eps = 0.0f;
15151549
};
15161550

15171551
struct ggml_cuda_kernel_launch_params {

ggml/src/ggml-cuda/fattn-tile.cuh

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,8 +309,29 @@ static constexpr __host__ __device__ uint32_t ggml_cuda_fattn_tile_get_config_am
309309
return 0;
310310
}
311311

312+
static constexpr __host__ __device__ uint32_t ggml_cuda_fattn_tile_get_config_amd_rdna3_5(const int DKQ, const int DV, const int ncols) {
313+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 72, 72, 2, 64, 4, 64, 72)
314+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 72, 72, 4, 128, 4, 64, 72)
315+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 72, 72, 8, 128, 4, 64, 72)
316+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 72, 72, 16, 128, 4, 64, 72)
317+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 72, 72, 32, 128, 4, 64, 72)
318+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 72, 72, 64, 128, 4, 64, 72)
319+
320+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 80, 80, 2, 64, 4, 64, 80)
321+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 80, 80, 4, 128, 4, 64, 80)
322+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 80, 80, 8, 256, 4, 64, 80)
323+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 80, 80, 16, 256, 4, 64, 80)
324+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 80, 80, 32, 256, 4, 64, 80)
325+
GGML_CUDA_FATTN_TILE_CONFIG_CASE( 80, 80, 64, 256, 4, 64, 80)
326+
327+
return ggml_cuda_fattn_tile_get_config_amd_rdna(DKQ, DV, ncols);
328+
}
329+
312330
static __host__ uint32_t ggml_cuda_fattn_tile_get_config(const int DKQ, const int DV, const int ncols, const int cc) {
313331
if (GGML_CUDA_CC_IS_AMD(cc)) {
332+
if (GGML_CUDA_CC_IS_RDNA3_5(cc)) {
333+
return ggml_cuda_fattn_tile_get_config_amd_rdna3_5(DKQ, DV, ncols);
334+
}
314335
if (GGML_CUDA_CC_IS_RDNA(cc)) {
315336
return ggml_cuda_fattn_tile_get_config_amd_rdna(DKQ, DV, ncols);
316337
}
@@ -324,11 +345,13 @@ static __host__ uint32_t ggml_cuda_fattn_tile_get_config(const int DKQ, const in
324345

325346
static constexpr __device__ uint32_t ggml_cuda_fattn_tile_get_config(const int DKQ, const int DV, const int ncols) {
326347
#ifdef GGML_USE_HIP
327-
#ifdef RDNA
348+
#ifdef RDNA3_5
349+
return ggml_cuda_fattn_tile_get_config_amd_rdna3_5(DKQ, DV, ncols);
350+
#elif defined(RDNA)
328351
return ggml_cuda_fattn_tile_get_config_amd_rdna(DKQ, DV, ncols);
329352
#else
330353
return ggml_cuda_fattn_tile_get_config_amd(DKQ, DV, ncols);
331-
#endif // RDNA
354+
#endif // RDNA3_5
332355
#else
333356
#ifdef FAST_FP16_AVAILABLE
334357
return ggml_cuda_fattn_tile_get_config_nvidia_fp16(DKQ, DV, ncols);

ggml/src/ggml-cuda/ggml-cuda.cu

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4240,6 +4240,36 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
42404240
return 2;
42414241
}
42424242

4243+
// RMS_NORM + MUL + MUL_MAT: fold rms_norm+mul+quantize into a single MMVQ dispatch
4244+
if (ggml_cuda_can_fuse(cgraph, i, { GGML_OP_RMS_NORM, GGML_OP_MUL }, {}) &&
4245+
i + 2 < cgraph->n_nodes &&
4246+
cgraph->nodes[i + 2]->op == GGML_OP_MUL_MAT) {
4247+
4248+
ggml_tensor * rms_node = cgraph->nodes[i];
4249+
ggml_tensor * mul_node = cgraph->nodes[i + 1];
4250+
ggml_tensor * mm_node = cgraph->nodes[i + 2];
4251+
4252+
if (ggml_node_has_n_uses(cgraph, i + 1, 1) &&
4253+
(mm_node->src[1] == mul_node) &&
4254+
ggml_cuda_should_fuse_mul_mat_vec_q(mm_node)) {
4255+
4256+
float eps;
4257+
memcpy(&eps, rms_node->op_params, sizeof(float));
4258+
4259+
const ggml_tensor * mul_weights = (mul_node->src[0] == rms_node)
4260+
? mul_node->src[1] : mul_node->src[0];
4261+
4262+
ggml_cuda_mm_fusion_args_host fusion_data{};
4263+
fusion_data.rms_norm_src = rms_node->src[0];
4264+
fusion_data.rms_norm_weights = mul_weights;
4265+
fusion_data.rms_norm_eps = eps;
4266+
4267+
ggml_cuda_mul_mat_vec_q(*cuda_ctx, mm_node->src[0], mm_node->src[1],
4268+
mm_node->src[2], mm_node, &fusion_data);
4269+
return 2;
4270+
}
4271+
}
4272+
42434273
if (ggml_cuda_can_fuse(cgraph, i, { GGML_OP_RMS_NORM, GGML_OP_MUL }, {})) {
42444274
ggml_cuda_op_rms_norm_fused(*cuda_ctx, node, cgraph->nodes[i + 1]);
42454275
return 1;
@@ -4373,6 +4403,8 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
43734403
stream_ctx.concurrent_events.clear();
43744404
}
43754405

4406+
cuda_ctx->q8_1_cache_invalidate();
4407+
43764408
for (int i = 0; i < cgraph->n_nodes; i++) {
43774409
ggml_tensor * node = cgraph->nodes[i];
43784410
if (is_concurrent_event_active) {

ggml/src/ggml-cuda/mmvq.cu

Lines changed: 172 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,18 @@ enum mmvq_parameter_table_id {
6767
MMVQ_PARAMETERS_GCN,
6868
MMVQ_PARAMETERS_RDNA2,
6969
MMVQ_PARAMETERS_RDNA3_0,
70+
MMVQ_PARAMETERS_RDNA3_5,
7071
MMVQ_PARAMETERS_RDNA4
7172
};
7273

7374
static constexpr __device__ mmvq_parameter_table_id get_device_table_id() {
7475
#if defined(RDNA4)
7576
return MMVQ_PARAMETERS_RDNA4;
76-
#elif defined(RDNA3_0)
77+
#elif defined(RDNA3_5)
78+
return MMVQ_PARAMETERS_RDNA3_5;
79+
#elif defined(RDNA3)
7780
return MMVQ_PARAMETERS_RDNA3_0;
78-
#elif defined(RDNA2) || defined(RDNA3_5)
81+
#elif defined(RDNA2)
7982
return MMVQ_PARAMETERS_RDNA2;
8083
#elif defined(GCN) || defined(CDNA)
8184
return MMVQ_PARAMETERS_GCN;
@@ -90,10 +93,13 @@ static __host__ mmvq_parameter_table_id get_device_table_id(int cc) {
9093
if (GGML_CUDA_CC_IS_RDNA4(cc)) {
9194
return MMVQ_PARAMETERS_RDNA4;
9295
}
96+
if (GGML_CUDA_CC_IS_RDNA3_5(cc)) {
97+
return MMVQ_PARAMETERS_RDNA3_5;
98+
}
9399
if (GGML_CUDA_CC_IS_RDNA3_0(cc)) {
94100
return MMVQ_PARAMETERS_RDNA3_0;
95101
}
96-
if (GGML_CUDA_CC_IS_RDNA2(cc) || GGML_CUDA_CC_IS_RDNA3_5(cc)) {
102+
if (GGML_CUDA_CC_IS_RDNA2(cc)) {
97103
return MMVQ_PARAMETERS_RDNA2;
98104
}
99105
if (GGML_CUDA_CC_IS_GCN(cc) || GGML_CUDA_CC_IS_CDNA(cc)) {
@@ -422,6 +428,9 @@ static constexpr __host__ __device__ int calc_nwarps(ggml_type type, int ncols_d
422428
}
423429
return 1;
424430
}
431+
if (table_id == MMVQ_PARAMETERS_RDNA3_5) {
432+
return 1;
433+
}
425434
if (table_id == MMVQ_PARAMETERS_TURING) {
426435
if (ncols_dst == 1) {
427436
switch (type) {
@@ -674,6 +683,86 @@ static __global__ void mul_mat_vec_q(
674683
}
675684
}
676685

686+
// Zero scattered output locations for split-K.
687+
// Grid: (nrows, nchannels_dst, nsamples) Block: (1)
688+
static __global__ void mmvq_splitk_zero_output(
689+
float * dst, const uint32_t stride_channel_dst, const uint32_t stride_sample_dst) {
690+
dst[blockIdx.z*stride_sample_dst + blockIdx.y*stride_channel_dst + blockIdx.x] = 0.0f;
691+
}
692+
693+
// Add bias to split-K output.
694+
// Grid: (ceil(nrows/256), nchannels_dst, nsamples) Block: (256)
695+
static __global__ void mmvq_splitk_add_bias(
696+
float * dst, const float * bias, const uint32_t nrows,
697+
const uint32_t stride_channel_dst, const uint32_t stride_sample_dst) {
698+
const uint32_t row = blockIdx.x * blockDim.x + threadIdx.x;
699+
if (row >= nrows) {
700+
return;
701+
}
702+
const uint32_t offset = blockIdx.z*stride_sample_dst + blockIdx.y*stride_channel_dst + row;
703+
dst[offset] += bias[offset];
704+
}
705+
706+
// Split-K MMVQ kernel for RDNA 3.5: splits each row's K-dimension across split_k_factor blocks.
707+
// Each block computes a partial dot product and atomicAdds to the output.
708+
// Grid: (nrows, nchannels_dst, split_k_factor * nsamples)
709+
// Block: (warp_size, 1, 1) — single wave, no shared memory reduction.
710+
template <ggml_type type, int split_k_factor>
711+
__launch_bounds__(ggml_cuda_get_physical_warp_size(), 1)
712+
static __global__ void mul_mat_vec_q_splitk(
713+
const void * vx_ptr, const void * vy_ptr, float * dst_ptr,
714+
const uint32_t ncols_x, const uint3 nchannels_y,
715+
const uint32_t stride_row_x, const uint32_t stride_col_y, const uint32_t stride_col_dst,
716+
const uint3 channel_ratio, const uint32_t stride_channel_x,
717+
const uint32_t stride_channel_y, const uint32_t stride_channel_dst,
718+
const uint3 sample_ratio, const uint32_t stride_sample_x,
719+
const uint32_t stride_sample_y, const uint32_t stride_sample_dst) {
720+
const void * GGML_CUDA_RESTRICT vx = vx_ptr;
721+
const void * GGML_CUDA_RESTRICT vy = vy_ptr;
722+
float * GGML_CUDA_RESTRICT dst = dst_ptr;
723+
724+
constexpr int qk = ggml_cuda_type_traits<type>::qk;
725+
constexpr int qi = ggml_cuda_type_traits<type>::qi;
726+
constexpr int vdr = get_vdr_mmvq(type);
727+
constexpr int warp_size = ggml_cuda_get_physical_warp_size();
728+
729+
constexpr vec_dot_q_cuda_t vec_dot_q_cuda = get_vec_dot_q_cuda(type);
730+
731+
const int row0 = blockIdx.x;
732+
const int blocks_per_row_x = ncols_x / qk;
733+
constexpr int blocks_per_iter = vdr * warp_size / qi;
734+
735+
const uint32_t channel_dst = blockIdx.y;
736+
const uint32_t split_chunk = blockIdx.z % split_k_factor;
737+
const uint32_t sample_dst = blockIdx.z / split_k_factor;
738+
739+
const uint32_t channel_x = fastdiv(channel_dst, channel_ratio);
740+
const uint32_t channel_y = channel_dst;
741+
const uint32_t sample_x = fastdiv(sample_dst, sample_ratio);
742+
const uint32_t sample_y = sample_dst;
743+
744+
const int blocks_per_chunk = (blocks_per_row_x + split_k_factor - 1) / split_k_factor;
745+
const int k_start = split_chunk * blocks_per_chunk;
746+
const int k_end = min(k_start + blocks_per_chunk, blocks_per_row_x);
747+
748+
const block_q8_1 * y = ((const block_q8_1 *) vy) + sample_y*stride_sample_y + channel_y*stride_channel_y;
749+
const int kbx_offset = sample_x*stride_sample_x + channel_x*stride_channel_x + row0*stride_row_x;
750+
751+
float tmp = 0.0f;
752+
753+
for (int kbx = k_start + threadIdx.x / (qi/vdr); kbx < k_end; kbx += blocks_per_iter) {
754+
const int kby = kbx * (qk/QK8_1);
755+
const int kqs = vdr * (threadIdx.x % (qi/vdr));
756+
tmp += vec_dot_q_cuda(vx, &y[kby], kbx_offset + kbx, kqs);
757+
}
758+
759+
tmp = warp_reduce_sum<warp_size>(tmp);
760+
761+
if (threadIdx.x == 0) {
762+
atomicAdd(&dst[sample_dst*stride_sample_dst + channel_dst*stride_channel_dst + row0], tmp);
763+
}
764+
}
765+
677766
// Dedicated MoE multi-token kernel.
678767
// Grid: (ceil(nrows_x / c_rows_per_block), nchannels_dst)
679768
// Block: (warp_size, ncols_dst) - each warp handles one token independently.
@@ -890,6 +979,57 @@ static void mul_mat_vec_q_switch_ncols_dst(
890979
case 1: {
891980
constexpr int c_ncols_dst = 1;
892981

982+
// Bias-only defusion for RDNA 3.5: run non-fused kernel + separate bias-add.
983+
// The fused template generates slower code for bias-only cases on RDNA 3.5.
984+
if (table_id == MMVQ_PARAMETERS_RDNA3_5 && has_fusion && fusion.gate == nullptr && fusion.x_bias != nullptr && !has_ids) {
985+
const ggml_cuda_mm_fusion_args_device no_fusion{};
986+
std::pair<dim3, dim3> dims = calc_launch_params<type>(c_ncols_dst, nrows_x, nchannels_dst,
987+
nsamples_dst, warp_size, table_id);
988+
mul_mat_vec_q_switch_fusion<type, c_ncols_dst>(
989+
vx, vy, ids, no_fusion, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
990+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst, sample_ratio_fd,
991+
stride_sample_x, stride_sample_y, stride_sample_dst, dims.first, dims.second, 0, ids_stride,
992+
stream);
993+
994+
const int bias_threads = 256;
995+
const dim3 bias_grid((nrows_x + bias_threads - 1) / bias_threads, nchannels_dst, nsamples_dst);
996+
mmvq_splitk_add_bias<<<bias_grid, bias_threads, 0, stream>>>(
997+
dst, (const float *) fusion.x_bias, nrows_x, stride_channel_dst, stride_sample_dst);
998+
CUDA_CHECK(cudaGetLastError());
999+
break;
1000+
}
1001+
1002+
// Non-fused split-K for RDNA 3.5: increase wave count to hide LPDDR5X latency
1003+
if (table_id == MMVQ_PARAMETERS_RDNA3_5 && !has_fusion && !has_ids) {
1004+
constexpr int qk = ggml_cuda_type_traits<type>::qk;
1005+
const int blocks_per_row = ncols_x / qk;
1006+
const int waves_per_cu = nrows_x / 40;
1007+
if (waves_per_cu < 80 && blocks_per_row >= 4) {
1008+
const int split_k = (waves_per_cu < 40) ? 4 : 2;
1009+
1010+
const dim3 zero_grid(nrows_x, nchannels_dst, nsamples_dst);
1011+
mmvq_splitk_zero_output<<<zero_grid, 1, 0, stream>>>(dst, stride_channel_dst, stride_sample_dst);
1012+
CUDA_CHECK(cudaGetLastError());
1013+
1014+
const dim3 block_nums(nrows_x, nchannels_dst, split_k * nsamples_dst);
1015+
const dim3 block_dims(warp_size, 1, 1);
1016+
const ggml_cuda_kernel_launch_params launch_params(block_nums, block_dims, 0, stream);
1017+
1018+
if (split_k == 4) {
1019+
ggml_cuda_kernel_launch(mul_mat_vec_q_splitk<type, 4>, launch_params,
1020+
vx, vy, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
1021+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
1022+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst);
1023+
} else {
1024+
ggml_cuda_kernel_launch(mul_mat_vec_q_splitk<type, 2>, launch_params,
1025+
vx, vy, dst, ncols_x, nchannels_y_fd, stride_row_x, stride_col_y, stride_col_dst,
1026+
channel_ratio_fd, stride_channel_x, stride_channel_y, stride_channel_dst,
1027+
sample_ratio_fd, stride_sample_x, stride_sample_y, stride_sample_dst);
1028+
}
1029+
break;
1030+
}
1031+
}
1032+
8931033
bool use_small_k = should_use_small_k(c_ncols_dst);
8941034

8951035
if (use_small_k) {
@@ -1183,12 +1323,34 @@ void ggml_cuda_mul_mat_vec_q(
11831323
}
11841324

11851325
const int64_t ne10_padded = GGML_PAD(ne10, MATRIX_ROW_PADDING);
1186-
ggml_cuda_pool_alloc<char> src1_q8_1(ctx.pool(), ne13*ne12 * ne11*ne10_padded * sizeof(block_q8_1)/QK8_1);
1187-
{
1188-
const int64_t s11 = src1->nb[1] / ts_src1;
1189-
const int64_t s12 = src1->nb[2] / ts_src1;
1190-
const int64_t s13 = src1->nb[3] / ts_src1;
1191-
quantize_row_q8_1_cuda(src1_d, nullptr, src1_q8_1.get(), src0->type, ne10, s11, s12, s13, ne10_padded, ne11, ne12, ne13, stream);
1326+
const size_t q8_1_size = ne13*ne12 * ne11*ne10_padded * sizeof(block_q8_1)/QK8_1;
1327+
1328+
bool q8_cache_hit = false;
1329+
void * q8_1_ptr = ctx.q8_1_cache_get_or_alloc(src1->data, q8_1_size, &q8_cache_hit);
1330+
1331+
ggml_cuda_pool_alloc<char> src1_q8_1_pool;
1332+
if (!q8_1_ptr) {
1333+
src1_q8_1_pool.alloc(ctx.pool(), q8_1_size);
1334+
q8_1_ptr = src1_q8_1_pool.get();
1335+
}
1336+
1337+
if (!q8_cache_hit) {
1338+
if (fusion && fusion->rms_norm_src) {
1339+
const ggml_tensor * rms_src = fusion->rms_norm_src;
1340+
const size_t ts_rms = ggml_type_size(rms_src->type);
1341+
const int64_t rs01 = rms_src->nb[1] / ts_rms;
1342+
const int64_t rs02 = rms_src->nb[2] / ts_rms;
1343+
const int64_t rs03 = rms_src->nb[3] / ts_rms;
1344+
quantize_row_q8_1_rms_norm_cuda(
1345+
(const float *)rms_src->data, (const float *)fusion->rms_norm_weights->data,
1346+
q8_1_ptr, fusion->rms_norm_eps,
1347+
ne10, rs01, rs02, rs03, ne10_padded, ne11, ne12, ne13, stream);
1348+
} else {
1349+
const int64_t s11 = src1->nb[1] / ts_src1;
1350+
const int64_t s12 = src1->nb[2] / ts_src1;
1351+
const int64_t s13 = src1->nb[3] / ts_src1;
1352+
quantize_row_q8_1_cuda(src1_d, nullptr, q8_1_ptr, src0->type, ne10, s11, s12, s13, ne10_padded, ne11, ne12, ne13, stream);
1353+
}
11921354
}
11931355

11941356
const int64_t s01 = src0->nb[1] / ts_src0;
@@ -1214,7 +1376,7 @@ void ggml_cuda_mul_mat_vec_q(
12141376
const int64_t ids_stride = ids ? ids->nb[1] / ggml_type_size(ids->type) : 0;
12151377

12161378
mul_mat_vec_q_switch_type(
1217-
src0->data, src0->type, src1_q8_1.get(), ids_d, fusion_local, dst_d, ne00,
1379+
src0->data, src0->type, q8_1_ptr, ids_d, fusion_local, dst_d, ne00,
12181380
ne01, ncols_dst, s01, stride_col_y, stride_col_dst,
12191381
ne02, nchannels_y, nchannels_dst, s02, stride_channel_y, stride_channel_dst,
12201382
ne03, ne3, s03, s13, s3, ids_stride, stream);

0 commit comments

Comments
 (0)