From 5c200e0c8dfdbfa388f5d8f79ef7195dd4eb801e Mon Sep 17 00:00:00 2001 From: Ruben Ortlam Date: Tue, 29 Sep 2026 19:44:20 +0200 Subject: [PATCH] vulkan: Tune GDN kernel, fix Intel performance (#29476) * vulkan: tune GDN shader * tune for Intel --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 30 ++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 6c5a57394b..e23d5b4339 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -3668,33 +3668,43 @@ void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { const uint32_t S_V = gdn_sizes[si]; GGML_ASSERT(is_pow2(S_V)); + // Intel Xe regresses at SIMD32 for this scan; prefer a narrower subgroup. + uint32_t gdn_subgroup_size = device->subgroup_size; + if (device->vendor_id == VK_VENDOR_ID_INTEL && device->subgroup_size_control && + device->subgroup_min_size <= 16u && device->subgroup_max_size >= 16u) { + gdn_subgroup_size = 16u; + } uint32_t lanes_per_column; - if (S_V >= 128u && device->subgroup_clustered) { - lanes_per_column = 8u; + if (device->vendor_id == VK_VENDOR_ID_INTEL) { + // Intel Xe: full-width reduction (min rows/lane) ~10x over the COLS_PER_WG=8 rule. + lanes_per_column = std::min(gdn_subgroup_size, S_V); + } else if (S_V >= 128u && device->subgroup_clustered) { + // COLS_PER_WG=8: measured optimum (Ampere sg32->4, Vega20 sg64->8). + lanes_per_column = std::max(1u, gdn_subgroup_size / 8u); } else { // Use largest power-of-two that divides both S_V and subgroup_size so that // (1) S_V % lanes_per_column == 0 and (2) S_V % (subgroup_size / lanes_per_column) == 0. // This means we don't need extra bounds checking logic in the shader. - lanes_per_column = std::min(S_V, device->subgroup_size); + lanes_per_column = std::min(S_V, gdn_subgroup_size); } // gated_delta_net.comp relies on S_V % COLS_PER_WG == 0 and // S_V % LANES_PER_COLUMN == 0 to avoid bounds checks. while (lanes_per_column > 1u) { - const bool valid_lanes = (device->subgroup_size % lanes_per_column) == 0 && + const bool valid_lanes = (gdn_subgroup_size % lanes_per_column) == 0 && (S_V % lanes_per_column) == 0; - const uint32_t cols_per_wg = valid_lanes ? device->subgroup_size / lanes_per_column : 0; + const uint32_t cols_per_wg = valid_lanes ? gdn_subgroup_size / lanes_per_column : 0; if (valid_lanes && cols_per_wg > 0 && (S_V % cols_per_wg) == 0) { break; } lanes_per_column >>= 1u; } - GGML_ASSERT((device->subgroup_size % lanes_per_column) == 0); + GGML_ASSERT((gdn_subgroup_size % lanes_per_column) == 0); GGML_ASSERT((S_V % lanes_per_column) == 0); - GGML_ASSERT((S_V % (device->subgroup_size / lanes_per_column)) == 0); + GGML_ASSERT((S_V % (gdn_subgroup_size / lanes_per_column)) == 0); - const bool need_partial_subgroup_reduce = lanes_per_column != 1u && lanes_per_column < device->subgroup_size; + const bool need_partial_subgroup_reduce = lanes_per_column != 1u && lanes_per_column < gdn_subgroup_size; const bool use_clustered_reduce = device->subgroup_arithmetic && device->subgroup_clustered && need_partial_subgroup_reduce; const bool use_subgroup_reduce = device->subgroup_arithmetic && !need_partial_subgroup_reduce; const bool use_subgroup_ops = use_clustered_reduce || use_subgroup_reduce; @@ -3711,13 +3721,13 @@ void ggml_vk_load_shaders(vk_device& device, vk_pipeline requested) { gdn_data = (const void *)gated_delta_net_f32_shmem_data; } - const uint32_t cols_per_wg = device->subgroup_size / lanes_per_column; + const uint32_t cols_per_wg = gdn_subgroup_size / lanes_per_column; const std::array wg_denoms = {1u, 1u, cols_per_wg}; for (uint32_t kda = 0; kda < 2; kda++) { ggml_vk_create_pipeline(device, device->pipeline_gated_delta_net[si][kda], gdn_names[si][kda], gdn_len, gdn_data, "main", 7, sizeof(vk_op_gated_delta_net_push_constants), - wg_denoms, {S_V, kda, device->subgroup_size, lanes_per_column}, 1, true, use_subgroup_ops, device->subgroup_size); + wg_denoms, {S_V, kda, gdn_subgroup_size, lanes_per_column}, 1, true, use_subgroup_ops, gdn_subgroup_size); } } }