@@ -1026,6 +1026,53 @@ static __global__ void k_turbo_fwht_forward(
10261026 }
10271027}
10281028
1029+ static inline bool ggml_cuda_fattn_is_classic_non_q8_type (const ggml_type type) {
1030+ return type == GGML_TYPE_BF16 ||
1031+ type == GGML_TYPE_Q4_0 ||
1032+ type == GGML_TYPE_Q4_1 ||
1033+ type == GGML_TYPE_Q5_0 ||
1034+ type == GGML_TYPE_Q5_1 ||
1035+ type == GGML_TYPE_Q6_0 ||
1036+ type == GGML_TYPE_Q6_1 ||
1037+ type == GGML_TYPE_Q3_0 ||
1038+ type == GGML_TYPE_Q3_1 ||
1039+ type == GGML_TYPE_Q2_0 ||
1040+ type == GGML_TYPE_Q2_1 ;
1041+ }
1042+
1043+ static void ggml_cuda_fattn_materialize_to_f16 (
1044+ const ggml_tensor * src, half * dst, cudaStream_t stream, ggml_tensor & src_f16) {
1045+ const size_t bs = ggml_blck_size (src->type );
1046+ const size_t ts = ggml_type_size (src->type );
1047+
1048+ src_f16 = *src;
1049+ src_f16.type = GGML_TYPE_F16 ;
1050+ src_f16.data = dst;
1051+ src_f16.nb [0 ] = sizeof (half);
1052+
1053+ if (ggml_is_contiguously_allocated (src)) {
1054+ const to_fp16_cuda_t to_fp16 = ggml_get_to_fp16_cuda (src->type );
1055+ GGML_ASSERT (to_fp16 != nullptr );
1056+ to_fp16 (src->data , dst, ggml_nelements (src), stream);
1057+
1058+ src_f16.nb [1 ] = src->nb [1 ] * bs * sizeof (half) / ts;
1059+ src_f16.nb [2 ] = src->nb [2 ] * bs * sizeof (half) / ts;
1060+ src_f16.nb [3 ] = src->nb [3 ] * bs * sizeof (half) / ts;
1061+ } else {
1062+ GGML_ASSERT (src->nb [0 ] == ts);
1063+ const to_fp16_nc_cuda_t to_fp16 = ggml_get_to_fp16_nc_cuda (src->type );
1064+ GGML_ASSERT (to_fp16 != nullptr );
1065+ const int64_t s01 = src->nb [1 ] / ts;
1066+ const int64_t s02 = src->nb [2 ] / ts;
1067+ const int64_t s03 = src->nb [3 ] / ts;
1068+ to_fp16 (src->data , dst, src->ne [0 ], src->ne [1 ], src->ne [2 ], src->ne [3 ], s01, s02, s03, stream);
1069+
1070+ src_f16.nb [1 ] = src->ne [0 ] * sizeof (half);
1071+ src_f16.nb [2 ] = src->ne [1 ] * src_f16.nb [1 ];
1072+ src_f16.nb [3 ] = src->ne [2 ] * src_f16.nb [2 ];
1073+ }
1074+ }
1075+
10291076static void ggml_cuda_turbo_prefill_attend (ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
10301077 load_tcq_decode_alpha (ctx.device );
10311078 cudaStream_t stream = ctx.stream ();
@@ -1034,12 +1081,17 @@ static void ggml_cuda_turbo_prefill_attend(ggml_backend_cuda_context & ctx, ggml
10341081
10351082 const bool turbo_k = K->type == GGML_TYPE_TURBO2_0 || K->type == GGML_TYPE_TURBO3_0 || K->type == GGML_TYPE_TURBO4_0 || K->type == GGML_TYPE_TURBO4_TCQ || K->type == GGML_TYPE_TURBO3_TCQ || K->type == GGML_TYPE_TURBO2_TCQ ;
10361083 const bool turbo_v = V->type == GGML_TYPE_TURBO2_0 || V->type == GGML_TYPE_TURBO3_0 || V->type == GGML_TYPE_TURBO4_0 || V->type == GGML_TYPE_TURBO4_TCQ || V->type == GGML_TYPE_TURBO3_TCQ || V->type == GGML_TYPE_TURBO2_TCQ ;
1084+ const bool classic_non_q8_v = !turbo_v && ggml_cuda_fattn_is_classic_non_q8_type (V->type );
10371085
10381086 int device;
10391087 CUDA_CHECK (cudaGetDevice (&device));
10401088
10411089 half * k_fp16 = nullptr ;
10421090 half * v_fp16 = nullptr ;
1091+ bool v_f16_layout_set = false ;
1092+
1093+ ggml_tensor K_f16 = *K;
1094+ ggml_tensor V_f16 = *V;
10431095
10441096 // Allocate and dequant K to fp16 (turbo2, turbo3, or turbo4)
10451097 if (turbo_k) {
@@ -1115,8 +1167,8 @@ static void ggml_cuda_turbo_prefill_attend(ggml_backend_cuda_context & ctx, ggml
11151167 }
11161168 }
11171169
1118- // Allocate and dequant V to fp16 (turbo2, turbo3, or turbo4)
1119- if (turbo_v) {
1170+ // Allocate and materialize V to fp16 (turbo2, turbo3, turbo4, or classic non-q8).
1171+ if (turbo_v || classic_non_q8_v ) {
11201172 // Size for full cache (kv_size from root) so we never realloc mid-session.
11211173 const ggml_tensor * v_root = V;
11221174 while (v_root->view_src ) v_root = v_root->view_src ;
@@ -1182,16 +1234,15 @@ static void ggml_cuda_turbo_prefill_attend(ggml_backend_cuda_context & ctx, ggml
11821234 }
11831235 k_turbo2_tcq_dequant_f16<<<grid_v, V->ne[0 ], 0 , stream>>> (
11841236 (const char *)V->data , v_fp16, V->ne [0 ], V->ne [1 ], V->ne [2 ], V->nb [1 ], V->nb [2 ], V->nb [3 ], tcq_compute_alpha_v (V->type , V->ne [1 ]));
1185- } else {
1237+ } else if (V-> type == GGML_TYPE_TURBO4_0 ) {
11861238 k_turbo4_dequant_f16<<<grid_v, V->ne[0 ], 0 , stream>>> (
11871239 (const char *)V->data , v_fp16, V->ne [0 ], V->ne [1 ], V->ne [2 ], V->nb [1 ], V->nb [2 ], V->nb [3 ]);
1240+ } else {
1241+ ggml_cuda_fattn_materialize_to_f16 (V, v_fp16, stream, V_f16);
1242+ v_f16_layout_set = true ;
11881243 }
11891244 }
11901245
1191- // Create fp16 tensor copies on stack
1192- ggml_tensor K_f16 = *K;
1193- ggml_tensor V_f16 = *V;
1194-
11951246 if (k_fp16) {
11961247 K_f16.type = GGML_TYPE_F16 ;
11971248 K_f16.data = k_fp16;
@@ -1201,7 +1252,7 @@ static void ggml_cuda_turbo_prefill_attend(ggml_backend_cuda_context & ctx, ggml
12011252 K_f16.nb [3 ] = K->ne [0 ] * K->ne [1 ] * K->ne [2 ] * sizeof (half);
12021253 }
12031254
1204- if (v_fp16) {
1255+ if (v_fp16 && !v_f16_layout_set ) {
12051256 V_f16.type = GGML_TYPE_F16 ;
12061257 V_f16.data = v_fp16;
12071258 V_f16.nb [0 ] = sizeof (half);
@@ -1380,18 +1431,21 @@ static inline bool ggml_cuda_fattn_pair_compiled(const ggml_type type_K_in, cons
13801431#endif
13811432}
13821433
1383- static inline bool ggml_cuda_fattn_is_classic_non_q8_type (const ggml_type type) {
1384- return type == GGML_TYPE_BF16 ||
1385- type == GGML_TYPE_Q4_0 ||
1386- type == GGML_TYPE_Q4_1 ||
1387- type == GGML_TYPE_Q5_0 ||
1388- type == GGML_TYPE_Q5_1 ||
1389- type == GGML_TYPE_Q6_0 ||
1390- type == GGML_TYPE_Q6_1 ||
1391- type == GGML_TYPE_Q3_0 ||
1392- type == GGML_TYPE_Q3_1 ||
1393- type == GGML_TYPE_Q2_0 ||
1394- type == GGML_TYPE_Q2_1 ;
1434+ static inline bool ggml_cuda_fattn_prefers_native_vec_for_turbo_k_classic_v (
1435+ const ggml_tensor * Q, const ggml_tensor * K, const ggml_tensor * V) {
1436+ return ggml_cuda_fattn_is_turbo_kv_type (K->type ) &&
1437+ !ggml_cuda_fattn_is_turbo_kv_type (V->type ) &&
1438+ ggml_cuda_fattn_is_classic_non_q8_type (V->type ) &&
1439+ Q->ne [0 ] <= 512 &&
1440+ Q->ne [0 ] % 64 == 0 &&
1441+ ggml_cuda_fattn_pair_compiled (K->type , V->type );
1442+ }
1443+
1444+ static inline bool ggml_cuda_fattn_prefill_mma_can_materialize_turbo_k_classic_v (
1445+ const ggml_tensor * K, const ggml_tensor * V) {
1446+ return ggml_cuda_fattn_is_turbo_kv_type (K->type ) &&
1447+ !ggml_cuda_fattn_is_turbo_kv_type (V->type ) &&
1448+ ggml_cuda_fattn_is_classic_non_q8_type (V->type );
13951449}
13961450
13971451// Shape guard for the effective K/V pair after Turbo V decode-dequant.
@@ -2317,6 +2371,8 @@ static ggml_cuda_fattn_route_plan ggml_cuda_fattn_make_route_plan(const int devi
23172371#endif
23182372
23192373 const bool turbo_decode_native = getenv (" GGML_TURBO_DECODE_NATIVE" ) != nullptr ;
2374+ const bool prefer_native_vec =
2375+ ggml_cuda_fattn_prefers_native_vec_for_turbo_k_classic_v (Q, K, V);
23202376
23212377 const bool turbo_k_only = ggml_cuda_fattn_is_turbo_kv_type (K->type );
23222378 const bool turbo_v_only = ggml_cuda_fattn_is_turbo_kv_type (V->type );
@@ -2327,6 +2383,8 @@ static ggml_cuda_fattn_route_plan ggml_cuda_fattn_make_route_plan(const int devi
23272383 !turbo_k_only;
23282384
23292385 // Decode-dequant policy:
2386+ // - Compiled Turbo K + classic non-q8 V fallback routes stay native vec
2387+ // instead of taking generic f16 materialization after Turbo K decode.
23302388 // - D <= 256: Turbo K/V sides may be decoded to f16.
23312389 // - D = 512: f16/q8_0/Turbo pairs keep the existing f16 route.
23322390 // - D = 512 classic non-q8 K + Turbo V decodes Turbo V to f16 and keeps
@@ -2340,6 +2398,7 @@ static ggml_cuda_fattn_route_plan ggml_cuda_fattn_make_route_plan(const int devi
23402398 plan.decode_dequant =
23412399 !hip_native_tcq_decode &&
23422400 !turbo_decode_native &&
2401+ !prefer_native_vec &&
23432402 turbo_kv &&
23442403 (Q->ne [0 ] <= 256 ||
23452404 (Q->ne [0 ] <= 512 && k_f16_q8_or_turbo && v_f16_q8_or_turbo) ||
@@ -2425,6 +2484,7 @@ static ggml_cuda_fattn_route_plan ggml_cuda_fattn_make_route_plan(const int devi
24252484 " Kshape=[%lld,%lld,%lld,%lld] Vshape=[%lld,%lld,%lld,%lld] "
24262485 " Keff=%s Veff=%s "
24272486 " turbo_kv=%d "
2487+ " prefer_native_vec=%d "
24282488 " decode=%d dk=%d dv=%d "
24292489 " unsafe_vec_after_turbo_v_decode=%d allow_vec=%d "
24302490 " kernel=%s "
@@ -2438,6 +2498,7 @@ static ggml_cuda_fattn_route_plan ggml_cuda_fattn_make_route_plan(const int devi
24382498 (long long ) V->ne [0 ], (long long ) V->ne [1 ], (long long ) V->ne [2 ], (long long ) V->ne [3 ],
24392499 ggml_type_name (plan.effective_type_K ), ggml_type_name (plan.effective_type_V ),
24402500 (int ) turbo_kv,
2501+ (int ) prefer_native_vec,
24412502 (int ) plan.decode_dequant ,
24422503 (int ) plan.decode_dequant_K ,
24432504 (int ) plan.decode_dequant_V ,
@@ -2588,12 +2649,19 @@ void ggml_cuda_flash_attn_ext(ggml_backend_cuda_context & ctx, ggml_tensor * dst
25882649 return ;
25892650 }
25902651
2652+ const bool turbo_k_classic_v_prefill =
2653+ ggml_cuda_fattn_prefill_mma_can_materialize_turbo_k_classic_v (K, V);
2654+ const bool turbo_prefill_can_make_f16_K = ggml_cuda_turbo_prefill_mma_can_make_f16 (K->type );
2655+ const bool turbo_prefill_can_make_f16_V = ggml_cuda_turbo_prefill_mma_can_make_f16 (V->type );
25912656 const bool turbo_prefill_mma_safe =
25922657 turbo_kv &&
2593- ggml_cuda_turbo_prefill_mma_can_make_f16 (K->type ) &&
2594- ggml_cuda_turbo_prefill_mma_can_make_f16 (V->type );
2658+ ((turbo_prefill_can_make_f16_K &&
2659+ turbo_prefill_can_make_f16_V) ||
2660+ turbo_k_classic_v_prefill);
2661+ const bool turbo_prefill_turing_mma =
2662+ turing_mma_available (ggml_cuda_info ().devices [ggml_cuda_get_device ()].cc );
25952663
2596- if (turbo_prefill_mma_safe && !turbo_prefill_vec && Q->ne [1 ] > 1 && Q->ne [0 ] <= 256 && turing_mma_available ( ggml_cuda_info (). devices [ ggml_cuda_get_device ()]. cc ) ) {
2664+ if (turbo_prefill_mma_safe && !turbo_prefill_vec && Q->ne [1 ] > 1 && Q->ne [0 ] <= 512 && turbo_prefill_turing_mma ) {
25972665 if (turbo_fa_debug) {
25982666 fprintf (stderr,
25992667 " GGML_TURBO_FA_DEBUG: path=prefill-dequant K=%s V=%s Q=[%lld,%lld,%lld,%lld] K=[%lld,%lld,%lld,%lld] V=[%lld,%lld,%lld,%lld]\n " ,
@@ -2608,11 +2676,19 @@ void ggml_cuda_flash_attn_ext(ggml_backend_cuda_context & ctx, ggml_tensor * dst
26082676 } else {
26092677 if (turbo_fa_debug && turbo_kv) {
26102678 fprintf (stderr,
2611- " GGML_TURBO_FA_DEBUG: path=decode-dequant-or-vec K=%s V=%s Q=[%lld,%lld,%lld,%lld] K=[%lld,%lld,%lld,%lld] V=[%lld,%lld,%lld,%lld]\n " ,
2679+ " GGML_TURBO_FA_DEBUG: path=decode-dequant-or-vec K=%s V=%s Q=[%lld,%lld,%lld,%lld] K=[%lld,%lld,%lld,%lld] V=[%lld,%lld,%lld,%lld] prefill_safe=%d can_make_f16_K=%d can_make_f16_V=%d turbo_k_classic_v_prefill=%d vec_override=%d batch_ok=%d dim_ok=%d turing_mma=%d \n " ,
26122680 ggml_type_name (K->type ), ggml_type_name (V->type ),
26132681 (long long ) Q->ne [0 ], (long long ) Q->ne [1 ], (long long ) Q->ne [2 ], (long long ) Q->ne [3 ],
26142682 (long long ) K->ne [0 ], (long long ) K->ne [1 ], (long long ) K->ne [2 ], (long long ) K->ne [3 ],
2615- (long long ) V->ne [0 ], (long long ) V->ne [1 ], (long long ) V->ne [2 ], (long long ) V->ne [3 ]);
2683+ (long long ) V->ne [0 ], (long long ) V->ne [1 ], (long long ) V->ne [2 ], (long long ) V->ne [3 ],
2684+ (int ) turbo_prefill_mma_safe,
2685+ (int ) turbo_prefill_can_make_f16_K,
2686+ (int ) turbo_prefill_can_make_f16_V,
2687+ (int ) turbo_k_classic_v_prefill,
2688+ (int ) turbo_prefill_vec,
2689+ (int ) (Q->ne [1 ] > 1 ),
2690+ (int ) (Q->ne [0 ] <= 512 ),
2691+ (int ) turbo_prefill_turing_mma);
26162692 }
26172693 load_tcq_decode_alpha (ctx.device );
26182694
0 commit comments