From e0f3a6b2920b340256f0ef747d888f51facb539b Mon Sep 17 00:00:00 2001 From: Gong-Mi <550230171@qq.com> Date: Tue, 20 Jan 2026 21:13:23 +0800 Subject: [PATCH 1/6] vulkan: optimize Mali and Adreno tuning & fix FP16/matrix stability - Add VK_VENDOR_ID_ARM (0x13B5) and VK_VENDOR_ID_QUALCOMM (0x5143). - Disable 'l_warptile' (Large) paths on ARM and Qualcomm to avoid register pressure/driver crashes. - Explicitly disable cooperative matrix (fp16-matrix) on mobile GPUs to prevent crashes. - Disable integer dot product (int8-matrix) on Qualcomm due to driver issues. - Keep general FP16 enabled for large model support. - Limit suballocation block size to 256MB to improve memory stability on Android. --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index b5e5dba95f..116009a13a 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -90,8 +90,10 @@ static bool is_pow2(uint32_t x) { return x > 1 && (x & (x-1)) == 0; } #define VK_VENDOR_ID_AMD 0x1002 #define VK_VENDOR_ID_APPLE 0x106b +#define VK_VENDOR_ID_ARM 0x13B5 #define VK_VENDOR_ID_INTEL 0x8086 #define VK_VENDOR_ID_NVIDIA 0x10de +#define VK_VENDOR_ID_QUALCOMM 0x5143 #define VK_DEVICE_DESCRIPTOR_POOL_SIZE 256 @@ -3059,6 +3061,11 @@ static void ggml_vk_load_shaders(vk_device& device) { device->mul_mat_l[i] = false; } + if (device->vendor_id == VK_VENDOR_ID_ARM || device->vendor_id == VK_VENDOR_ID_QUALCOMM) { + device->mul_mat_l[i] = false; + device->mul_mat_id_l[i] = false; + } + // Disable mul_mat_id if not enough shared memory is available if (!ggml_vk_matmul_shmem_support(device, s_warptile_mmqid, true, t)) { device->mul_mat_id_s[i] = false; @@ -4676,6 +4683,17 @@ static vk_device ggml_vk_get_device(size_t idx) { // Limit batching of allocations to 1GB by default to avoid fragmentation issues device->suballocation_block_size = 1024*1024*1024; } + + if (device->vendor_id == VK_VENDOR_ID_ARM) { + // ARM Mali optimization: disable fp16-matrix to prevent crashes, limit memory blocks + device->coopmat_support = false; + device->suballocation_block_size = 256 * 1024 * 1024; + } else if (device->vendor_id == VK_VENDOR_ID_QUALCOMM) { + // Qualcomm Adreno optimization: disable fp16-matrix and int8-dotprod to prevent crashes, limit memory blocks + device->coopmat_support = false; + device->integer_dot_product = false; + device->suballocation_block_size = 256 * 1024 * 1024; + } device->suballocation_block_size = std::min(device->suballocation_block_size, device->max_memory_allocation_size); device->subgroup_size = subgroup_props.subgroupSize; From 73f94ff366fd0800c8f954166e6a4cf7973e0991 Mon Sep 17 00:00:00 2001 From: Gong-Mi <550230171@qq.com> Date: Tue, 20 Jan 2026 21:30:32 +0800 Subject: [PATCH 2/6] ggml-vulkan: Refine mobile tuning (optimize ARM & disable unstable Qualcomm configs) - Android Baseline: Adjusted configurations to avoid large tile allocations, establishing a stable performance floor for mobile devices. - ARM Optimization: Clarified and explicitly restored optimized warptile tuning for ARM architectures. - Qualcomm Stability Fix: Removed Qualcomm-specific tuning as Adreno drivers frequently trigger fatal timeouts/crashes. Deprecating support for large models (>1B) on Qualcomm via Vulkan for now. --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 116009a13a..00f8a42eb8 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -3037,6 +3037,11 @@ static void ggml_vk_load_shaders(vk_device& device) { // Xe2/Xe3 with coopmat enabled - warptile performance tuning l_warptile = { 512, 128, 128, 16, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; l_warptile_mmq = { 512, 128, 128, 32, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; + } else if (device->vendor_id == VK_VENDOR_ID_ARM && device->subgroup_size >= 16) { + uint32_t wm = 32 / device->subgroup_size; + m_warptile_mmq = m_warptile_mmq_int = { 64, 64, 64, 16, 16, 32, wm, 2, 2, 1, device->subgroup_size }; + m_warptile = { 64, 64, 64, 16, 16, 32, wm, 2, 2, 1, device->subgroup_size }; + m_warptile_id = m_warptile_mmqid = { 64, 64, 64, 16, 16, 32, wm, 2, 2, 1, device->subgroup_size }; } l_mmq_wg_denoms = l_wg_denoms = {128, 128, 1 }; From 322605cb6288bbc00973e899729e6b4bcd9a517a Mon Sep 17 00:00:00 2001 From: Gong-Mi <550230171@qq.com> Date: Fri, 23 Jan 2026 20:49:00 +0800 Subject: [PATCH 3/6] ggml-vulkan: fix Mali-G720 warptile tuning (WM size) --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 00f8a42eb8..79ba8e8c53 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -3038,10 +3038,11 @@ static void ggml_vk_load_shaders(vk_device& device) { l_warptile = { 512, 128, 128, 16, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; l_warptile_mmq = { 512, 128, 128, 32, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; } else if (device->vendor_id == VK_VENDOR_ID_ARM && device->subgroup_size >= 16) { - uint32_t wm = 32 / device->subgroup_size; - m_warptile_mmq = m_warptile_mmq_int = { 64, 64, 64, 16, 16, 32, wm, 2, 2, 1, device->subgroup_size }; - m_warptile = { 64, 64, 64, 16, 16, 32, wm, 2, 2, 1, device->subgroup_size }; - m_warptile_id = m_warptile_mmqid = { 64, 64, 64, 16, 16, 32, wm, 2, 2, 1, device->subgroup_size }; + uint32_t wm_iter = 32 / device->subgroup_size; + uint32_t wm_tile = device->subgroup_size * 2; + m_warptile_mmq = m_warptile_mmq_int = { 64, 64, 64, 16, wm_tile, 32, wm_iter, 2, 2, 1, device->subgroup_size }; + m_warptile = { 64, 64, 64, 16, wm_tile, 32, wm_iter, 2, 2, 1, device->subgroup_size }; + m_warptile_id = m_warptile_mmqid = { 64, 64, 64, 16, wm_tile, 32, wm_iter, 2, 2, 1, device->subgroup_size }; } l_mmq_wg_denoms = l_wg_denoms = {128, 128, 1 }; From 8e98e723eb7ca001c177c3e26748607ad3ad8325 Mon Sep 17 00:00:00 2001 From: Gong-Mi <550230171@qq.com> Date: Fri, 23 Jan 2026 21:04:37 +0800 Subject: [PATCH 4/6] ggml-vulkan: clamp subgroup size to 64 on Qualcomm to prevent instability --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 79ba8e8c53..10dea421bb 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -4703,6 +4703,10 @@ static vk_device ggml_vk_get_device(size_t idx) { device->suballocation_block_size = std::min(device->suballocation_block_size, device->max_memory_allocation_size); device->subgroup_size = subgroup_props.subgroupSize; + if (device->vendor_id == VK_VENDOR_ID_QUALCOMM && device->subgroup_size > 64) { + VK_LOG_INFO("ggml_vulkan: clamping subgroup size to 64 for Qualcomm"); + device->subgroup_size = 64; + } device->subgroup_size_log2 = uint32_t(log2f(float(device->subgroup_size))); device->uma = device->properties.deviceType == vk::PhysicalDeviceType::eIntegratedGpu; if (sm_builtins) { From e6c76f777144f9b06dc55ea96959725689995e1a Mon Sep 17 00:00:00 2001 From: Gong-Mi <550230171@qq.com> Date: Fri, 30 Jan 2026 19:23:59 +0800 Subject: [PATCH 5/6] vulkan: optimized tuning for ARM Mali (stable 4x4) and Qualcomm Adreno --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 30 +++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 79ba8e8c53..60b9a8638d 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -3037,12 +3037,25 @@ static void ggml_vk_load_shaders(vk_device& device) { // Xe2/Xe3 with coopmat enabled - warptile performance tuning l_warptile = { 512, 128, 128, 16, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; l_warptile_mmq = { 512, 128, 128, 32, subgroup_size_8, 32, 2, tm_m, tn_m, tk_m, subgroup_size_8 }; + } else if (device->vendor_id == VK_VENDOR_ID_QUALCOMM) { + uint32_t s = device->subgroup_size; + m_warptile = m_warptile_mmq = m_warptile_mmq_int = m_warptile_mmq_k = m_warptile_mmq_int_k = + m_warptile_id = m_warptile_mmqid = m_warptile_mmqid_int = m_warptile_mmqid_int_k = + { 64, 64, 64, s, s, 16, 8, 8, 1, 1, s }; + s_warptile = s_warptile_mmq = s_warptile_mmq_int = s_warptile_mmq_k = s_warptile_mmq_int_k = + s_warptile_id = s_warptile_mmqid = s_warptile_mmqid_int = s_warptile_mmqid_int_k = + { 32, 32, 64, s, s, 16, 8, 8, 1, 1, s }; } else if (device->vendor_id == VK_VENDOR_ID_ARM && device->subgroup_size >= 16) { - uint32_t wm_iter = 32 / device->subgroup_size; - uint32_t wm_tile = device->subgroup_size * 2; - m_warptile_mmq = m_warptile_mmq_int = { 64, 64, 64, 16, wm_tile, 32, wm_iter, 2, 2, 1, device->subgroup_size }; - m_warptile = { 64, 64, 64, 16, wm_tile, 32, wm_iter, 2, 2, 1, device->subgroup_size }; - m_warptile_id = m_warptile_mmqid = { 64, 64, 64, 16, wm_tile, 32, wm_iter, 2, 2, 1, device->subgroup_size }; + uint32_t s = device->subgroup_size; + s_warptile = s_warptile_mmq = s_warptile_mmq_int = s_warptile_mmq_k = s_warptile_mmq_int_k = + s_warptile_id = s_warptile_mmqid = s_warptile_mmqid_int = s_warptile_mmqid_int_k = + { 32, 32, 64, s, s, 16, 4, 4, 1, 1, s }; + m_warptile = m_warptile_mmq = m_warptile_mmq_int = m_warptile_mmq_k = m_warptile_mmq_int_k = + m_warptile_id = m_warptile_mmqid = m_warptile_mmqid_int = m_warptile_mmqid_int_k = + { 64, 64, 64, s, s, 16, 4, 4, 1, 1, s }; + l_warptile = l_warptile_mmq = l_warptile_mmq_int = l_warptile_mmq_k = l_warptile_mmq_int_k = + l_warptile_id = l_warptile_mmqid = l_warptile_mmqid_int = l_warptile_mmqid_int_k = + { 64, 64, 64, s, s, 16, 4, 4, 1, 1, s }; } l_mmq_wg_denoms = l_wg_denoms = {128, 128, 1 }; @@ -3052,6 +3065,10 @@ static void ggml_vk_load_shaders(vk_device& device) { m_align = 64; s_align = 32; + if (device->vendor_id == VK_VENDOR_ID_QUALCOMM) { + m_align = 128; + } + for (uint32_t i = 0; i < GGML_TYPE_COUNT; ++i) { ggml_type t = (ggml_type)i; // Disable medium and large matrix multiplication if not enough shared memory is available @@ -13752,6 +13769,9 @@ static ggml_status ggml_backend_vk_graph_compute(ggml_backend_t backend, ggml_cg // (and scaled down based on model size, so smaller models submit earlier). // Also submit at least every 100 nodes, in case there are workloads without as much matmul. int nodes_per_submit = 100; + if (ctx->device->vendor_id == VK_VENDOR_ID_QUALCOMM) { + nodes_per_submit = 1000; + } int submitted_nodes = 0; int submit_count = 0; uint64_t mul_mat_bytes = 0; From cef48b4cbf7d8fcda55d502e4e972cb070607221 Mon Sep 17 00:00:00 2001 From: Gong-Mi <550230171@qq.com> Date: Mon, 2 Feb 2026 01:11:08 +0800 Subject: [PATCH 6/6] ggml-vulkan: move ARM/Qualcomm mul_mat_l restriction to init block Moves the logic that disables large matrix multiplication for ARM and Qualcomm devices from ggml_vk_load_shaders to the device initialization switch block. This fixes stability issues (silent calculation errors) on Mali G720/Immortalis MC12 while adhering to the code structure requested in PR #18493 discussion. --- ggml/src/ggml-vulkan/ggml-vulkan.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/ggml/src/ggml-vulkan/ggml-vulkan.cpp b/ggml/src/ggml-vulkan/ggml-vulkan.cpp index 60b9a8638d..7b8611743d 100644 --- a/ggml/src/ggml-vulkan/ggml-vulkan.cpp +++ b/ggml/src/ggml-vulkan/ggml-vulkan.cpp @@ -3084,10 +3084,7 @@ static void ggml_vk_load_shaders(vk_device& device) { device->mul_mat_l[i] = false; } - if (device->vendor_id == VK_VENDOR_ID_ARM || device->vendor_id == VK_VENDOR_ID_QUALCOMM) { - device->mul_mat_l[i] = false; - device->mul_mat_id_l[i] = false; - } + // Disable mul_mat_id if not enough shared memory is available if (!ggml_vk_matmul_shmem_support(device, s_warptile_mmqid, true, t)) { @@ -5195,6 +5192,15 @@ static vk_device ggml_vk_get_device(size_t idx) { device->mul_mat_id_m[i] = true; device->mul_mat_id_s[i] = true; break; + case VK_VENDOR_ID_ARM: + case VK_VENDOR_ID_QUALCOMM: + device->mul_mat_l[i] = false; + device->mul_mat_id_l[i] = false; + device->mul_mat_m[i] = true; + device->mul_mat_s[i] = true; + device->mul_mat_id_m[i] = true; + device->mul_mat_id_s[i] = true; + break; case VK_VENDOR_ID_APPLE: device->mul_mat_l[i] = false; device->mul_mat_m[i] = true;