whispercpp 1.3.7 → 1.3.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (308) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +5 -4
  3. data/ext/options.rb +1 -1
  4. data/ext/ruby_whisper.c +0 -1
  5. data/ext/ruby_whisper.h +7 -1
  6. data/ext/ruby_whisper_context.c +50 -1
  7. data/ext/ruby_whisper_log_settable.h +1 -2
  8. data/ext/ruby_whisper_params.c +9 -8
  9. data/ext/ruby_whisper_transcribe.cpp +0 -19
  10. data/ext/ruby_whisper_vad_context.c +30 -10
  11. data/ext/ruby_whisper_vad_context_detect.cpp +8 -9
  12. data/ext/ruby_whisper_vad_params.c +4 -4
  13. data/ext/ruby_whisper_vad_segment.c +2 -2
  14. data/ext/sources/CMakeLists.txt +2 -1
  15. data/ext/sources/cmake/parakeet.pc.in +2 -2
  16. data/ext/sources/cmake/whisper.pc.in +2 -2
  17. data/ext/sources/examples/cli/cli.cpp +9 -1
  18. data/ext/sources/examples/common-ggml.cpp +2 -0
  19. data/ext/sources/examples/vad-speech-segments/speech.cpp +3 -2
  20. data/ext/sources/ggml/CMakeLists.txt +3 -4
  21. data/ext/sources/ggml/include/ggml-cuda.h +0 -3
  22. data/ext/sources/ggml/include/ggml-sycl.h +8 -0
  23. data/ext/sources/ggml/include/ggml.h +3 -1
  24. data/ext/sources/ggml/src/CMakeLists.txt +8 -1
  25. data/ext/sources/ggml/src/ggml-backend-meta.cpp +7 -4
  26. data/ext/sources/ggml/src/ggml-common.h +13 -2
  27. data/ext/sources/ggml/src/ggml-cpu/CMakeLists.txt +1 -1
  28. data/ext/sources/ggml/src/ggml-cpu/amx/mmq.cpp +5 -6
  29. data/ext/sources/ggml/src/ggml-cpu/arch/arm/quants.c +78 -4
  30. data/ext/sources/ggml/src/ggml-cpu/arch/x86/quants.c +142 -4
  31. data/ext/sources/ggml/src/ggml-cpu/arch-fallback.h +7 -2
  32. data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.c +14 -0
  33. data/ext/sources/ggml/src/ggml-cpu/llamafile/sgemm.cpp +26 -19
  34. data/ext/sources/ggml/src/ggml-cpu/ops.cpp +129 -46
  35. data/ext/sources/ggml/src/ggml-cpu/quants.c +51 -0
  36. data/ext/sources/ggml/src/ggml-cpu/quants.h +3 -0
  37. data/ext/sources/ggml/src/ggml-cpu/simd-gemm.h +1 -1
  38. data/ext/sources/ggml/src/ggml-cpu/simd-mappings.h +11 -0
  39. data/ext/sources/ggml/src/ggml-cpu/vec.cpp +2 -2
  40. data/ext/sources/ggml/src/ggml-cuda/binbcast.cu +90 -46
  41. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
  42. data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
  43. data/ext/sources/ggml/src/ggml-cuda/common.cuh +4 -0
  44. data/ext/sources/ggml/src/ggml-cuda/concat.cu +33 -21
  45. data/ext/sources/ggml/src/ggml-cuda/conv-transpose-1d.cu +14 -12
  46. data/ext/sources/ggml/src/ggml-cuda/convert.cu +86 -34
  47. data/ext/sources/ggml/src/ggml-cuda/cpy.cu +80 -29
  48. data/ext/sources/ggml/src/ggml-cuda/fattn-common.cuh +9 -5
  49. data/ext/sources/ggml/src/ggml-cuda/fattn-mma-f16.cuh +4 -0
  50. data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cuh +9 -5
  51. data/ext/sources/ggml/src/ggml-cuda/fattn.cu +27 -21
  52. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cu +40 -25
  53. data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cuh +10 -0
  54. data/ext/sources/ggml/src/ggml-cuda/getrows.cu +15 -12
  55. data/ext/sources/ggml/src/ggml-cuda/ggml-cuda.cu +718 -1248
  56. data/ext/sources/ggml/src/ggml-cuda/mmq.cu +7 -0
  57. data/ext/sources/ggml/src/ggml-cuda/mmvq.cu +77 -40
  58. data/ext/sources/ggml/src/ggml-cuda/out-prod.cu +55 -12
  59. data/ext/sources/ggml/src/ggml-cuda/set-rows.cu +64 -4
  60. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +1 -0
  61. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +1 -0
  62. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +1 -0
  63. data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +1 -0
  64. data/ext/sources/ggml/src/ggml-cuda/topk-moe.cu +7 -1
  65. data/ext/sources/ggml/src/ggml-cuda/vendors/hip.h +1 -0
  66. data/ext/sources/ggml/src/ggml-cuda/vendors/musa.h +1 -0
  67. data/ext/sources/ggml/src/ggml-hexagon/CMakeLists.txt +0 -5
  68. data/ext/sources/ggml/src/ggml-hexagon/ggml-hexagon.cpp +1634 -1293
  69. data/ext/sources/ggml/src/ggml-hexagon/htp/CMakeLists.txt +11 -40
  70. data/ext/sources/ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake +13 -15
  71. data/ext/sources/ggml/src/ggml-hexagon/htp/concat-ops.c +1 -1
  72. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.c +1749 -399
  73. data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.h +303 -0
  74. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-common.h +80 -0
  75. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.h +26 -23
  76. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-profile.h +64 -0
  77. data/ext/sources/ggml/src/ggml-hexagon/htp/hex-utils.h +1 -83
  78. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h +555 -0
  79. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-mm-kernels-tiled.h +1303 -0
  80. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.c +9 -0
  81. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.h +27 -4
  82. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-utils.h +59 -37
  83. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ctx.h +11 -3
  84. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ops.h +52 -12
  85. data/ext/sources/ggml/src/ggml-hexagon/htp/htp-vtcm.h +19 -0
  86. data/ext/sources/ggml/src/ggml-hexagon/htp/htp_iface.idl +2 -1
  87. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-base.h +14 -30
  88. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-exp.h +39 -0
  89. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h +232 -0
  90. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-flat.h +1511 -0
  91. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-tiled.h +1200 -0
  92. data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sigmoid.h +39 -0
  93. data/ext/sources/ggml/src/ggml-hexagon/htp/main.c +127 -32
  94. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.c +3023 -4425
  95. data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.h +650 -0
  96. data/ext/sources/ggml/src/ggml-hexagon/htp/rope-ops.c +48 -13
  97. data/ext/sources/ggml/src/ggml-hexagon/htp/ssm-conv.c +10 -9
  98. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.c +15 -3
  99. data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.h +8 -0
  100. data/ext/sources/ggml/src/ggml-hexagon/htp-opnode.h +168 -50
  101. data/ext/sources/ggml/src/ggml-hexagon/libggml-htp.inf +0 -4
  102. data/ext/sources/ggml/src/ggml-hip/CMakeLists.txt +5 -0
  103. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.cpp +69 -5
  104. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.h +4 -1
  105. data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.m +27 -6
  106. data/ext/sources/ggml/src/ggml-metal/ggml-metal-impl.h +38 -0
  107. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.cpp +132 -2
  108. data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.h +2 -0
  109. data/ext/sources/ggml/src/ggml-metal/ggml-metal.metal +345 -87
  110. data/ext/sources/ggml/src/ggml-opencl/CMakeLists.txt +13 -0
  111. data/ext/sources/ggml/src/ggml-opencl/fa_tune.h +92 -0
  112. data/ext/sources/ggml/src/ggml-opencl/ggml-opencl.cpp +4060 -357
  113. data/ext/sources/ggml/src/ggml-opencl/kernels/cvt.cl +198 -0
  114. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f16.cl +81 -41
  115. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32.cl +88 -39
  116. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl +1995 -96
  117. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q4_0.cl +1615 -0
  118. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q8_0.cl +1486 -0
  119. data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_pre_f16.cl +156 -0
  120. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32_ns.cl +74 -6
  121. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_f32_ns.cl +74 -6
  122. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_1_f32_ns.cl +74 -6
  123. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_f32_ns.cl +71 -6
  124. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_0_f32_ns.cl +74 -6
  125. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_1_f32_ns.cl +74 -6
  126. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_k_f32_ns.cl +74 -6
  127. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_f32_ns.cl +74 -6
  128. data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q1_0_f32.cl +94 -0
  129. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl +121 -0
  130. data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q8_0_f32.cl +1 -1
  131. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q1_0_f32_l4_lm.cl +156 -0
  132. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +1149 -0
  133. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32.cl +141 -0
  134. data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32_flat.cl +190 -0
  135. data/ext/sources/ggml/src/ggml-opencl/kernels/norm.cl +5 -2
  136. data/ext/sources/ggml/src/ggml-opencl/kernels/set_rows.cl +500 -0
  137. data/ext/sources/ggml/src/ggml-opencl/libdl.h +79 -0
  138. data/ext/sources/ggml/src/ggml-openvino/.clang-format +0 -5
  139. data/ext/sources/ggml/src/ggml-openvino/CMakeLists.txt +2 -4
  140. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.cpp +733 -130
  141. data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.h +76 -23
  142. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.cpp +57 -3
  143. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.h +29 -8
  144. data/ext/sources/ggml/src/ggml-openvino/ggml-openvino.cpp +307 -59
  145. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.cpp +66 -0
  146. data/ext/sources/ggml/src/ggml-openvino/ggml-quants.h +10 -4
  147. data/ext/sources/ggml/src/ggml-openvino/openvino/decoder.h +56 -16
  148. data/ext/sources/ggml/src/ggml-openvino/openvino/frontend.h +1 -1
  149. data/ext/sources/ggml/src/ggml-openvino/openvino/input_model.h +4 -4
  150. data/ext/sources/ggml/src/ggml-openvino/openvino/node_context.h +94 -37
  151. data/ext/sources/ggml/src/ggml-openvino/openvino/op/add_id.cpp +76 -0
  152. data/ext/sources/ggml/src/ggml-openvino/openvino/op/argsort.cpp +47 -0
  153. data/ext/sources/ggml/src/ggml-openvino/openvino/op/clamp.cpp +33 -0
  154. data/ext/sources/ggml/src/ggml-openvino/openvino/op/concat.cpp +48 -0
  155. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cont.cpp +8 -16
  156. data/ext/sources/ggml/src/ggml-openvino/openvino/op/cpy.cpp +14 -1
  157. data/ext/sources/ggml/src/ggml-openvino/openvino/op/div.cpp +146 -0
  158. data/ext/sources/ggml/src/ggml-openvino/openvino/op/flash_attn_ext.cpp +108 -21
  159. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.cpp +282 -0
  160. data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.hpp +65 -0
  161. data/ext/sources/ggml/src/ggml-openvino/openvino/op/get_rows.cpp +2 -9
  162. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_geglu.cpp +21 -7
  163. data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp +41 -8
  164. data/ext/sources/ggml/src/ggml-openvino/openvino/op/im2col.cpp +120 -0
  165. data/ext/sources/ggml/src/ggml-openvino/openvino/op/l2_norm.cpp +44 -0
  166. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp +226 -0
  167. data/ext/sources/ggml/src/ggml-openvino/openvino/op/mulmat.cpp +19 -9
  168. data/ext/sources/ggml/src/ggml-openvino/openvino/op/norm.cpp +58 -0
  169. data/ext/sources/ggml/src/ggml-openvino/openvino/op/pad.cpp +95 -0
  170. data/ext/sources/ggml/src/ggml-openvino/openvino/op/permute.cpp +58 -13
  171. data/ext/sources/ggml/src/ggml-openvino/openvino/op/repeat.cpp +74 -0
  172. data/ext/sources/ggml/src/ggml-openvino/openvino/op/reshape.cpp +13 -6
  173. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rms_norm.cpp +1 -1
  174. data/ext/sources/ggml/src/ggml-openvino/openvino/op/rope.cpp +134 -38
  175. data/ext/sources/ggml/src/ggml-openvino/openvino/op/set_rows.cpp +3 -3
  176. data/ext/sources/ggml/src/ggml-openvino/openvino/op/softmax.cpp +126 -49
  177. data/ext/sources/ggml/src/ggml-openvino/openvino/op/ssm_conv.cpp +59 -0
  178. data/ext/sources/ggml/src/ggml-openvino/openvino/op/sum_rows.cpp +27 -0
  179. data/ext/sources/ggml/src/ggml-openvino/openvino/op/transpose.cpp +32 -1
  180. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_silu.cpp +1 -1
  181. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp +38 -0
  182. data/ext/sources/ggml/src/ggml-openvino/openvino/op/view.cpp +90 -25
  183. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.cpp +41 -23
  184. data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.h +18 -5
  185. data/ext/sources/ggml/src/ggml-openvino/openvino/pass/mark_decompression_convert_constant_folding.h +1 -1
  186. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.cpp +43 -40
  187. data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.h +5 -4
  188. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.cpp +548 -3
  189. data/ext/sources/ggml/src/ggml-openvino/openvino/utils.h +28 -26
  190. data/ext/sources/ggml/src/ggml-openvino/utils.cpp +383 -94
  191. data/ext/sources/ggml/src/ggml-openvino/utils.h +11 -8
  192. data/ext/sources/ggml/src/ggml-quants.c +76 -0
  193. data/ext/sources/ggml/src/ggml-quants.h +3 -0
  194. data/ext/sources/ggml/src/ggml-sycl/CMakeLists.txt +5 -5
  195. data/ext/sources/ggml/src/ggml-sycl/backend.hpp +2 -0
  196. data/ext/sources/ggml/src/ggml-sycl/binbcast.cpp +12 -0
  197. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.cpp +102 -0
  198. data/ext/sources/ggml/src/ggml-sycl/col2im-1d.hpp +8 -0
  199. data/ext/sources/ggml/src/ggml-sycl/common.cpp +6 -8
  200. data/ext/sources/ggml/src/ggml-sycl/common.hpp +19 -2
  201. data/ext/sources/ggml/src/ggml-sycl/concat.cpp +21 -1
  202. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.cpp +158 -0
  203. data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.hpp +10 -0
  204. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.cpp +125 -0
  205. data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.hpp +10 -0
  206. data/ext/sources/ggml/src/ggml-sycl/conv2d.cpp +150 -0
  207. data/ext/sources/ggml/src/ggml-sycl/conv2d.hpp +10 -0
  208. data/ext/sources/ggml/src/ggml-sycl/conv3d.cpp +224 -0
  209. data/ext/sources/ggml/src/ggml-sycl/conv3d.hpp +8 -0
  210. data/ext/sources/ggml/src/ggml-sycl/convert.cpp +6 -0
  211. data/ext/sources/ggml/src/ggml-sycl/cpy.cpp +706 -0
  212. data/ext/sources/ggml/src/ggml-sycl/cpy.hpp +281 -0
  213. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.cpp +255 -0
  214. data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.hpp +7 -0
  215. data/ext/sources/ggml/src/ggml-sycl/dequantize.hpp +15 -0
  216. data/ext/sources/ggml/src/ggml-sycl/dmmv.cpp +492 -319
  217. data/ext/sources/ggml/src/ggml-sycl/dpct/helper.hpp +15 -7
  218. data/ext/sources/ggml/src/ggml-sycl/element_wise.cpp +215 -115
  219. data/ext/sources/ggml/src/ggml-sycl/element_wise.hpp +2 -0
  220. data/ext/sources/ggml/src/ggml-sycl/ggml-sycl.cpp +1006 -336
  221. data/ext/sources/ggml/src/ggml-sycl/mmvq.cpp +252 -67
  222. data/ext/sources/ggml/src/ggml-sycl/mmvq.hpp +17 -0
  223. data/ext/sources/ggml/src/ggml-sycl/norm.cpp +103 -49
  224. data/ext/sources/ggml/src/ggml-sycl/outprod.cpp +45 -9
  225. data/ext/sources/ggml/src/ggml-sycl/pool.cpp +185 -0
  226. data/ext/sources/ggml/src/ggml-sycl/pool.hpp +22 -0
  227. data/ext/sources/ggml/src/ggml-sycl/presets.hpp +3 -1
  228. data/ext/sources/ggml/src/ggml-sycl/set_rows.cpp +10 -2
  229. data/ext/sources/ggml/src/ggml-sycl/softmax.cpp +9 -10
  230. data/ext/sources/ggml/src/ggml-sycl/vecdotq.hpp +35 -0
  231. data/ext/sources/ggml/src/ggml-vulkan/CMakeLists.txt +5 -0
  232. data/ext/sources/ggml/src/ggml-vulkan/ggml-vulkan.cpp +833 -215
  233. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
  234. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +1 -1
  235. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
  236. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/diag.comp +3 -3
  237. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp +1 -0
  238. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp +1 -0
  239. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl +21 -19
  240. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/get_rows_back.comp +25 -0
  241. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl +23 -4
  242. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl +14 -18
  243. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp +4 -7
  244. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp +21 -24
  245. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +31 -23
  246. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp +6 -5
  247. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl +84 -67
  248. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/norm.comp +10 -10
  249. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp +3 -3
  250. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/roll.comp +3 -3
  251. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tri.comp +3 -3
  252. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/unary.comp +168 -0
  253. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +121 -74
  254. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp +26 -19
  255. data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu.cpp +31 -36
  256. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl +16 -2
  257. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_split.wgsl +7 -7
  258. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl +21 -0
  259. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl +439 -320
  260. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_vec.wgsl +2 -2
  261. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl +45 -39
  262. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl +586 -465
  263. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_q_acc.tmpl +63 -69
  264. data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quantize_q8.wgsl +14 -9
  265. data/ext/sources/ggml/src/ggml.c +36 -14
  266. data/ext/sources/include/whisper.h +21 -0
  267. data/ext/sources/src/whisper.cpp +164 -14
  268. data/lib/whisper/log_settable.rb +5 -8
  269. data/lib/whisper/model/uri.rb +0 -7
  270. data/sig/whisper.rbs +6 -0
  271. data/test/test_vad.rb +9 -0
  272. data/test/test_vad_context.rb +2 -2
  273. data/whispercpp.gemspec +1 -1
  274. metadata +62 -37
  275. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-flash-attn-ops.c +0 -1878
  276. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-matmul-ops.c +0 -2066
  277. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-ops.c +0 -6
  278. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-ops.h +0 -88
  279. data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-profile.h +0 -34
  280. data/ext/sources/ggml/src/ggml-hexagon/htp/vtcm-utils.h +0 -16
  281. data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_gelu.cpp +0 -25
  282. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/abs.comp +0 -21
  283. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ceil.comp +0 -22
  284. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/clamp.comp +0 -17
  285. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/cos.comp +0 -17
  286. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/elu.comp +0 -27
  287. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/exp.comp +0 -20
  288. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/floor.comp +0 -22
  289. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu.comp +0 -25
  290. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_erf.comp +0 -39
  291. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_quick.comp +0 -23
  292. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardsigmoid.comp +0 -22
  293. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardswish.comp +0 -22
  294. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/leaky_relu.comp +0 -22
  295. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/neg.comp +0 -20
  296. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/relu.comp +0 -21
  297. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/round.comp +0 -29
  298. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sgn.comp +0 -21
  299. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sigmoid.comp +0 -20
  300. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/silu.comp +0 -22
  301. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sin.comp +0 -17
  302. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/softplus.comp +0 -23
  303. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sqrt.comp +0 -17
  304. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/square.comp +0 -17
  305. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/step.comp +0 -22
  306. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tanh.comp +0 -20
  307. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/trunc.comp +0 -22
  308. data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/xielu.comp +0 -35
@@ -0,0 +1,156 @@
1
+ #pragma OPENCL EXTENSION cl_khr_fp16 : enable
2
+
3
+ __kernel void flash_attn_kv_pad_f16(
4
+ const global void * k_void, ulong k_offset,
5
+ const global void * v_void, ulong v_offset,
6
+ global void * k_pad_void,
7
+ global void * v_pad_void,
8
+ const int n_kv,
9
+ const int n_head_kv,
10
+ const int n_batch,
11
+ const ulong k_nb1, const ulong k_nb2, const ulong k_nb3,
12
+ const ulong v_nb1, const ulong v_nb2, const ulong v_nb3
13
+ ) {
14
+ const int row_idx = get_global_id(0);
15
+ const int head_kv_idx = get_global_id(1);
16
+ const int batch_idx = get_global_id(2);
17
+
18
+ if (row_idx >= BLOCK_N || head_kv_idx >= n_head_kv || batch_idx >= n_batch) {
19
+ return;
20
+ }
21
+
22
+ const int tail_start = n_kv - (n_kv % BLOCK_N);
23
+ const int src_row_idx = tail_start + row_idx;
24
+
25
+ const global char * k_src = (const global char *) k_void + k_offset;
26
+ const global char * v_src = (const global char *) v_void + v_offset;
27
+ global char * k_pad = (global char *) k_pad_void;
28
+ global char * v_pad = (global char *) v_pad_void;
29
+
30
+ const ulong k_dst_offset = ((ulong) batch_idx * (ulong) n_head_kv + (ulong) head_kv_idx) * ((ulong) BLOCK_N * k_nb1) + (ulong) row_idx * k_nb1;
31
+ const ulong v_dst_offset = ((ulong) batch_idx * (ulong) n_head_kv + (ulong) head_kv_idx) * ((ulong) BLOCK_N * v_nb1) + (ulong) row_idx * v_nb1;
32
+
33
+ if (src_row_idx < n_kv) {
34
+ const ulong k_src_offset = (ulong) batch_idx * k_nb3 + (ulong) head_kv_idx * k_nb2 + (ulong) src_row_idx * k_nb1;
35
+ const ulong v_src_offset = (ulong) batch_idx * v_nb3 + (ulong) head_kv_idx * v_nb2 + (ulong) src_row_idx * v_nb1;
36
+
37
+ for (ulong i = 0; i < k_nb1; ++i) {
38
+ k_pad[k_dst_offset + i] = k_src[k_src_offset + i];
39
+ }
40
+ for (ulong i = 0; i < v_nb1; ++i) {
41
+ v_pad[v_dst_offset + i] = v_src[v_src_offset + i];
42
+ }
43
+ } else {
44
+ for (ulong i = 0; i < k_nb1; ++i) {
45
+ k_pad[k_dst_offset + i] = 0;
46
+ }
47
+ for (ulong i = 0; i < v_nb1; ++i) {
48
+ v_pad[v_dst_offset + i] = 0;
49
+ }
50
+ }
51
+ }
52
+
53
+ __kernel void flash_attn_mask_pad_f16(
54
+ const global void * mask_void, ulong mask_offset,
55
+ global void * mask_pad_void,
56
+ const int n_q,
57
+ const int n_kv,
58
+ const ulong mask_nb1,
59
+ const ulong mask_nb2,
60
+ const ulong mask_nb3,
61
+ const int mask_ne2,
62
+ const int mask_ne3
63
+ ) {
64
+ const int col_idx = get_global_id(0);
65
+ const int q_row = get_global_id(1);
66
+ const int mask_slice = get_global_id(2);
67
+
68
+ if (col_idx >= BLOCK_N || q_row >= n_q || mask_slice >= mask_ne2 * mask_ne3) {
69
+ return;
70
+ }
71
+
72
+ const int tail_start = n_kv - (n_kv % BLOCK_N);
73
+ const int src_col_idx = tail_start + col_idx;
74
+ const int mask_head_idx = mask_slice % mask_ne2;
75
+ const int mask_batch_idx = mask_slice / mask_ne2;
76
+
77
+ const global char * mask_src_base = (const global char *) mask_void + mask_offset +
78
+ (ulong) mask_batch_idx * mask_nb3 +
79
+ (ulong) mask_head_idx * mask_nb2 +
80
+ (ulong) q_row * mask_nb1;
81
+ const global half * mask_src = (const global half *) mask_src_base;
82
+
83
+ global half * mask_pad = (global half *) mask_pad_void;
84
+ const ulong dst_idx =
85
+ (((ulong) mask_batch_idx * (ulong) mask_ne2 + (ulong) mask_head_idx) * (ulong) n_q + (ulong) q_row) * (ulong) BLOCK_N +
86
+ (ulong) col_idx;
87
+
88
+ mask_pad[dst_idx] = src_col_idx < n_kv ? mask_src[src_col_idx] : (half) (-INFINITY);
89
+ }
90
+
91
+ // Per-KV-tile mask class. 0=all -inf (skip tile), 1=mixed (apply mask),
92
+ // 2=all zero, no -inf (skip mask lookup). Causal diagonal tiles are class 1.
93
+ __kernel void flash_attn_blk_f16(
94
+ const global void * mask_void, ulong mask_offset,
95
+ global char * blk,
96
+ const int n_q,
97
+ const int n_kv,
98
+ const ulong mask_nb1,
99
+ const ulong mask_nb2,
100
+ const ulong mask_nb3,
101
+ const int mask_ne2,
102
+ const int mask_ne3
103
+ ) {
104
+ const int kv_block_idx = get_global_id(0);
105
+ const int q_block_idx = get_global_id(1);
106
+ const int mask_slice = get_global_id(2);
107
+
108
+ const int n_q_blocks = (n_q + BLOCK_M - 1) / BLOCK_M;
109
+ const int n_kv_blocks = (n_kv + BLOCK_N - 1) / BLOCK_N;
110
+ if (kv_block_idx >= n_kv_blocks || q_block_idx >= n_q_blocks || mask_slice >= mask_ne2 * mask_ne3) {
111
+ return;
112
+ }
113
+
114
+ const int mask_head_idx = mask_slice % mask_ne2;
115
+ const int mask_batch_idx = mask_slice / mask_ne2;
116
+ const int q_start = q_block_idx * BLOCK_M;
117
+ const int k_start = kv_block_idx * BLOCK_N;
118
+ const int q_count = min(BLOCK_M, n_q - q_start);
119
+ const int k_count = min(BLOCK_N, n_kv - k_start);
120
+
121
+ const half neg_max_half = (half) (-65504.0f);
122
+ char has_unmasked = 0;
123
+ char has_masked = 0;
124
+ char has_nonzero = 0;
125
+
126
+ const global char * mask_base = (const global char *) mask_void + mask_offset +
127
+ (ulong) mask_batch_idx * mask_nb3 +
128
+ (ulong) mask_head_idx * mask_nb2;
129
+
130
+ for (int qi = 0; qi < q_count; ++qi) {
131
+ const global half * mask_row = (const global half *) (mask_base + (ulong) (q_start + qi) * mask_nb1) + k_start;
132
+ for (int ki = 0; ki < k_count; ++ki) {
133
+ const half v = mask_row[ki];
134
+ if (v <= neg_max_half) {
135
+ has_masked = 1;
136
+ } else {
137
+ has_unmasked = 1;
138
+ if (v != (half) 0.0f) {
139
+ has_nonzero = 1;
140
+ }
141
+ }
142
+ }
143
+ if (has_masked && has_unmasked) break; // mixed tile — short-circuit.
144
+ }
145
+
146
+ char res;
147
+ if (has_unmasked == 0) {
148
+ res = 0;
149
+ } else if (has_masked || has_nonzero) {
150
+ res = 1;
151
+ } else {
152
+ res = 2;
153
+ }
154
+
155
+ blk[((ulong) mask_slice * (ulong) n_q_blocks + (ulong) q_block_idx) * (ulong) n_kv_blocks + (ulong) kv_block_idx] = res;
156
+ }
@@ -132,6 +132,46 @@ static inline half8 mxfp4_to_fp16_packed8(ushort2 fp4x8) {
132
132
  c_reg.lo += convert_float8(acc.lo); \
133
133
  c_reg.hi += convert_float8(acc.hi); \
134
134
 
135
+ // Quarter-tile variant: computes 8 output columns (one skip-group) into a float8
136
+ // accumulator. Same reduction order / flush cadence as dotx16_reduce8, so the
137
+ // non-skipped path is byte-identical; it just lets the caller skip empty
138
+ // 8-column groups at finer granularity. Uses a private half8 `acc8`.
139
+ #define dotx8_reduce4(a_reg, b_lm, c_reg, lm_offset) \
140
+ acc8.s0 = dot(a_reg.s0123, b_lm[lm_offset + 0]); \
141
+ acc8.s1 = dot(a_reg.s0123, b_lm[lm_offset + 1]); \
142
+ acc8.s2 = dot(a_reg.s0123, b_lm[lm_offset + 2]); \
143
+ acc8.s3 = dot(a_reg.s0123, b_lm[lm_offset + 3]); \
144
+ acc8.s4 = dot(a_reg.s0123, b_lm[lm_offset + 4]); \
145
+ acc8.s5 = dot(a_reg.s0123, b_lm[lm_offset + 5]); \
146
+ acc8.s6 = dot(a_reg.s0123, b_lm[lm_offset + 6]); \
147
+ acc8.s7 = dot(a_reg.s0123, b_lm[lm_offset + 7]); \
148
+ acc8.s0 += dot(a_reg.s4567, b_lm[lm_offset + 32]); \
149
+ acc8.s1 += dot(a_reg.s4567, b_lm[lm_offset + 33]); \
150
+ acc8.s2 += dot(a_reg.s4567, b_lm[lm_offset + 34]); \
151
+ acc8.s3 += dot(a_reg.s4567, b_lm[lm_offset + 35]); \
152
+ acc8.s4 += dot(a_reg.s4567, b_lm[lm_offset + 36]); \
153
+ acc8.s5 += dot(a_reg.s4567, b_lm[lm_offset + 37]); \
154
+ acc8.s6 += dot(a_reg.s4567, b_lm[lm_offset + 38]); \
155
+ acc8.s7 += dot(a_reg.s4567, b_lm[lm_offset + 39]); \
156
+ c_reg += convert_float8(acc8); \
157
+ acc8.s0 = dot(a_reg.s89ab, b_lm[lm_offset + 64]); \
158
+ acc8.s1 = dot(a_reg.s89ab, b_lm[lm_offset + 65]); \
159
+ acc8.s2 = dot(a_reg.s89ab, b_lm[lm_offset + 66]); \
160
+ acc8.s3 = dot(a_reg.s89ab, b_lm[lm_offset + 67]); \
161
+ acc8.s4 = dot(a_reg.s89ab, b_lm[lm_offset + 68]); \
162
+ acc8.s5 = dot(a_reg.s89ab, b_lm[lm_offset + 69]); \
163
+ acc8.s6 = dot(a_reg.s89ab, b_lm[lm_offset + 70]); \
164
+ acc8.s7 = dot(a_reg.s89ab, b_lm[lm_offset + 71]); \
165
+ acc8.s0 += dot(a_reg.scdef, b_lm[lm_offset + 96]); \
166
+ acc8.s1 += dot(a_reg.scdef, b_lm[lm_offset + 97]); \
167
+ acc8.s2 += dot(a_reg.scdef, b_lm[lm_offset + 98]); \
168
+ acc8.s3 += dot(a_reg.scdef, b_lm[lm_offset + 99]); \
169
+ acc8.s4 += dot(a_reg.scdef, b_lm[lm_offset + 100]); \
170
+ acc8.s5 += dot(a_reg.scdef, b_lm[lm_offset + 101]); \
171
+ acc8.s6 += dot(a_reg.scdef, b_lm[lm_offset + 102]); \
172
+ acc8.s7 += dot(a_reg.scdef, b_lm[lm_offset + 103]); \
173
+ c_reg += convert_float8(acc8); \
174
+
135
175
 
136
176
  static inline half e8m0_to_fp16(uchar x) {
137
177
  ushort bits;
@@ -157,7 +197,9 @@ kernel void kernel_gemm_moe_mxfp4_f32_ns(
157
197
  __write_only image1d_buffer_t dst,
158
198
  __global int * total_tiles,
159
199
  uint ne00,
160
- uint ne01
200
+ uint ne01,
201
+ uint is_ragged,
202
+ uint skip_gran
161
203
  ) {
162
204
  uint block_id_m = get_global_id(1); // m_tile
163
205
  uint block_id_n = get_global_id(2); // n_tile
@@ -167,6 +209,28 @@ kernel void kernel_gemm_moe_mxfp4_f32_ns(
167
209
  return;
168
210
  }
169
211
 
212
+ // Ragged tile-skip: when is_ragged and the upper 16 token-slots of this tile are all
213
+ // padding (router 0xFFFFFFFF), skip the second (reg_c.hi) dotx16_reduce8 half -> ~half
214
+ // the GEMM dot for sparse tiles. Numerically identical (the skipped lanes are padding).
215
+ // Ragged tile-skip: tokens are packed contiguously per expert (moe_scatter fills
216
+ // lanes 0..V-1, moe_fill pre-pads the rest), so router padding (0xFFFFFFFF) is always
217
+ // trailing. Find the valid-token count V and round it UP to the skip granularity
218
+ // skip_gran (columns per skip-group: 8 = quarter, 16 = half/legacy, 32 = disabled).
219
+ // A 8-column group g is all-padding iff its first column (8*g) >= n_active, so its
220
+ // dotx8_reduce4 is skipped. Numerically identical (skipped lanes are padding).
221
+ uint n_active = TILESIZE_N;
222
+ if (is_ragged && skip_gran < TILESIZE_N) {
223
+ uint n_valid = TILESIZE_N;
224
+ for (uint _t = 0; _t < TILESIZE_N; ++_t) {
225
+ if (src2[block_id_n * TILESIZE_N + _t] == 0xFFFFFFFFu) { n_valid = _t; break; }
226
+ }
227
+ n_active = min((uint)TILESIZE_N, ((n_valid + skip_gran - 1) / skip_gran) * skip_gran);
228
+ }
229
+ // Group 0 (cols 0-7) always runs; groups 1-3 skip when fully padding.
230
+ bool skip_g1 = (8u >= n_active);
231
+ bool skip_g2 = (16u >= n_active);
232
+ bool skip_g3 = (24u >= n_active);
233
+
170
234
  __private half16 reg_a;
171
235
  __private float32 reg_c = (float32)(0);
172
236
  __local half4 shared_b[128];
@@ -216,9 +280,11 @@ kernel void kernel_gemm_moe_mxfp4_f32_ns(
216
280
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
217
281
 
218
282
  // 32 16x16 fp16 dot product with 8 elements reduction for better precision
219
- half16 acc;
220
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
221
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
283
+ half8 acc8;
284
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
285
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
286
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
287
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
222
288
 
223
289
  // Repeat for second sub-block
224
290
  uint half_step = step + TILESIZE_K;
@@ -244,8 +310,10 @@ kernel void kernel_gemm_moe_mxfp4_f32_ns(
244
310
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
245
311
 
246
312
  // 32 16x16 fp16 dot product with 3-levels reduction for better precision
247
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
248
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
313
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
314
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
315
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
316
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
249
317
  }
250
318
 
251
319
  if ((get_global_id(0) + block_id_m * TILESIZE_M) >= ne01) {
@@ -98,6 +98,46 @@
98
98
  c_reg.lo += convert_float8(acc.lo); \
99
99
  c_reg.hi += convert_float8(acc.hi); \
100
100
 
101
+ // Quarter-tile variant: computes 8 output columns (one skip-group) into a float8
102
+ // accumulator. Same reduction order / flush cadence as dotx16_reduce8, so the
103
+ // non-skipped path is byte-identical; it just lets the caller skip empty
104
+ // 8-column groups at finer granularity. Uses a private half8 `acc8`.
105
+ #define dotx8_reduce4(a_reg, b_lm, c_reg, lm_offset) \
106
+ acc8.s0 = dot(a_reg.s0123, b_lm[lm_offset + 0]); \
107
+ acc8.s1 = dot(a_reg.s0123, b_lm[lm_offset + 1]); \
108
+ acc8.s2 = dot(a_reg.s0123, b_lm[lm_offset + 2]); \
109
+ acc8.s3 = dot(a_reg.s0123, b_lm[lm_offset + 3]); \
110
+ acc8.s4 = dot(a_reg.s0123, b_lm[lm_offset + 4]); \
111
+ acc8.s5 = dot(a_reg.s0123, b_lm[lm_offset + 5]); \
112
+ acc8.s6 = dot(a_reg.s0123, b_lm[lm_offset + 6]); \
113
+ acc8.s7 = dot(a_reg.s0123, b_lm[lm_offset + 7]); \
114
+ acc8.s0 += dot(a_reg.s4567, b_lm[lm_offset + 32]); \
115
+ acc8.s1 += dot(a_reg.s4567, b_lm[lm_offset + 33]); \
116
+ acc8.s2 += dot(a_reg.s4567, b_lm[lm_offset + 34]); \
117
+ acc8.s3 += dot(a_reg.s4567, b_lm[lm_offset + 35]); \
118
+ acc8.s4 += dot(a_reg.s4567, b_lm[lm_offset + 36]); \
119
+ acc8.s5 += dot(a_reg.s4567, b_lm[lm_offset + 37]); \
120
+ acc8.s6 += dot(a_reg.s4567, b_lm[lm_offset + 38]); \
121
+ acc8.s7 += dot(a_reg.s4567, b_lm[lm_offset + 39]); \
122
+ c_reg += convert_float8(acc8); \
123
+ acc8.s0 = dot(a_reg.s89ab, b_lm[lm_offset + 64]); \
124
+ acc8.s1 = dot(a_reg.s89ab, b_lm[lm_offset + 65]); \
125
+ acc8.s2 = dot(a_reg.s89ab, b_lm[lm_offset + 66]); \
126
+ acc8.s3 = dot(a_reg.s89ab, b_lm[lm_offset + 67]); \
127
+ acc8.s4 = dot(a_reg.s89ab, b_lm[lm_offset + 68]); \
128
+ acc8.s5 = dot(a_reg.s89ab, b_lm[lm_offset + 69]); \
129
+ acc8.s6 = dot(a_reg.s89ab, b_lm[lm_offset + 70]); \
130
+ acc8.s7 = dot(a_reg.s89ab, b_lm[lm_offset + 71]); \
131
+ acc8.s0 += dot(a_reg.scdef, b_lm[lm_offset + 96]); \
132
+ acc8.s1 += dot(a_reg.scdef, b_lm[lm_offset + 97]); \
133
+ acc8.s2 += dot(a_reg.scdef, b_lm[lm_offset + 98]); \
134
+ acc8.s3 += dot(a_reg.scdef, b_lm[lm_offset + 99]); \
135
+ acc8.s4 += dot(a_reg.scdef, b_lm[lm_offset + 100]); \
136
+ acc8.s5 += dot(a_reg.scdef, b_lm[lm_offset + 101]); \
137
+ acc8.s6 += dot(a_reg.scdef, b_lm[lm_offset + 102]); \
138
+ acc8.s7 += dot(a_reg.scdef, b_lm[lm_offset + 103]); \
139
+ c_reg += convert_float8(acc8); \
140
+
101
141
 
102
142
  __attribute__((qcom_wave_pair_mode(1))) // 1=force single 2=force pair
103
143
  kernel void kernel_gemm_moe_q4_0_f32_ns(
@@ -109,7 +149,9 @@ kernel void kernel_gemm_moe_q4_0_f32_ns(
109
149
  __write_only image1d_buffer_t dst,
110
150
  __global int * total_tiles,
111
151
  uint ne00,
112
- uint ne01
152
+ uint ne01,
153
+ uint is_ragged,
154
+ uint skip_gran
113
155
  ) {
114
156
  uint block_id_m = get_global_id(1); // m_tile
115
157
  uint block_id_n = get_global_id(2); // n_tile
@@ -119,6 +161,28 @@ kernel void kernel_gemm_moe_q4_0_f32_ns(
119
161
  return;
120
162
  }
121
163
 
164
+ // Ragged tile-skip: when is_ragged and the upper 16 token-slots of this tile are all
165
+ // padding (router 0xFFFFFFFF), skip the second (reg_c.hi) dotx16_reduce8 half -> ~half
166
+ // the GEMM dot for sparse tiles. Numerically identical (the skipped lanes are padding).
167
+ // Ragged tile-skip: tokens are packed contiguously per expert (moe_scatter fills
168
+ // lanes 0..V-1, moe_fill pre-pads the rest), so router padding (0xFFFFFFFF) is always
169
+ // trailing. Find the valid-token count V and round it UP to the skip granularity
170
+ // skip_gran (columns per skip-group: 8 = quarter, 16 = half/legacy, 32 = disabled).
171
+ // A 8-column group g is all-padding iff its first column (8*g) >= n_active, so its
172
+ // dotx8_reduce4 is skipped. Numerically identical (skipped lanes are padding).
173
+ uint n_active = TILESIZE_N;
174
+ if (is_ragged && skip_gran < TILESIZE_N) {
175
+ uint n_valid = TILESIZE_N;
176
+ for (uint _t = 0; _t < TILESIZE_N; ++_t) {
177
+ if (src2[block_id_n * TILESIZE_N + _t] == 0xFFFFFFFFu) { n_valid = _t; break; }
178
+ }
179
+ n_active = min((uint)TILESIZE_N, ((n_valid + skip_gran - 1) / skip_gran) * skip_gran);
180
+ }
181
+ // Group 0 (cols 0-7) always runs; groups 1-3 skip when fully padding.
182
+ bool skip_g1 = (8u >= n_active);
183
+ bool skip_g2 = (16u >= n_active);
184
+ bool skip_g3 = (24u >= n_active);
185
+
122
186
  __private half16 reg_a;
123
187
  __private float32 reg_c = (float32)(0);
124
188
  __local half4 shared_b[128];
@@ -167,9 +231,11 @@ kernel void kernel_gemm_moe_q4_0_f32_ns(
167
231
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
168
232
 
169
233
  // 32 16x16 fp16 dot product with 8 elements reduction for better precision
170
- half16 acc;
171
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
172
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
234
+ half8 acc8;
235
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
236
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
237
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
238
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
173
239
 
174
240
  // Repeat for second sub-block
175
241
  uint half_step = step + TILESIZE_K;
@@ -194,8 +260,10 @@ kernel void kernel_gemm_moe_q4_0_f32_ns(
194
260
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
195
261
 
196
262
  // 32 16x16 fp16 dot product with 3-levels reduction for better precision
197
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
198
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
263
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
264
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
265
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
266
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
199
267
  }
200
268
 
201
269
  if ((get_global_id(0) + block_id_m * TILESIZE_M) >= ne01) {
@@ -98,6 +98,46 @@
98
98
  c_reg.lo += convert_float8(acc.lo); \
99
99
  c_reg.hi += convert_float8(acc.hi); \
100
100
 
101
+ // Quarter-tile variant: computes 8 output columns (one skip-group) into a float8
102
+ // accumulator. Same reduction order / flush cadence as dotx16_reduce8, so the
103
+ // non-skipped path is byte-identical; it just lets the caller skip empty
104
+ // 8-column groups at finer granularity. Uses a private half8 `acc8`.
105
+ #define dotx8_reduce4(a_reg, b_lm, c_reg, lm_offset) \
106
+ acc8.s0 = dot(a_reg.s0123, b_lm[lm_offset + 0]); \
107
+ acc8.s1 = dot(a_reg.s0123, b_lm[lm_offset + 1]); \
108
+ acc8.s2 = dot(a_reg.s0123, b_lm[lm_offset + 2]); \
109
+ acc8.s3 = dot(a_reg.s0123, b_lm[lm_offset + 3]); \
110
+ acc8.s4 = dot(a_reg.s0123, b_lm[lm_offset + 4]); \
111
+ acc8.s5 = dot(a_reg.s0123, b_lm[lm_offset + 5]); \
112
+ acc8.s6 = dot(a_reg.s0123, b_lm[lm_offset + 6]); \
113
+ acc8.s7 = dot(a_reg.s0123, b_lm[lm_offset + 7]); \
114
+ acc8.s0 += dot(a_reg.s4567, b_lm[lm_offset + 32]); \
115
+ acc8.s1 += dot(a_reg.s4567, b_lm[lm_offset + 33]); \
116
+ acc8.s2 += dot(a_reg.s4567, b_lm[lm_offset + 34]); \
117
+ acc8.s3 += dot(a_reg.s4567, b_lm[lm_offset + 35]); \
118
+ acc8.s4 += dot(a_reg.s4567, b_lm[lm_offset + 36]); \
119
+ acc8.s5 += dot(a_reg.s4567, b_lm[lm_offset + 37]); \
120
+ acc8.s6 += dot(a_reg.s4567, b_lm[lm_offset + 38]); \
121
+ acc8.s7 += dot(a_reg.s4567, b_lm[lm_offset + 39]); \
122
+ c_reg += convert_float8(acc8); \
123
+ acc8.s0 = dot(a_reg.s89ab, b_lm[lm_offset + 64]); \
124
+ acc8.s1 = dot(a_reg.s89ab, b_lm[lm_offset + 65]); \
125
+ acc8.s2 = dot(a_reg.s89ab, b_lm[lm_offset + 66]); \
126
+ acc8.s3 = dot(a_reg.s89ab, b_lm[lm_offset + 67]); \
127
+ acc8.s4 = dot(a_reg.s89ab, b_lm[lm_offset + 68]); \
128
+ acc8.s5 = dot(a_reg.s89ab, b_lm[lm_offset + 69]); \
129
+ acc8.s6 = dot(a_reg.s89ab, b_lm[lm_offset + 70]); \
130
+ acc8.s7 = dot(a_reg.s89ab, b_lm[lm_offset + 71]); \
131
+ acc8.s0 += dot(a_reg.scdef, b_lm[lm_offset + 96]); \
132
+ acc8.s1 += dot(a_reg.scdef, b_lm[lm_offset + 97]); \
133
+ acc8.s2 += dot(a_reg.scdef, b_lm[lm_offset + 98]); \
134
+ acc8.s3 += dot(a_reg.scdef, b_lm[lm_offset + 99]); \
135
+ acc8.s4 += dot(a_reg.scdef, b_lm[lm_offset + 100]); \
136
+ acc8.s5 += dot(a_reg.scdef, b_lm[lm_offset + 101]); \
137
+ acc8.s6 += dot(a_reg.scdef, b_lm[lm_offset + 102]); \
138
+ acc8.s7 += dot(a_reg.scdef, b_lm[lm_offset + 103]); \
139
+ c_reg += convert_float8(acc8); \
140
+
101
141
 
102
142
  __attribute__((qcom_wave_pair_mode(1))) // 1=force single 2=force pair
103
143
  kernel void kernel_gemm_moe_q4_1_f32_ns(
@@ -110,7 +150,9 @@ kernel void kernel_gemm_moe_q4_1_f32_ns(
110
150
  __write_only image1d_buffer_t dst,
111
151
  __global int * total_tiles,
112
152
  uint ne00,
113
- uint ne01
153
+ uint ne01,
154
+ uint is_ragged,
155
+ uint skip_gran
114
156
  ) {
115
157
  uint block_id_m = get_global_id(1); // m_tile
116
158
  uint block_id_n = get_global_id(2); // n_tile
@@ -120,6 +162,28 @@ kernel void kernel_gemm_moe_q4_1_f32_ns(
120
162
  return;
121
163
  }
122
164
 
165
+ // Ragged tile-skip: when is_ragged and the upper 16 token-slots of this tile are all
166
+ // padding (router 0xFFFFFFFF), skip the second (reg_c.hi) dotx16_reduce8 half -> ~half
167
+ // the GEMM dot for sparse tiles. Numerically identical (the skipped lanes are padding).
168
+ // Ragged tile-skip: tokens are packed contiguously per expert (moe_scatter fills
169
+ // lanes 0..V-1, moe_fill pre-pads the rest), so router padding (0xFFFFFFFF) is always
170
+ // trailing. Find the valid-token count V and round it UP to the skip granularity
171
+ // skip_gran (columns per skip-group: 8 = quarter, 16 = half/legacy, 32 = disabled).
172
+ // A 8-column group g is all-padding iff its first column (8*g) >= n_active, so its
173
+ // dotx8_reduce4 is skipped. Numerically identical (skipped lanes are padding).
174
+ uint n_active = TILESIZE_N;
175
+ if (is_ragged && skip_gran < TILESIZE_N) {
176
+ uint n_valid = TILESIZE_N;
177
+ for (uint _t = 0; _t < TILESIZE_N; ++_t) {
178
+ if (src2[block_id_n * TILESIZE_N + _t] == 0xFFFFFFFFu) { n_valid = _t; break; }
179
+ }
180
+ n_active = min((uint)TILESIZE_N, ((n_valid + skip_gran - 1) / skip_gran) * skip_gran);
181
+ }
182
+ // Group 0 (cols 0-7) always runs; groups 1-3 skip when fully padding.
183
+ bool skip_g1 = (8u >= n_active);
184
+ bool skip_g2 = (16u >= n_active);
185
+ bool skip_g3 = (24u >= n_active);
186
+
123
187
  __private half16 reg_a;
124
188
  __private float32 reg_c = (float32)(0);
125
189
  __local half4 shared_b[128];
@@ -169,9 +233,11 @@ kernel void kernel_gemm_moe_q4_1_f32_ns(
169
233
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
170
234
 
171
235
  // 32 16x16 fp16 dot product with 8 elements reduction for better precision
172
- half16 acc;
173
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
174
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
236
+ half8 acc8;
237
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
238
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
239
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
240
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
175
241
 
176
242
  // Repeat for second sub-block
177
243
  uint half_step = step + TILESIZE_K;
@@ -196,8 +262,10 @@ kernel void kernel_gemm_moe_q4_1_f32_ns(
196
262
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
197
263
 
198
264
  // 32 16x16 fp16 dot product with 3-levels reduction for better precision
199
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
200
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
265
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
266
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
267
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
268
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
201
269
  }
202
270
 
203
271
  if ((get_global_id(0) + block_id_m * TILESIZE_M) >= ne01) {
@@ -114,6 +114,46 @@ inline void get_scale_min_k4(
114
114
  c_reg.lo += convert_float8(acc.lo); \
115
115
  c_reg.hi += convert_float8(acc.hi); \
116
116
 
117
+ // Quarter-tile variant: computes 8 output columns (one skip-group) into a float8
118
+ // accumulator. Same reduction order / flush cadence as dotx16_reduce8, so the
119
+ // non-skipped path is byte-identical; it just lets the caller skip empty
120
+ // 8-column groups at finer granularity. Uses a private half8 `acc8`.
121
+ #define dotx8_reduce4(a_reg, b_lm, c_reg, lm_offset) \
122
+ acc8.s0 = dot(a_reg.s0123, b_lm[lm_offset + 0]); \
123
+ acc8.s1 = dot(a_reg.s0123, b_lm[lm_offset + 1]); \
124
+ acc8.s2 = dot(a_reg.s0123, b_lm[lm_offset + 2]); \
125
+ acc8.s3 = dot(a_reg.s0123, b_lm[lm_offset + 3]); \
126
+ acc8.s4 = dot(a_reg.s0123, b_lm[lm_offset + 4]); \
127
+ acc8.s5 = dot(a_reg.s0123, b_lm[lm_offset + 5]); \
128
+ acc8.s6 = dot(a_reg.s0123, b_lm[lm_offset + 6]); \
129
+ acc8.s7 = dot(a_reg.s0123, b_lm[lm_offset + 7]); \
130
+ acc8.s0 += dot(a_reg.s4567, b_lm[lm_offset + 32]); \
131
+ acc8.s1 += dot(a_reg.s4567, b_lm[lm_offset + 33]); \
132
+ acc8.s2 += dot(a_reg.s4567, b_lm[lm_offset + 34]); \
133
+ acc8.s3 += dot(a_reg.s4567, b_lm[lm_offset + 35]); \
134
+ acc8.s4 += dot(a_reg.s4567, b_lm[lm_offset + 36]); \
135
+ acc8.s5 += dot(a_reg.s4567, b_lm[lm_offset + 37]); \
136
+ acc8.s6 += dot(a_reg.s4567, b_lm[lm_offset + 38]); \
137
+ acc8.s7 += dot(a_reg.s4567, b_lm[lm_offset + 39]); \
138
+ c_reg += convert_float8(acc8); \
139
+ acc8.s0 = dot(a_reg.s89ab, b_lm[lm_offset + 64]); \
140
+ acc8.s1 = dot(a_reg.s89ab, b_lm[lm_offset + 65]); \
141
+ acc8.s2 = dot(a_reg.s89ab, b_lm[lm_offset + 66]); \
142
+ acc8.s3 = dot(a_reg.s89ab, b_lm[lm_offset + 67]); \
143
+ acc8.s4 = dot(a_reg.s89ab, b_lm[lm_offset + 68]); \
144
+ acc8.s5 = dot(a_reg.s89ab, b_lm[lm_offset + 69]); \
145
+ acc8.s6 = dot(a_reg.s89ab, b_lm[lm_offset + 70]); \
146
+ acc8.s7 = dot(a_reg.s89ab, b_lm[lm_offset + 71]); \
147
+ acc8.s0 += dot(a_reg.scdef, b_lm[lm_offset + 96]); \
148
+ acc8.s1 += dot(a_reg.scdef, b_lm[lm_offset + 97]); \
149
+ acc8.s2 += dot(a_reg.scdef, b_lm[lm_offset + 98]); \
150
+ acc8.s3 += dot(a_reg.scdef, b_lm[lm_offset + 99]); \
151
+ acc8.s4 += dot(a_reg.scdef, b_lm[lm_offset + 100]); \
152
+ acc8.s5 += dot(a_reg.scdef, b_lm[lm_offset + 101]); \
153
+ acc8.s6 += dot(a_reg.scdef, b_lm[lm_offset + 102]); \
154
+ acc8.s7 += dot(a_reg.scdef, b_lm[lm_offset + 103]); \
155
+ c_reg += convert_float8(acc8); \
156
+
117
157
 
118
158
  __attribute__((qcom_wave_pair_mode(1)))
119
159
  kernel void kernel_gemm_moe_q4_k_f32_ns(
@@ -127,7 +167,9 @@ kernel void kernel_gemm_moe_q4_k_f32_ns(
127
167
  __write_only image1d_buffer_t dst,
128
168
  __global int * total_tiles,
129
169
  uint ne00,
130
- uint ne01
170
+ uint ne01,
171
+ uint is_ragged,
172
+ uint skip_gran
131
173
  ) {
132
174
  uint block_id_m = get_global_id(1); // m_tile
133
175
  uint block_id_n = get_global_id(2); // n_tile
@@ -137,6 +179,25 @@ kernel void kernel_gemm_moe_q4_k_f32_ns(
137
179
  return;
138
180
  }
139
181
 
182
+ // Ragged tile-skip: tokens are packed contiguously per expert (moe_scatter fills
183
+ // lanes 0..V-1, moe_fill pre-pads the rest), so router padding (0xFFFFFFFF) is always
184
+ // trailing. Find the valid-token count V and round it UP to the skip granularity
185
+ // skip_gran (columns per skip-group: 8 = quarter, 16 = half/legacy, 32 = disabled).
186
+ // A 8-column group g is all-padding iff its first column (8*g) >= n_active, so its
187
+ // dotx8_reduce4 is skipped. Numerically identical (skipped lanes are padding).
188
+ uint n_active = TILESIZE_N;
189
+ if (is_ragged && skip_gran < TILESIZE_N) {
190
+ uint n_valid = TILESIZE_N;
191
+ for (uint _t = 0; _t < TILESIZE_N; ++_t) {
192
+ if (src2[block_id_n * TILESIZE_N + _t] == 0xFFFFFFFFu) { n_valid = _t; break; }
193
+ }
194
+ n_active = min((uint)TILESIZE_N, ((n_valid + skip_gran - 1) / skip_gran) * skip_gran);
195
+ }
196
+ // Group 0 (cols 0-7) always runs; groups 1-3 skip when fully padding.
197
+ bool skip_g1 = (8u >= n_active);
198
+ bool skip_g2 = (16u >= n_active);
199
+ bool skip_g3 = (24u >= n_active);
200
+
140
201
  __private half16 reg_a;
141
202
  __private float32 reg_c = (float32)(0);
142
203
  __local half4 shared_b[128];
@@ -199,9 +260,11 @@ kernel void kernel_gemm_moe_q4_k_f32_ns(
199
260
 
200
261
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
201
262
 
202
- half16 acc;
203
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
204
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
263
+ half8 acc8;
264
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
265
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
266
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
267
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
205
268
 
206
269
  // Second half (next 16 elements, same sub-block scale)
207
270
  uint half_step = step + TILESIZE_K;
@@ -221,8 +284,10 @@ kernel void kernel_gemm_moe_q4_k_f32_ns(
221
284
 
222
285
  sub_group_barrier(CLK_LOCAL_MEM_FENCE);
223
286
 
224
- dotx16_reduce8(reg_a, shared_b, reg_c.lo, 0);
225
- dotx16_reduce8(reg_a, shared_b, reg_c.hi, 16);
287
+ dotx8_reduce4(reg_a, shared_b, reg_c.lo.lo, 0);
288
+ if (!skip_g1) { dotx8_reduce4(reg_a, shared_b, reg_c.lo.hi, 8); }
289
+ if (!skip_g2) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.lo, 16); }
290
+ if (!skip_g3) { dotx8_reduce4(reg_a, shared_b, reg_c.hi.hi, 24); }
226
291
  }
227
292
 
228
293
  if ((get_global_id(0) + block_id_m * TILESIZE_M) >= ne01) {