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
@@ -7,6 +7,7 @@
7
7
  #include <openvino/core/node.hpp>
8
8
  #include <openvino/core/node_output.hpp>
9
9
  #include <openvino/op/add.hpp>
10
+ #include <openvino/op/broadcast.hpp>
10
11
  #include <openvino/op/concat.hpp>
11
12
  #include <openvino/op/constant.hpp>
12
13
  #include <openvino/op/convert.hpp>
@@ -38,8 +39,7 @@ OutputVector translate_rope(const NodeContext & context) {
38
39
  auto data_node = context.get_input(0).get_node_shared_ptr();
39
40
  auto output_shape = context.get_output_shape().to_shape();
40
41
  int32_t * op_params = context.get_output_op_params();
41
- const int mode = (op_case & 0xFFFF0000) >> 16;
42
- op_case = (op_case & 0x0000FFFF);
42
+ const int mode = op_case;
43
43
 
44
44
  constexpr int TYPE_NORMAL = 0;
45
45
  constexpr int TYPE_NEOX = 1;
@@ -56,55 +56,146 @@ OutputVector translate_rope(const NodeContext & context) {
56
56
  if (context.get_input_size() == 3) {
57
57
  rope_freqs_weight = context.get_input(2).get_node_shared_ptr();
58
58
  }
59
- auto sin_cos = make_sin_cos(op_params, inp_pos, rope_freqs_weight, mode == TYPE_IMROPE);
59
+ auto sin_cos = make_sin_cos(op_params, inp_pos, rope_freqs_weight, mode == TYPE_IMROPE, false);
60
60
  sin_theta_node = sin_cos.first;
61
61
  cos_theta_node = sin_cos.second;
62
62
  }
63
63
 
64
- if (op_case == 2) {
65
- // The input comes from a VIEW
66
- int slice_len = output_shape[2] * output_shape[3];
67
- data_node = process_view_input(context, 0, slice_len).get_node_shared_ptr();
64
+ if (context.get_view_input_size(0) > 0) {
65
+ data_node = process_view_input_new(context, 0).get_node_shared_ptr();
68
66
  if (context.is_stateful()) {
69
67
  auto data_shape = ov::op::v0::Constant::create(
70
68
  ov::element::i64, {3}, std::vector<int64_t>{-1, (int64_t) output_shape[2], (int64_t) output_shape[3]});
71
69
  data_node = std::make_shared<ov::op::v1::Reshape>(data_node, data_shape, false);
72
70
  } else {
73
71
  auto data_shape = ov::op::v0::Constant::create(
74
- ov::element::i64, {4}, std::vector<int64_t>{1, -1, (int64_t) output_shape[2], (int64_t) output_shape[3]});
72
+ ov::element::i64, {4},
73
+ std::vector<int64_t>{1, -1, (int64_t) output_shape[2], (int64_t) output_shape[3]});
75
74
  data_node = std::make_shared<ov::op::v1::Reshape>(data_node, data_shape, false);
76
75
  }
77
76
  }
78
77
 
78
+ auto output_type = context.get_output_type();
79
+ if (data_node->get_element_type() != ov::element::f32) {
80
+ data_node = std::make_shared<ov::op::v0::Convert>(data_node, ov::element::f32);
81
+ }
82
+
83
+ // TODO(openvino-gpu-rope-fusion): TEMPORARY WORKAROUND - do NOT revert until the
84
+ // OpenVINO GPU plugin is updated.
85
+ //
86
+ // For TYPE_NORMAL rope (both stateful and stateless) we emit the Flux-style
87
+ // interleaved pattern below so the GPU plugin's RoPEFusionFlux matcher folds it
88
+ // into ov::op::internal::RoPE. The matcher requires rank-4 inputs, which is why
89
+ // the original even/odd Slice translation (kept in the `else if (mode ==
90
+ // TYPE_NORMAL)` branch below for reference) does not get fused.
91
+ //
92
+ // Once the GPU plugin's RoPE fusion is extended to also recognize the original
93
+ // even/odd Slice form, this Flux rewrite should be removed and both modes should
94
+ // be restored to the captured even/odd translation. Until then, keep both paths:
95
+ // the active Flux rewrite here and the previous translation preserved below.
79
96
  if (mode == TYPE_NORMAL) {
80
- auto neg_one = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1});
81
- auto zero = ov::op::v0::Constant::create(ov::element::i64, {1}, {0});
82
- auto one = ov::op::v0::Constant::create(ov::element::i64, {1}, {1});
83
- auto two = ov::op::v0::Constant::create(ov::element::i64, {1}, {2});
84
- auto end = ov::op::v0::Constant::create(ov::element::i64, {1}, {output_shape[3]});
85
- Output<Node> even_slice;
86
- Output<Node> odd_slice;
87
- int32_t unsqueeze_dim = context.is_stateful() ? 3 : 4;
88
- even_slice = std::make_shared<ov::op::v8::Slice>(data_node, zero, end, two, neg_one);
89
- odd_slice = std::make_shared<ov::op::v8::Slice>(data_node, one, end, two, neg_one);
90
-
91
- Output<Node> first_half =
92
- std::make_shared<ov::op::v1::Subtract>(std::make_shared<ov::op::v1::Multiply>(even_slice, cos_theta_node),
93
- std::make_shared<ov::op::v1::Multiply>(odd_slice, sin_theta_node));
94
- Output<Node> second_half =
95
- std::make_shared<ov::op::v1::Add>(std::make_shared<ov::op::v1::Multiply>(even_slice, sin_theta_node),
96
- std::make_shared<ov::op::v1::Multiply>(odd_slice, cos_theta_node));
97
-
98
- first_half = std::make_shared<ov::op::v0::Unsqueeze>(first_half,
99
- ov::op::v0::Constant::create(ov::element::i64, {1}, {unsqueeze_dim}));
100
- second_half = std::make_shared<ov::op::v0::Unsqueeze>(second_half,
101
- ov::op::v0::Constant::create(ov::element::i64, {1}, {unsqueeze_dim}));
102
- auto stack = std::make_shared<ov::op::v0::Concat>(OutputVector{first_half, second_half}, unsqueeze_dim);
103
-
104
- auto data_shape = ov::op::v0::Constant::create(
105
- ov::element::i64, {4}, std::vector<int64_t>{1, -1, (int64_t) output_shape[2], (int64_t) output_shape[3]});
106
- res = std::make_shared<ov::op::v1::Reshape>(stack, data_shape, false);
107
- } else if (mode == TYPE_NEOX) {
97
+ // Emit the Flux-style interleaved-RoPE pattern so the GPU plugin's
98
+ // RoPEFusionFlux matcher folds this subgraph into ov::op::internal::RoPE:
99
+ // x_paired = Reshape(x, [1, S, n_heads, head_size/2, 2])
100
+ // x0, x1 = Split(x_paired, axis=-1, num_splits=2)
101
+ // x1_neg = x1 * -1
102
+ // x_rotated = Reshape(Concat([x1_neg, x0], axis=-1), [1, S, n_heads, head_size])
103
+ // y = x * t_cos + x_rotated * t_sin
104
+ // Mathematically equivalent to the even/odd Slice form below.
105
+ //
106
+ // RoPEFusionFlux requires rank_equals(4) on x, t_cos and t_sin. The cos/sin
107
+ // tables are already built rank-4 ([1, S, 1, head_size/2]) for both modes. In
108
+ // stateful mode the data arrives rank-3 ([S, n_heads, head_size]), so lift it
109
+ // to rank-4 ([1, S, n_heads, head_size]) here. Stateful RoPE already produced
110
+ // rank-4 output, so downstream attention is unaffected.
111
+ if (context.is_stateful()) {
112
+ auto r4_shape = ov::op::v0::Constant::create(
113
+ ov::element::i64, {4},
114
+ std::vector<int64_t>{1, -1, (int64_t) output_shape[2], (int64_t) output_shape[3]});
115
+ data_node = std::make_shared<ov::op::v1::Reshape>(data_node, r4_shape, false);
116
+ }
117
+ const int64_t head_size = static_cast<int64_t>(output_shape[3]);
118
+ const int64_t n_heads = static_cast<int64_t>(output_shape[2]);
119
+ const int64_t half = head_size / 2;
120
+
121
+ auto neg_one_f = ov::op::v0::Constant::create(data_node->get_element_type(), ov::Shape{}, {-1.0f});
122
+
123
+ auto paired_shape =
124
+ ov::op::v0::Constant::create(ov::element::i64, {5}, std::vector<int64_t>{1, -1, n_heads, half, 2});
125
+ auto x_paired = std::make_shared<ov::op::v1::Reshape>(data_node, paired_shape, false);
126
+
127
+ auto split_axis = ov::op::v0::Constant::create(ov::element::i64, ov::Shape{}, {-1});
128
+ auto data_split = std::make_shared<ov::op::v1::Split>(x_paired, split_axis, 2);
129
+ Output<Node> x0 = data_split->outputs()[0];
130
+ Output<Node> x1 = data_split->outputs()[1];
131
+
132
+ auto x1_neg = std::make_shared<ov::op::v1::Multiply>(x1, neg_one_f);
133
+ auto x_rotated_paired = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{x1_neg, x0}, -1);
134
+
135
+ auto flat_shape =
136
+ ov::op::v0::Constant::create(ov::element::i64, {4}, std::vector<int64_t>{1, -1, n_heads, head_size});
137
+ auto x_rotated = std::make_shared<ov::op::v1::Reshape>(x_rotated_paired, flat_shape, false);
138
+
139
+ // Expand cos/sin from [..., head_size/2] to [..., head_size] by repeating each
140
+ // entry twice. Use special_zero on the final Reshape so the seq dim passes
141
+ // through dynamically. Final rank is 4 to satisfy the matcher's predicate.
142
+ auto expand_cos_sin = [&](Output<Node> cs) {
143
+ auto cs_unsq =
144
+ std::make_shared<ov::op::v0::Unsqueeze>(cs, ov::op::v0::Constant::create(ov::element::i64, {1}, {-1}));
145
+ auto bcast_target =
146
+ ov::op::v0::Constant::create(ov::element::i64, {5}, std::vector<int64_t>{1, 1, 1, half, 2});
147
+ auto bcast =
148
+ std::make_shared<ov::op::v3::Broadcast>(cs_unsq, bcast_target, ov::op::BroadcastType::BIDIRECTIONAL);
149
+ auto flat = ov::op::v0::Constant::create(ov::element::i64, {4}, std::vector<int64_t>{0, 0, 0, head_size});
150
+ return std::make_shared<ov::op::v1::Reshape>(bcast, flat, true);
151
+ };
152
+ Output<Node> cos_full = expand_cos_sin(cos_theta_node);
153
+ Output<Node> sin_full = expand_cos_sin(sin_theta_node);
154
+
155
+ auto y1 = std::make_shared<ov::op::v1::Multiply>(data_node, cos_full);
156
+ auto y2 = std::make_shared<ov::op::v1::Multiply>(x_rotated, sin_full);
157
+ res = std::make_shared<ov::op::v1::Add>(y1, y2);
158
+ }
159
+ // PRESERVED PREVIOUS TRANSLATION - Re-enable this branch (and remove the Flux branch above) once
160
+ // the GPU plugin's RoPE fusion is updated to recognize the even/odd Slice form;
161
+ // see the TODO(openvino-gpu-rope-fusion) note above. Do not delete.
162
+ //
163
+ // Original even/odd Slice form. In stateless mode it ran on rank-4 data
164
+ // ([1, S, n_heads, head_size]); in stateful mode on rank-3 data
165
+ // ([S, n_heads, head_size]). Either way it does not match RoPEFusionFlux
166
+ // (which needs rank-4 x in the interleaved layout), so the RoPE stays as
167
+ // discrete elementwise ops.
168
+ //
169
+ // } else if (mode == TYPE_NORMAL) {
170
+ // auto neg_one = ov::op::v0::Constant::create(ov::element::i64, {1}, {-1});
171
+ // auto zero = ov::op::v0::Constant::create(ov::element::i64, {1}, {0});
172
+ // auto one = ov::op::v0::Constant::create(ov::element::i64, {1}, {1});
173
+ // auto two = ov::op::v0::Constant::create(ov::element::i64, {1}, {2});
174
+ // auto end = ov::op::v0::Constant::create(ov::element::i64, {1}, {output_shape[3]});
175
+ // Output<Node> even_slice;
176
+ // Output<Node> odd_slice;
177
+ // // stateful data is rank 3 (unsqueeze at axis 3), stateless is rank 4 (axis 4)
178
+ // int32_t unsqueeze_dim = context.is_stateful() ? 3 : 4;
179
+ // even_slice = std::make_shared<ov::op::v8::Slice>(data_node, zero, end, two, neg_one);
180
+ // odd_slice = std::make_shared<ov::op::v8::Slice>(data_node, one, end, two, neg_one);
181
+ //
182
+ // Output<Node> first_half =
183
+ // std::make_shared<ov::op::v1::Subtract>(std::make_shared<ov::op::v1::Multiply>(even_slice, cos_theta_node),
184
+ // std::make_shared<ov::op::v1::Multiply>(odd_slice, sin_theta_node));
185
+ // Output<Node> second_half =
186
+ // std::make_shared<ov::op::v1::Add>(std::make_shared<ov::op::v1::Multiply>(even_slice, sin_theta_node),
187
+ // std::make_shared<ov::op::v1::Multiply>(odd_slice, cos_theta_node));
188
+ //
189
+ // first_half = std::make_shared<ov::op::v0::Unsqueeze>(first_half,
190
+ // ov::op::v0::Constant::create(ov::element::i64, {1}, {unsqueeze_dim}));
191
+ // second_half = std::make_shared<ov::op::v0::Unsqueeze>(second_half,
192
+ // ov::op::v0::Constant::create(ov::element::i64, {1}, {unsqueeze_dim}));
193
+ // auto stack = std::make_shared<ov::op::v0::Concat>(OutputVector{first_half, second_half}, unsqueeze_dim);
194
+ //
195
+ // auto data_shape = ov::op::v0::Constant::create(
196
+ // ov::element::i64, {4}, std::vector<int64_t>{1, -1, (int64_t) output_shape[2], (int64_t) output_shape[3]});
197
+ // res = std::make_shared<ov::op::v1::Reshape>(stack, data_shape, false);
198
+ else if (mode == TYPE_NEOX) {
108
199
  auto data_split = std::make_shared<ov::op::v1::Split>(
109
200
  data_node, ov::op::v0::Constant::create(ov::element::i64, ov::Shape{}, {-1}), 2);
110
201
  Output<Node> slice_data_node_0 = data_split->outputs()[0];
@@ -120,8 +211,9 @@ OutputVector translate_rope(const NodeContext & context) {
120
211
 
121
212
  res = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{first_half_node, second_half_node}, -1);
122
213
  } else if (mode == TYPE_IMROPE) {
123
- int64_t n_dims = data_node->get_shape()[3];
124
- auto cos_sin_shape = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{4}, std::vector<int64_t>{1,-1,1,(n_dims >> 1)});
214
+ int64_t n_dims = data_node->get_output_partial_shape(0)[3].get_length();
215
+ auto cos_sin_shape = std::make_shared<ov::op::v0::Constant>(ov::element::i64, ov::Shape{4},
216
+ std::vector<int64_t>{1, -1, 1, (n_dims >> 1)});
125
217
  auto cos_reshaped = std::make_shared<ov::op::v1::Reshape>(cos_theta_node, cos_sin_shape, true);
126
218
  auto sin_reshaped = std::make_shared<ov::op::v1::Reshape>(sin_theta_node, cos_sin_shape, true);
127
219
 
@@ -140,6 +232,10 @@ OutputVector translate_rope(const NodeContext & context) {
140
232
  res = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{sub, add}, 3);
141
233
  }
142
234
 
235
+ if (res.get_element_type() != output_type) {
236
+ res = std::make_shared<ov::op::v0::Convert>(res, output_type);
237
+ }
238
+
143
239
  return rename_outputs_with_suffix({res}, context.get_name());
144
240
  }
145
241
 
@@ -28,20 +28,20 @@ namespace op {
28
28
  OutputVector translate_set_rows(const NodeContext & context) {
29
29
  num_inputs_check(context, 3, 3);
30
30
 
31
- auto data = context.get_input(0);
31
+ auto data = process_view_input_new(context, 0);
32
32
  auto indices = context.get_input(1);
33
33
  auto dst = context.get_input(2);
34
34
 
35
35
  data = std::make_shared<ov::op::v0::Convert>(data, context.get_output_type());
36
36
 
37
- auto dst_shape = context.get_output_shape().to_shape();
37
+ auto row_size = context.get_input_shape(2)[3].get_length();
38
38
 
39
39
  auto ind_squeezed =
40
40
  std::make_shared<ov::op::v0::Squeeze>(indices, ov::op::v0::Constant::create(ov::element::i64, {3}, {0, 1, 2}));
41
41
  auto data_reshaped = std::make_shared<ov::op::v1::Reshape>(
42
42
  data,
43
43
  ov::op::v0::Constant::create(ov::element::i64, {4},
44
- {(int64_t) 1, (int64_t) 1, (int64_t) -1, (int64_t) dst_shape[3]}),
44
+ {(int64_t) 1, (int64_t) 1, (int64_t) -1, (int64_t) row_size}),
45
45
  false);
46
46
  auto axes = ov::op::v0::Constant::create(ov::element::i64, ov::Shape{}, {2});
47
47
 
@@ -2,17 +2,19 @@
2
2
  #include "../op_table.h"
3
3
  #include "../utils.h"
4
4
 
5
- #include <climits>
5
+ #include <cmath>
6
6
  #include <cstdint>
7
+ #include <cstring>
7
8
  #include <memory>
8
- #include <openvino/core/node.hpp>
9
- #include <openvino/core/node_output.hpp>
9
+ #include <openvino/op/broadcast.hpp>
10
+ #include <openvino/frontend/exception.hpp>
10
11
  #include <openvino/op/add.hpp>
11
12
  #include <openvino/op/concat.hpp>
12
13
  #include <openvino/op/constant.hpp>
13
14
  #include <openvino/op/convert.hpp>
14
- #include <openvino/op/matmul.hpp>
15
15
  #include <openvino/op/multiply.hpp>
16
+ #include <openvino/op/reshape.hpp>
17
+ #include <openvino/op/shape_of.hpp>
16
18
  #include <openvino/op/slice.hpp>
17
19
  #include <openvino/op/softmax.hpp>
18
20
  #include <vector>
@@ -22,63 +24,138 @@ namespace frontend {
22
24
  namespace ggml {
23
25
  namespace op {
24
26
 
25
- OutputVector translate_soft_max(const NodeContext & context) {
26
- // TODO code is outdated
27
- num_inputs_check(context, 1, 2);
27
+ static bool is_static_one(const ov::Dimension & dim) {
28
+ return dim.is_static() && dim.get_length() == 1;
29
+ }
30
+
31
+ static bool same_static_dim(const ov::Dimension & lhs, const ov::Dimension & rhs) {
32
+ return lhs.is_static() && rhs.is_static() && lhs.get_length() == rhs.get_length();
33
+ }
34
+
35
+ static bool is_attention_sinks_input_shape(const ov::PartialShape & candidate, const ov::PartialShape & logits_shape) {
36
+ if (candidate.rank().is_dynamic() || logits_shape.rank().is_dynamic() || candidate.rank().get_length() != 4 ||
37
+ logits_shape.rank().get_length() != 4) {
38
+ return false;
39
+ }
40
+
41
+ return is_static_one(candidate[0]) && is_static_one(candidate[1]) && is_static_one(candidate[2]) &&
42
+ same_static_dim(candidate[3], logits_shape[1]);
43
+ }
28
44
 
29
- auto input_node = context.get_input(0).get_node_shared_ptr();
30
- ov::Output<Node> res;
45
+ // Reimplementation of GGML_OP_SOFT_MAX semantics for OpenVINO backend:
46
+ // 1) logits = src0 * scale
47
+ // 2) logits += mask (if provided)
48
+ // 3) append attention sinks as hidden logits (if provided)
49
+ // 4) softmax over the last dimension and remove the hidden sink column
50
+ OutputVector translate_soft_max(const NodeContext & context) {
51
+ num_inputs_check(context, 1, 3);
31
52
 
32
53
  float scale = 1.0f;
33
54
  float max_bias = 0.0f;
34
- auto * op_params = context.get_output_op_params();
35
- memcpy(&scale, (float *) op_params + 0, sizeof(float));
36
- memcpy(&max_bias, (float *) op_params + 1, sizeof(float));
37
- auto src0_shape = context.get_input_shape(0).get_shape();
38
- const uint32_t h = src0_shape[2];
39
- const uint32_t n_head = src0_shape[0];
40
- const uint32_t n_head_log2 = 1u << (uint32_t) floor(log2(n_head));
41
-
42
- const float m0 = powf(2.0f, -(max_bias) / n_head_log2);
43
- const float m1 = powf(2.0f, -(max_bias / 2.0f) / n_head_log2);
44
- const float slope =
45
- (max_bias > 0.0f) ? h < n_head_log2 ? powf(m0, h + 1) : powf(m1, 2 * (h - n_head_log2) + 1) : 1.0f;
46
-
47
- auto scale_node = std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{}, std::vector<float>{scale});
48
- auto scaled_input = std::make_shared<ov::op::v1::Multiply>(input_node, scale_node);
49
-
50
- if (context.get_input_size() < 2) {
51
- res = std::make_shared<ov::op::v8::Softmax>(scaled_input, 2);
52
- return rename_outputs_with_suffix({res}, context.get_name());
55
+ memcpy(&scale, (float *) context.get_output_op_params() + 0, sizeof(float));
56
+ memcpy(&max_bias, (float *) context.get_output_op_params() + 1, sizeof(float));
57
+
58
+ ov::Output<ov::Node> logits = context.get_input(0);
59
+ const bool second_input_is_sinks =
60
+ context.get_input_size() == 2 && is_attention_sinks_input_shape(context.get_input_shape(1), context.get_output_shape());
61
+ const bool has_mask = context.get_input_size() > 1 && !second_input_is_sinks;
62
+ const bool has_sinks = second_input_is_sinks || context.get_input_size() > 2;
63
+ const size_t sinks_input_idx = second_input_is_sinks ? 1 : 2;
64
+
65
+ // Apply scale first: logits = src0 * scale
66
+ if (scale != 1.0f) {
67
+ auto scale_const =
68
+ std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{}, std::vector<float>{scale});
69
+ logits = std::make_shared<ov::op::v1::Multiply>(logits, scale_const);
53
70
  }
54
71
 
55
- ov::Output<ov::Node> mask_node_sliced;
56
- if (context.has_input("KQ_mask_sliced")) {
57
- mask_node_sliced = context.get_input("KQ_mask_sliced");
58
- } else {
59
- auto token_len = get_dimensions(input_node, {1});
60
- auto mask_node = context.get_input(1);
72
+ FRONT_END_CHECK_IMPLEMENTED(!(max_bias > 0.0f && !has_mask),
73
+ "OpenVINO softmax ALiBi path requires mask input");
74
+
75
+ // Optional mask add: logits += mask
76
+ // For max_bias > 0 (ALiBi), apply per-head slope to mask before adding.
77
+ if (has_mask) {
78
+ ov::Output<ov::Node> mask = context.get_input(1);
79
+
80
+ // For stateful
81
+ std::string mask_name = "KQ_mask_sliced";
82
+ if (context.get_input_names()[1].find("swa") != std::string::npos) {
83
+ mask_name = "KQ_mask_swa_sliced";
84
+ }
85
+ if (context.has_input(mask_name)) {
86
+ mask = context.get_input(mask_name);
87
+ }
88
+
89
+ if (mask.get_element_type() != logits.get_element_type()) {
90
+ mask = std::make_shared<ov::op::v0::Convert>(mask, logits.get_element_type());
91
+ }
92
+
93
+ if (max_bias > 0.0f) {
94
+ auto out_shape = context.get_output_shape().to_shape();
95
+ FRONT_END_CHECK_IMPLEMENTED(out_shape.size() == 4, "OpenVINO softmax ALiBi path expects rank-4 tensor");
96
+
97
+ const uint32_t n_head = static_cast<uint32_t>(out_shape[1]);
98
+ FRONT_END_CHECK_IMPLEMENTED(n_head > 0, "OpenVINO softmax ALiBi path expects n_head > 0");
99
+
100
+ const uint32_t n_head_log2 = 1u << static_cast<uint32_t>(std::floor(std::log2(static_cast<float>(n_head))));
101
+ const float m0 = std::pow(2.0f, -(max_bias) / static_cast<float>(n_head_log2));
102
+ const float m1 = std::pow(2.0f, -(max_bias / 2.0f) / static_cast<float>(n_head_log2));
103
+
104
+ std::vector<float> slopes(n_head);
105
+ for (uint32_t h = 0; h < n_head; ++h) {
106
+ slopes[h] = h < n_head_log2 ? std::pow(m0, static_cast<float>(h + 1)) :
107
+ std::pow(m1, static_cast<float>(2 * (h - n_head_log2) + 1));
108
+ }
109
+
110
+ ov::Output<ov::Node> slope_node =
111
+ std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{n_head}, slopes);
112
+ if (slope_node.get_element_type() != mask.get_element_type()) {
113
+ slope_node = std::make_shared<ov::op::v0::Convert>(slope_node, mask.get_element_type());
114
+ }
115
+
116
+ auto slope_shape = std::make_shared<ov::op::v0::Constant>(
117
+ ov::element::i64, ov::Shape{4}, std::vector<int64_t>{1, static_cast<int64_t>(n_head), 1, 1});
118
+ auto slope_4d = std::make_shared<ov::op::v1::Reshape>(slope_node, slope_shape, false);
119
+ mask = std::make_shared<ov::op::v1::Multiply>(mask, slope_4d);
120
+ }
121
+
122
+ logits = std::make_shared<ov::op::v1::Add>(logits, mask);
123
+ }
124
+
125
+ ov::Output<ov::Node> softmax_input = logits;
126
+ if (has_sinks) {
127
+ ov::Output<ov::Node> sinks = context.get_input(sinks_input_idx);
128
+ if (sinks.get_element_type() != logits.get_element_type()) {
129
+ sinks = std::make_shared<ov::op::v0::Convert>(sinks, logits.get_element_type());
130
+ }
131
+
132
+ auto sink_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, {1, -1, 1, 1});
133
+ auto sinks_4d = std::make_shared<ov::op::v1::Reshape>(sinks, sink_shape, false);
134
+
135
+ auto logits_shape = std::make_shared<ov::op::v3::ShapeOf>(logits, ov::element::i64);
61
136
  auto zero = ov::op::v0::Constant::create(ov::element::i64, {1}, {0});
62
137
  auto one = ov::op::v0::Constant::create(ov::element::i64, {1}, {1});
63
- mask_node_sliced = std::make_shared<ov::op::v8::Slice>(mask_node, zero, token_len, one, one);
64
- }
138
+ auto three = ov::op::v0::Constant::create(ov::element::i64, {1}, {3});
139
+ auto four = ov::op::v0::Constant::create(ov::element::i64, {1}, {4});
140
+ auto shape_axis = ov::op::v0::Constant::create(ov::element::i64, {1}, {0});
65
141
 
66
- if (mask_node_sliced.get_element_type() != context.get_output_type()) {
67
- mask_node_sliced = std::make_shared<ov::op::v0::Convert>(mask_node_sliced, context.get_output_type());
68
- }
142
+ auto sink_prefix_shape = std::make_shared<ov::op::v8::Slice>(logits_shape, zero, three, one, shape_axis);
143
+ auto sink_last_dim = ov::op::v0::Constant::create(ov::element::i64, {1}, {1});
144
+ auto sink_broadcast_shape = std::make_shared<ov::op::v0::Concat>(
145
+ ov::OutputVector{sink_prefix_shape, sink_last_dim}, 0);
146
+ auto sink_column = std::make_shared<ov::op::v3::Broadcast>(sinks_4d, sink_broadcast_shape,
147
+ ov::op::BroadcastType::BIDIRECTIONAL);
148
+ softmax_input = std::make_shared<ov::op::v0::Concat>(ov::OutputVector{logits, sink_column}, 3);
69
149
 
70
- Output<Node> slope_mask;
71
- if (slope != 1.0f) {
72
- auto slope_node =
73
- std::make_shared<ov::op::v0::Constant>(ov::element::f32, ov::Shape{}, std::vector<float>{slope});
74
- slope_mask = std::make_shared<ov::op::v1::Multiply>(mask_node_sliced, slope_node);
75
- throw std::runtime_error("Slope != 1.0f in softmax has not been tested, verify it before use.");
76
- }
77
- slope_mask = mask_node_sliced;
150
+ auto softmax_with_sink = std::make_shared<ov::op::v8::Softmax>(softmax_input, -1);
151
+ auto original_last_dim = std::make_shared<ov::op::v8::Slice>(logits_shape, three, four, one, shape_axis);
152
+ auto res = std::make_shared<ov::op::v8::Slice>(softmax_with_sink, zero, original_last_dim, one, three);
78
153
 
79
- auto input_slope_mask_node = std::make_shared<ov::op::v1::Add>(scaled_input, slope_mask);
154
+ return rename_outputs_with_suffix({res}, context.get_name());
155
+ }
80
156
 
81
- res = std::make_shared<ov::op::v8::Softmax>(input_slope_mask_node, 2);
157
+ // Softmax along last dimension (equivalent to ggml softmax over ne[0]).
158
+ auto res = std::make_shared<ov::op::v8::Softmax>(softmax_input, -1);
82
159
 
83
160
  return rename_outputs_with_suffix({res}, context.get_name());
84
161
  }
@@ -0,0 +1,59 @@
1
+ #include "../node_context.h"
2
+ #include "../op_table.h"
3
+ #include "../utils.h"
4
+
5
+ #include <openvino/op/constant.hpp>
6
+ #include <openvino/op/group_conv.hpp>
7
+ #include <openvino/op/reshape.hpp>
8
+ #include <openvino/op/transpose.hpp>
9
+
10
+ namespace ov {
11
+ namespace frontend {
12
+ namespace ggml {
13
+ namespace op {
14
+
15
+ OutputVector translate_ssm_conv(const NodeContext & context) {
16
+ num_inputs_check(context, 2, 2);
17
+
18
+ auto sx = context.get_input(0); // conv state + input: OV shape [1, n_s, d_inner, ncs]
19
+ auto c = context.get_input(1); // conv1d weight: OV shape [1, 1, d_inner, d_conv]
20
+
21
+ auto sx_shape = context.get_input_shape(0).to_shape(); // [1, n_s, d_inner, ncs]
22
+ auto c_shape = context.get_input_shape(1).to_shape(); // [1, 1, d_inner, d_conv]
23
+
24
+ int64_t n_s = sx_shape[1];
25
+ int64_t d_inner = sx_shape[2];
26
+ int64_t ncs = sx_shape[3]; // d_conv - 1 + n_t
27
+ int64_t d_conv = c_shape[3];
28
+ int64_t n_t = ncs - d_conv + 1;
29
+
30
+ // Reshape sx from [1, n_s, d_inner, ncs] to [n_s, d_inner, ncs] for 1D GroupConvolution
31
+ auto sx_new_shape = ov::op::v0::Constant::create(ov::element::i64, {3}, std::vector<int64_t>{n_s, d_inner, ncs});
32
+ auto sx_reshaped = std::make_shared<ov::op::v1::Reshape>(sx, sx_new_shape, false);
33
+
34
+ // Reshape c from [1, 1, d_inner, d_conv] to [d_inner, 1, 1, d_conv]
35
+ // GroupConvolution filter: [groups, out_channels/groups, in_channels/groups, kernel_size]
36
+ auto c_new_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, std::vector<int64_t>{d_inner, 1, 1, d_conv});
37
+ auto c_reshaped = std::make_shared<ov::op::v1::Reshape>(c, c_new_shape, false);
38
+
39
+ // Depthwise 1D convolution: groups=d_inner, stride=1, no padding, no dilation
40
+ // Input: [n_s, d_inner, ncs], Filter: [d_inner, 1, 1, d_conv]
41
+ // Output: [n_s, d_inner, n_t]
42
+ auto conv = std::make_shared<ov::op::v1::GroupConvolution>(
43
+ sx_reshaped, c_reshaped, ov::Strides{1}, ov::CoordinateDiff{0}, ov::CoordinateDiff{0}, ov::Strides{1});
44
+
45
+ // Transpose from [n_s, d_inner, n_t] to [n_s, n_t, d_inner]
46
+ auto perm = ov::op::v0::Constant::create(ov::element::i64, {3}, std::vector<int64_t>{0, 2, 1});
47
+ auto transposed = std::make_shared<ov::op::v1::Transpose>(conv, perm);
48
+
49
+ // Reshape to output shape [1, n_s, n_t, d_inner]
50
+ auto out_shape = ov::op::v0::Constant::create(ov::element::i64, {4}, std::vector<int64_t>{1, n_s, n_t, d_inner});
51
+ auto res = std::make_shared<ov::op::v1::Reshape>(transposed, out_shape, false);
52
+
53
+ return rename_outputs_with_suffix({res}, context.get_name());
54
+ }
55
+
56
+ } // namespace op
57
+ } // namespace ggml
58
+ } // namespace frontend
59
+ } // namespace ov
@@ -0,0 +1,27 @@
1
+ #include "../node_context.h"
2
+ #include "../op_table.h"
3
+ #include "../utils.h"
4
+
5
+ #include <memory>
6
+ #include <openvino/op/constant.hpp>
7
+ #include <openvino/op/reduce_sum.hpp>
8
+
9
+ namespace ov {
10
+ namespace frontend {
11
+ namespace ggml {
12
+ namespace op {
13
+
14
+ OutputVector translate_sum_rows(const NodeContext & context) {
15
+ num_inputs_check(context, 1, 1);
16
+
17
+ auto input = process_view_input_new(context, 0);
18
+ auto res = std::make_shared<ov::op::v1::ReduceSum>(
19
+ input, ov::op::v0::Constant::create(ov::element::i64, ov::Shape{1}, {-1}), true);
20
+
21
+ return rename_outputs_with_suffix({res}, context.get_name());
22
+ }
23
+
24
+ } // namespace op
25
+ } // namespace ggml
26
+ } // namespace frontend
27
+ } // namespace ov
@@ -12,8 +12,39 @@ namespace op {
12
12
  OutputVector translate_transpose(const NodeContext & context) {
13
13
  num_inputs_check(context, 1, 1);
14
14
 
15
+ // Compute permute order from input/output shape and stride information
16
+ // so it adapts to different input and output layouts.
17
+ auto input_shape = context.get_input_shape(0).to_shape();
18
+ auto input_stride = context.get_input_stride(0);
19
+ auto output_shape = context.get_output_shape().to_shape();
20
+ auto output_stride = context.get_output_stride();
21
+
22
+ // Compute permute order by matching output and input stride rankings.
23
+ // Build <stride, dim_index> pairs.
24
+ std::vector<std::pair<size_t, int>> output_stride_dims;
25
+ std::vector<std::pair<size_t, int>> input_stride_dims;
26
+
27
+ for (int i = 0; i < 4; ++i) {
28
+ output_stride_dims.push_back({output_stride[i], i});
29
+ input_stride_dims.push_back({input_stride[i], i});
30
+ }
31
+
32
+ // Sort by stride in descending order.
33
+ std::sort(output_stride_dims.rbegin(), output_stride_dims.rend());
34
+ std::sort(input_stride_dims.rbegin(), input_stride_dims.rend());
35
+
36
+ // Build permute order.
37
+ std::vector<int64_t> permute_order(4);
38
+ for (int i = 0; i < 4; ++i) {
39
+ int output_dim = output_stride_dims[i].second;
40
+ int input_dim = input_stride_dims[i].second;
41
+ permute_order[output_dim] = input_dim;
42
+ }
43
+
44
+ auto input = process_view_input_new(context, 0);
45
+
15
46
  auto res = std::make_shared<ov::op::v1::Transpose>(
16
- context.get_input(0), ov::op::v0::Constant::create(ov::element::i64, {4}, {0, 1, 3, 2}));
47
+ input, ov::op::v0::Constant::create(ov::element::i64, {4}, permute_order));
17
48
  return rename_outputs_with_suffix({res}, context.get_name());
18
49
  }
19
50
 
@@ -14,7 +14,7 @@ namespace op {
14
14
  OutputVector translate_unary_silu(const NodeContext & context) {
15
15
  num_inputs_check(context, 1, 1);
16
16
 
17
- auto input = context.get_input(0);
17
+ auto input = process_view_input_new(context, 0);
18
18
  auto sigmoid = std::make_shared<ov::op::v0::Sigmoid>(input);
19
19
  auto res = std::make_shared<ov::op::v1::Multiply>(input, sigmoid);
20
20
 
@@ -0,0 +1,38 @@
1
+ #include "../node_context.h"
2
+ #include "../op_table.h"
3
+ #include "../utils.h"
4
+
5
+ #include <openvino/op/abs.hpp>
6
+ #include <openvino/op/add.hpp>
7
+ #include <openvino/op/constant.hpp>
8
+ #include <openvino/op/exp.hpp>
9
+ #include <openvino/op/log.hpp>
10
+ #include <openvino/op/negative.hpp>
11
+ #include <openvino/op/relu.hpp>
12
+
13
+ namespace ov {
14
+ namespace frontend {
15
+ namespace ggml {
16
+ namespace op {
17
+
18
+ OutputVector translate_unary_softplus(const NodeContext & context) {
19
+ num_inputs_check(context, 1, 1);
20
+
21
+ auto input = process_view_input_new(context, 0);
22
+ const auto element_type = input.get_element_type();
23
+ auto one = ov::op::v0::Constant::create(element_type, ov::Shape{}, {1.0f});
24
+
25
+ auto positive = std::make_shared<ov::op::v0::Relu>(input);
26
+ auto abs = std::make_shared<ov::op::v0::Abs>(input);
27
+ auto neg_abs = std::make_shared<ov::op::v0::Negative>(abs);
28
+ auto exp_neg_abs = std::make_shared<ov::op::v0::Exp>(neg_abs);
29
+ auto log_term = std::make_shared<ov::op::v0::Log>(std::make_shared<ov::op::v1::Add>(one, exp_neg_abs));
30
+ auto res = std::make_shared<ov::op::v1::Add>(positive, log_term);
31
+
32
+ return rename_outputs_with_suffix({res}, context.get_name());
33
+ }
34
+
35
+ } // namespace op
36
+ } // namespace ggml
37
+ } // namespace frontend
38
+ } // namespace ov