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
@@ -32,7 +32,7 @@
32
32
 
33
33
  #include <sycl/sycl.hpp>
34
34
  #include <sycl/backend.hpp>
35
- #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
35
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
36
36
  #include <level_zero/ze_api.h>
37
37
  #endif
38
38
  #if defined(GGML_SYCL_GRAPH) && SYCL_EXT_ONEAPI_ASYNC_MEMORY_ALLOC
@@ -41,7 +41,7 @@
41
41
  #if SYCL_EXT_ONEAPI_VIRTUAL_MEM
42
42
  # include <sycl/ext/oneapi/virtual_mem/physical_mem.hpp>
43
43
  # include <sycl/ext/oneapi/virtual_mem/virtual_mem.hpp>
44
- # define GGML_SYCL_USE_VMM
44
+ # define GGML_SYCL_SUPPORT_VMM
45
45
  #endif
46
46
  #include <sycl/half_type.hpp>
47
47
 
@@ -62,6 +62,9 @@
62
62
  #include "ggml-sycl/repeat_back.hpp"
63
63
  #include "ggml-sycl/set_rows.hpp"
64
64
  #include "ggml-sycl/set.hpp"
65
+ #include "ggml-sycl/conv2d.hpp"
66
+ #include "ggml-sycl/conv2d-dw.hpp"
67
+ #include "ggml-sycl/conv2d-transpose.hpp"
65
68
  #include "ggml-sycl/ssm_conv.hpp"
66
69
  #include "ggml-sycl/sycl_hw.hpp"
67
70
  #include "ggml-sycl/ssm_scan.hpp"
@@ -70,19 +73,25 @@
70
73
  #include "ggml-sycl/diag.hpp"
71
74
  #include "ggml-sycl/solve_tri.hpp"
72
75
  #include "ggml-sycl/gated_delta_net.hpp"
76
+ #include "ggml-sycl/pool.hpp"
77
+ #include "ggml-sycl/cross_entropy_loss.hpp"
78
+
79
+ #define MEM_SIZE_2M 0x00200000
80
+ #define MEM_SIZE_1G 0x40000000
73
81
 
74
82
  static bool g_sycl_loaded = false;
75
83
  int g_ggml_sycl_debug = 0;
76
- int g_ggml_sycl_disable_optimize = 0;
77
- int g_ggml_sycl_disable_graph = 0;
78
- int g_ggml_sycl_disable_dnn = 0;
84
+ int g_ggml_sycl_enable_optimize = 1;
85
+ int g_ggml_sycl_enable_graph = 0;
86
+ int g_ggml_sycl_enable_dnn = 1;
79
87
  int g_ggml_sycl_enable_vmm = 1;
80
88
  int g_ggml_sycl_prioritize_dmmv = 0;
81
89
  int g_ggml_sycl_use_async_mem_op = 0;
82
90
  int g_ggml_sycl_use_async_mem_op_requested = 1;
83
- int g_ggml_sycl_enable_level_zero = 0;
91
+ int g_ggml_sycl_use_level_zero_api = 0;
84
92
  int g_ggml_sycl_enable_flash_attention = 1;
85
-
93
+ int g_ggml_sycl_dev2dev_memcpy = DEV2DEV_MEMCPY_SYCL;
94
+ int g_ggml_sycl_usm_system = 0;
86
95
 
87
96
  static ggml_sycl_device_info ggml_sycl_init() {
88
97
  ggml_sycl_device_info info = {};
@@ -109,7 +118,7 @@ static ggml_sycl_device_info ggml_sycl_init() {
109
118
  SYCL_CHECK(CHECK_TRY_ERROR(dpct::get_device_info(
110
119
  prop, device)));
111
120
 
112
- #if !defined(GGML_SYCL_USE_VMM)
121
+ #if !defined(GGML_SYCL_SUPPORT_VMM)
113
122
  info.devices[i].vmm = 0;
114
123
  #else
115
124
  info.devices[i].vmm = device.has(sycl::aspect::ext_oneapi_virtual_mem);
@@ -136,6 +145,7 @@ static ggml_sycl_device_info ggml_sycl_init() {
136
145
  info.devices[i].opt_feature.reorder = device.ext_oneapi_architecture_is(syclex::arch_category::intel_gpu);
137
146
  info.devices[i].smpbo = prop.get_local_mem_size();
138
147
  info.devices[i].warp_size = WARP_SIZE;
148
+ info.devices[i].usm_system_support = device.has(sycl::aspect::usm_system_allocations);
139
149
 
140
150
  info.max_work_group_sizes[i] = prop.get_max_work_group_size();
141
151
  info.devices[i].max_wg_per_cu = info.max_work_group_sizes[i] / prop.get_max_compute_units();
@@ -147,11 +157,31 @@ static ggml_sycl_device_info ggml_sycl_init() {
147
157
  GGML_LOG_WARN("SYCL GPU device %d does not use Level Zero backend, disabling Level Zero memory API\n", i);
148
158
  info.ext_oneapi_level_zero = false;
149
159
  }
160
+
161
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
162
+ if (info.ext_oneapi_level_zero && device.is_gpu() && device.default_queue().get_backend() == sycl::backend::ext_oneapi_level_zero) {
163
+ ze_device_handle_t ze_dev = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(device.default_queue().get_device());
164
+ ze_device_properties_t props = {};
165
+ props.stype = ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES;
166
+ ze_result_t r = zeDeviceGetProperties(ze_dev, &props);
167
+ info.devices[i].l0_discrete_gpu = r == ZE_RESULT_SUCCESS && !(props.flags & ZE_DEVICE_PROPERTY_FLAG_INTEGRATED);
168
+ }
169
+ #endif
150
170
  }
151
171
 
152
172
  for (int id = 0; id < info.device_count; ++id) {
153
173
  info.default_tensor_split[id] /= total_vram;
154
174
  }
175
+
176
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
177
+ // Large buffers can be allocated before ggml_check_sycl() initializes other
178
+ // g_ggml_sycl_enable_* globals, so initialize this one as early as we can.
179
+ g_ggml_sycl_use_level_zero_api =
180
+ info.ext_oneapi_level_zero && ggml_sycl_get_env("GGML_SYCL_USE_LEVEL_ZERO_API", 1);
181
+ #else
182
+ g_ggml_sycl_use_level_zero_api = 0;
183
+ #endif
184
+
155
185
  return info;
156
186
  }
157
187
 
@@ -236,110 +266,128 @@ void ggml_backend_sycl_print_sycl_devices() {
236
266
  print_device_opt_feature(device_count);
237
267
  }
238
268
 
239
- static inline int get_sycl_env(const char *env_name, int default_val) {
240
- char *user_device_string = getenv(env_name);
241
- int user_number = default_val;
242
-
243
- unsigned n;
244
- if (user_device_string != NULL &&
245
- sscanf(user_device_string, " %u", &n) == 1) {
246
- user_number = (int)n;
269
+ static const char* dev2dev_int2str(int dev2dev) {
270
+ if (dev2dev == DEV2DEV_MEMCPY_SYCL) {
271
+ return "SYCL API";
272
+ } else if (dev2dev == DEV2DEV_MEMCPY_L0) {
273
+ return "Level Zero API";
247
274
  } else {
248
- user_number = default_val;
275
+ return "Unknown";
249
276
  }
250
- return user_number;
251
277
  }
252
278
 
253
279
  static void ggml_check_sycl() try {
254
280
  static bool initialized = false;
255
281
 
256
282
  if (!initialized) {
257
- g_ggml_sycl_debug = get_sycl_env("GGML_SYCL_DEBUG", 0);
258
- g_ggml_sycl_disable_optimize = get_sycl_env("GGML_SYCL_DISABLE_OPT", 0);
259
- g_ggml_sycl_disable_graph = get_sycl_env("GGML_SYCL_DISABLE_GRAPH", 1);
260
- g_ggml_sycl_disable_dnn = get_sycl_env("GGML_SYCL_DISABLE_DNN", 0);
261
- g_ggml_sycl_enable_vmm = get_sycl_env("GGML_SYCL_ENABLE_VMM", 1);
262
- g_ggml_sycl_prioritize_dmmv = get_sycl_env("GGML_SYCL_PRIORITIZE_DMMV", 0);
263
- #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
264
- g_ggml_sycl_enable_level_zero = get_sycl_env("GGML_SYCL_ENABLE_LEVEL_ZERO", ggml_sycl_info().ext_oneapi_level_zero);
265
- #else
266
- g_ggml_sycl_enable_level_zero = 0;
267
- #endif
283
+ g_ggml_sycl_debug = ggml_sycl_get_env("GGML_SYCL_DEBUG", 0);
284
+ g_ggml_sycl_enable_optimize = ggml_sycl_get_env("GGML_SYCL_ENABLE_OPT", 1);
285
+ g_ggml_sycl_enable_graph = ggml_sycl_get_env("GGML_SYCL_ENABLE_GRAPH", 0);
286
+ g_ggml_sycl_enable_dnn = ggml_sycl_get_env("GGML_SYCL_ENABLE_DNN", 1);
287
+ g_ggml_sycl_enable_vmm = ggml_sycl_get_env("GGML_SYCL_ENABLE_VMM", 1);
288
+ g_ggml_sycl_prioritize_dmmv = ggml_sycl_get_env("GGML_SYCL_PRIORITIZE_DMMV", 0);
289
+
290
+ g_ggml_sycl_dev2dev_memcpy = ggml_sycl_get_env("GGML_SYCL_DEV2DEV_MEMCPY", DEV2DEV_MEMCPY_SYCL);
291
+ if (g_ggml_sycl_use_level_zero_api == 0) {
292
+ g_ggml_sycl_dev2dev_memcpy = DEV2DEV_MEMCPY_SYCL;
293
+ }
268
294
 
269
295
  #ifdef SYCL_FLASH_ATTN
270
- g_ggml_sycl_enable_flash_attention = get_sycl_env("GGML_SYCL_ENABLE_FLASH_ATTN", 1);
296
+ g_ggml_sycl_enable_flash_attention = ggml_sycl_get_env("GGML_SYCL_ENABLE_FLASH_ATTN", 1);
271
297
  #else
272
298
  g_ggml_sycl_enable_flash_attention = 0;
273
299
  #endif
274
300
 
301
+ g_ggml_sycl_usm_system = ggml_sycl_get_env("GGML_SYCL_USM_SYSTEM", 0);
302
+
275
303
  GGML_SYCL_DEBUG("[SYCL] call ggml_check_sycl\n");
276
304
 
277
305
  GGML_LOG_INFO("Build with Macros:\n");
278
- #if defined(GGML_SYCL_FORCE_MMQ)
279
- GGML_LOG_INFO(" GGML_SYCL_FORCE_MMQ: yes\n");
306
+ #if defined(GGML_SYCL_DNNL)
307
+ GGML_LOG_INFO(" GGML_SYCL_DNNL: yes\n");
280
308
  #else
281
- GGML_LOG_INFO(" GGML_SYCL_FORCE_MMQ: no\n");
309
+ GGML_LOG_INFO(" GGML_SYCL_DNNL: no\n");
282
310
  #endif
311
+
283
312
  #if defined(GGML_SYCL_F16)
284
313
  GGML_LOG_INFO(" GGML_SYCL_F16: yes\n");
285
314
  #else
286
315
  GGML_LOG_INFO(" GGML_SYCL_F16: no\n");
287
316
  #endif
317
+
318
+ #if defined(GGML_SYCL_FORCE_MMQ)
319
+ GGML_LOG_INFO(" GGML_SYCL_FORCE_MMQ: yes\n");
320
+ #else
321
+ GGML_LOG_INFO(" GGML_SYCL_FORCE_MMQ: no\n");
322
+ #endif
323
+
288
324
  #if defined(GGML_SYCL_GRAPH)
289
325
  GGML_LOG_INFO(" GGML_SYCL_GRAPH: yes\n");
290
326
  #else
291
327
  GGML_LOG_INFO(" GGML_SYCL_GRAPH: no\n");
292
328
  #endif
293
- #if defined(GGML_SYCL_DNNL)
294
- GGML_LOG_INFO(" GGML_SYCL_DNNL: yes\n");
295
- #else
296
- GGML_LOG_INFO(" GGML_SYCL_DNNL: no\n");
297
- #endif
298
- #if defined(GGML_SYCL_SUPPORT_LEVEL_ZERO)
299
- GGML_LOG_INFO(" GGML_SYCL_SUPPORT_LEVEL_ZERO: yes\n");
329
+
330
+ #if defined(GGML_SYCL_SUPPORT_LEVEL_ZERO_API)
331
+ GGML_LOG_INFO(" GGML_SYCL_SUPPORT_LEVEL_ZERO_API: yes\n");
300
332
  #else
301
- GGML_LOG_INFO(" GGML_SYCL_SUPPORT_LEVEL_ZERO: no\n");
333
+ GGML_LOG_INFO(" GGML_SYCL_SUPPORT_LEVEL_ZERO_API: no\n");
302
334
  #endif
303
- #if defined(GGML_SYCL_USE_VMM)
304
- GGML_LOG_INFO(" GGML_SYCL_USE_VMM: yes\n");
335
+ #if defined(GGML_SYCL_SUPPORT_VMM)
336
+ GGML_LOG_INFO(" GGML_SYCL_SUPPORT_VMM: yes\n");
305
337
  #else
306
- GGML_LOG_INFO(" GGML_SYCL_USE_VMM: no\n");
338
+ GGML_LOG_INFO(" GGML_SYCL_SUPPORT_VMM: no\n");
307
339
  #endif
308
340
 
309
341
  GGML_LOG_INFO("Running with Environment Variables:\n");
310
342
  GGML_LOG_INFO(" GGML_SYCL_DEBUG: %d\n", g_ggml_sycl_debug);
311
- GGML_LOG_INFO(" GGML_SYCL_DISABLE_OPT: %d\n", g_ggml_sycl_disable_optimize);
312
- #ifdef GGML_SYCL_GRAPH
313
- GGML_LOG_INFO(" GGML_SYCL_DISABLE_GRAPH: %d\n", g_ggml_sycl_disable_graph);
343
+
344
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
345
+ GGML_LOG_INFO(" GGML_SYCL_DEV2DEV_MEMCPY: %d (%s)\n", g_ggml_sycl_dev2dev_memcpy, dev2dev_int2str(g_ggml_sycl_dev2dev_memcpy));
314
346
  #else
315
- GGML_LOG_INFO(" GGML_SYCL_DISABLE_GRAPH: graph disabled by compile flag\n");
347
+ GGML_LOG_INFO(" GGML_SYCL_DEV2DEV_MEMCPY: %d (%s), enable to SYCL API since missing GGML_SYCL_SUPPORT_LEVEL_ZERO_API\n",
348
+ g_ggml_sycl_dev2dev_memcpy, dev2dev_int2str(g_ggml_sycl_dev2dev_memcpy));
316
349
  #endif
317
- #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
318
- GGML_LOG_INFO(" GGML_SYCL_ENABLE_LEVEL_ZERO: %d\n", g_ggml_sycl_enable_level_zero);
350
+
351
+ #if defined(GGML_SYCL_DNNL)
352
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_DNN: %d\n", g_ggml_sycl_enable_dnn);
319
353
  #else
320
- GGML_LOG_INFO(" GGML_SYCL_ENABLE_LEVEL_ZERO: Level Zero disabled by compile flag\n");
354
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_DNN: DNN disabled by compile flag\n");
321
355
  #endif
322
- #if GGML_SYCL_DNNL
323
- GGML_LOG_INFO(" GGML_SYCL_DISABLE_DNN: %d\n", g_ggml_sycl_disable_dnn);
356
+
357
+ #ifdef SYCL_FLASH_ATTN
358
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_FLASH_ATTN: %d\n", g_ggml_sycl_enable_flash_attention);
359
+ #else
360
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_FLASH_ATTN: %d disabled by compile flag\n",
361
+ g_ggml_sycl_enable_flash_attention);
362
+ #endif
363
+
364
+ #ifdef GGML_SYCL_GRAPH
365
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_GRAPH: %d\n", g_ggml_sycl_enable_graph);
324
366
  #else
325
- GGML_LOG_INFO(" GGML_SYCL_DISABLE_DNN: DNN disabled by compile flag\n");
367
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_GRAPH: graph disabled by compile flag\n");
326
368
  #endif
327
- #if defined(GGML_SYCL_USE_VMM)
369
+
370
+ GGML_LOG_INFO(" GGML_SYCL_ENABLE_OPT: %d\n", g_ggml_sycl_enable_optimize);
371
+
372
+ #if defined(GGML_SYCL_SUPPORT_VMM)
328
373
  GGML_LOG_INFO(" GGML_SYCL_ENABLE_VMM: %d\n", g_ggml_sycl_enable_vmm);
329
374
  #else
330
375
  GGML_LOG_INFO(" GGML_SYCL_ENABLE_VMM: virtual memory extension is not available\n");
331
376
  #endif
377
+
332
378
  GGML_LOG_INFO(" GGML_SYCL_PRIORITIZE_DMMV: %d\n", g_ggml_sycl_prioritize_dmmv);
333
- g_ggml_sycl_use_async_mem_op_requested = get_sycl_env("GGML_SYCL_USE_ASYNC_MEM_OP", 1);
379
+
380
+ g_ggml_sycl_use_async_mem_op_requested = ggml_sycl_get_env("GGML_SYCL_USE_ASYNC_MEM_OP", 1);
334
381
  GGML_LOG_INFO(" GGML_SYCL_USE_ASYNC_MEM_OP: %d\n", g_ggml_sycl_use_async_mem_op_requested);
335
382
 
336
- #ifdef SYCL_FLASH_ATTN
337
- GGML_LOG_INFO(" GGML_SYCL_ENABLE_FLASH_ATTN: %d\n", g_ggml_sycl_enable_flash_attention);
383
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
384
+ GGML_LOG_INFO(" GGML_SYCL_USE_LEVEL_ZERO_API: %d\n", g_ggml_sycl_use_level_zero_api);
338
385
  #else
339
- GGML_LOG_INFO(" GGML_SYCL_ENABLE_FLASH_ATTN: %d disabled by compile flag\n",
340
- g_ggml_sycl_enable_flash_attention);
386
+ GGML_LOG_INFO(" GGML_SYCL_USE_LEVEL_ZERO_API: Disable Level Zero API usage by compile flag\n");
341
387
  #endif
342
388
 
389
+ GGML_LOG_INFO(" GGML_SYCL_USM_SYSTEM: %d\n", g_ggml_sycl_usm_system);
390
+
343
391
  /* NOT REMOVE, keep it for next optimize for XMX.
344
392
  #if defined(SYCL_USE_XMX)
345
393
  fprintf(stderr, "%s: SYCL_USE_XMX: yes\n", __func__);
@@ -351,7 +399,7 @@ static void ggml_check_sycl() try {
351
399
  // staging path while preserving queue ordering semantics. Graph support still depends on the extension being
352
400
  // available, but it no longer needs to control the non-graph fast path.
353
401
  #if defined(GGML_SYCL_GRAPH) && SYCL_EXT_ONEAPI_ASYNC_MEMORY_ALLOC
354
- g_ggml_sycl_use_async_mem_op = g_ggml_sycl_use_async_mem_op_requested || !g_ggml_sycl_disable_graph;
402
+ g_ggml_sycl_use_async_mem_op = g_ggml_sycl_use_async_mem_op_requested || g_ggml_sycl_enable_graph;
355
403
  if (g_ggml_sycl_use_async_mem_op) {
356
404
  for (unsigned int i = 0; i < dpct::dev_mgr::instance().device_count(); ++i) {
357
405
  if (!dpct::dev_mgr::instance().get_device(i).has(sycl::aspect::ext_oneapi_async_memory_alloc)) {
@@ -415,6 +463,14 @@ catch (sycl::exception const &exc) {
415
463
  std::exit(1);
416
464
  }
417
465
 
466
+ inline void free_aligned_mem_host(void * memblock) {
467
+ #ifdef _WIN32
468
+ _aligned_free(memblock);
469
+ #else
470
+ free(memblock);
471
+ #endif
472
+ }
473
+
418
474
  // sycl buffer
419
475
 
420
476
  struct ggml_backend_sycl_buffer_context {
@@ -424,9 +480,10 @@ struct ggml_backend_sycl_buffer_context {
424
480
  std::string name;
425
481
  optimize_feature opt_feature;
426
482
  std::vector<ggml_tensor_extra_gpu *> tensor_extras;
483
+ bool is_usm_system;
427
484
 
428
- ggml_backend_sycl_buffer_context(int device, void * dev_ptr, queue_ptr stream) :
429
- device(device), dev_ptr(dev_ptr), stream(stream) {
485
+ ggml_backend_sycl_buffer_context(int device, void * dev_ptr, queue_ptr stream, bool is_usm_system) :
486
+ device(device), dev_ptr(dev_ptr), stream(stream), is_usm_system(is_usm_system) {
430
487
  check_allow_gpu_index(device);
431
488
  name = (GGML_SYCL_NAME + std::to_string(device));
432
489
  opt_feature = ggml_sycl_info().devices[device].opt_feature;
@@ -435,7 +492,10 @@ struct ggml_backend_sycl_buffer_context {
435
492
  ~ggml_backend_sycl_buffer_context() {
436
493
  if (dev_ptr != nullptr) {
437
494
  ggml_sycl_set_device(device);
438
- SYCL_CHECK(CHECK_TRY_ERROR(ggml_sycl_free_device(dev_ptr, *stream)));
495
+ if (is_usm_system)
496
+ free_aligned_mem_host(dev_ptr);
497
+ else
498
+ SYCL_CHECK(CHECK_TRY_ERROR(ggml_sycl_free_device(dev_ptr, *stream)));
439
499
  }
440
500
 
441
501
  //release extra used by tensors
@@ -482,12 +542,14 @@ ggml_backend_sycl_buffer_init_tensor(ggml_backend_buffer_t buffer,
482
542
  return GGML_STATUS_SUCCESS;
483
543
  }
484
544
 
485
- if (!g_ggml_sycl_disable_optimize) {
545
+ if (g_ggml_sycl_enable_optimize) {
486
546
  // set reorder extra buffer based on supported type
487
547
  switch (tensor->type) {
488
548
  case GGML_TYPE_Q4_0:
489
549
  case GGML_TYPE_Q8_0:
550
+ case GGML_TYPE_Q3_K:
490
551
  case GGML_TYPE_Q4_K:
552
+ case GGML_TYPE_Q5_K:
491
553
  case GGML_TYPE_Q6_K:{
492
554
  ggml_tensor_extra_gpu * extra = new ggml_tensor_extra_gpu{};
493
555
  tensor->extra = extra;
@@ -568,43 +630,50 @@ catch (sycl::exception const &exc) {
568
630
  std::exit(1);
569
631
  }
570
632
 
571
- #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
572
- static bool ggml_sycl_is_l0_discrete_gpu(sycl::queue &q) {
573
- if (!q.get_device().is_gpu() || q.get_backend() != sycl::backend::ext_oneapi_level_zero) {
574
- return false;
575
- }
576
-
577
- ze_device_handle_t ze_dev = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q.get_device());
578
- ze_device_properties_t props = {};
579
- props.stype = ZE_STRUCTURE_TYPE_DEVICE_PROPERTIES;
580
- ze_result_t r = zeDeviceGetProperties(ze_dev, &props);
581
- return r == ZE_RESULT_SUCCESS && !(props.flags & ZE_DEVICE_PROPERTY_FLAG_INTEGRATED);
633
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
634
+ static bool ggml_sycl_is_l0_discrete_gpu(int device) {
635
+ return ggml_sycl_info().devices[device].l0_discrete_gpu;
582
636
  }
583
637
  #endif
584
638
 
585
- static void dev2dev_memcpy(sycl::queue &q_dst, sycl::queue &q_src, void *ptr_dst,
639
+ static void dev2dev_memcpy(int device_dst, sycl::queue &q_dst, int device_src, sycl::queue &q_src, void *ptr_dst,
586
640
  const void *ptr_src, size_t size) {
587
- #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO
588
- // Use Level Zero direct copy for dGPU-to-dGPU transfers.
589
- const bool l0_copy_supported =
590
- ggml_sycl_is_l0_discrete_gpu(q_dst) && ggml_sycl_is_l0_discrete_gpu(q_src);
591
- if (g_ggml_sycl_enable_level_zero && l0_copy_supported) {
592
- auto ze_ctx = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_context());
593
- auto ze_dev = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_device());
594
- ze_command_queue_desc_t cq_desc = {ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC, nullptr, 0, 0,
595
- 0, ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS, ZE_COMMAND_QUEUE_PRIORITY_NORMAL};
596
- ze_command_list_handle_t cl;
597
- ze_result_t r = zeCommandListCreateImmediate(ze_ctx, ze_dev, &cq_desc, &cl);
598
- if (r == ZE_RESULT_SUCCESS) {
599
- r = zeCommandListAppendMemoryCopy(cl, ptr_dst, ptr_src, size, nullptr, 0, nullptr);
600
- zeCommandListDestroy(cl);
641
+
642
+ #ifdef GGML_SYCL_SUPPORT_LEVEL_ZERO_API
643
+ if (g_ggml_sycl_dev2dev_memcpy == DEV2DEV_MEMCPY_L0) {
644
+ // Use Level Zero direct copy for dGPU-to-dGPU transfers.
645
+ const bool l0_copy_supported =
646
+ ggml_sycl_is_l0_discrete_gpu(device_dst) && ggml_sycl_is_l0_discrete_gpu(device_src);
647
+ if (g_ggml_sycl_use_level_zero_api && l0_copy_supported) {
648
+ auto ze_ctx = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_context());
649
+ auto ze_dev = sycl::get_native<sycl::backend::ext_oneapi_level_zero>(q_dst.get_device());
650
+ ze_command_queue_desc_t cq_desc = {ZE_STRUCTURE_TYPE_COMMAND_QUEUE_DESC, nullptr, 0, 0,
651
+ 0, ZE_COMMAND_QUEUE_MODE_SYNCHRONOUS, ZE_COMMAND_QUEUE_PRIORITY_NORMAL};
652
+ ze_command_list_handle_t cl;
653
+ ze_result_t r = zeCommandListCreateImmediate(ze_ctx, ze_dev, &cq_desc, &cl);
601
654
  if (r == ZE_RESULT_SUCCESS) {
602
- return;
655
+ GGML_SYCL_DEBUG("[SYCL] dev2dev memcpy by L0\n");
656
+ r = zeCommandListAppendMemoryCopy(cl, ptr_dst, ptr_src, size, nullptr, 0, nullptr);
657
+ zeCommandListDestroy(cl);
658
+ if (r == ZE_RESULT_SUCCESS) {
659
+ return;
660
+ }
603
661
  }
604
662
  }
605
663
  }
606
664
  #endif
665
+
666
+ if (g_ggml_sycl_dev2dev_memcpy == DEV2DEV_MEMCPY_SYCL) {
667
+ if (q_dst.get_device().ext_oneapi_can_access_peer(q_src.get_device(),
668
+ sycl::ext::oneapi::peer_access::access_supported)) {
669
+ GGML_SYCL_DEBUG("[SYCL] dev2dev memcpy by SYCL\n");
670
+ SYCL_CHECK(CHECK_TRY_ERROR(q_dst.memcpy(ptr_dst, ptr_src, size).wait()));
671
+ return;
672
+ }
673
+ }
674
+
607
675
  // Host-staged copy
676
+ GGML_SYCL_DEBUG("[SYCL] dev2dev memcpy by host forward\n");
608
677
  char *host_buf = (char *)malloc(size);
609
678
  q_src.memcpy(host_buf, (const char *)ptr_src, size).wait();
610
679
  q_dst.memcpy((char *)ptr_dst, host_buf, size).wait();
@@ -651,7 +720,7 @@ ggml_backend_sycl_buffer_cpy_tensor(ggml_backend_buffer_t buffer,
651
720
  size_t size = ggml_nbytes(src);
652
721
 
653
722
  //todo. it's dirty solutino to walkaroud known issue:device2device cross GPUs.
654
- dev2dev_memcpy(*stream_dst, *stream_src, dst->data, src->data, size);
723
+ dev2dev_memcpy(dst_ctx->device, *stream_dst, src_ctx->device, *stream_src, dst->data, src->data, size);
655
724
 
656
725
  //todo, it's known issue:error in device2device cross GPUs. reused when the issue is fixed. DON"T remove
657
726
  #if 0
@@ -765,21 +834,59 @@ static const char * ggml_backend_sycl_buffer_type_get_name(ggml_backend_buffer_t
765
834
  return ctx->name.c_str();
766
835
  }
767
836
 
837
+ static bool check_usm_system(int device, size_t size) {
838
+ bool use_usm_system = g_ggml_sycl_usm_system && size >= MEM_SIZE_1G;
839
+
840
+ if (use_usm_system && !ggml_sycl_info().devices[device].usm_system_support) {
841
+ GGML_LOG_INFO("Device does not support USM system allocations\n");
842
+ use_usm_system = false;
843
+ }
844
+
845
+ return use_usm_system;
846
+ }
847
+
848
+ inline void * aligned_malloc_host(size_t alignment, size_t size) {
849
+ #ifdef _WIN32
850
+ return _aligned_malloc(size, alignment);
851
+ #else
852
+ return aligned_alloc(alignment, size);
853
+ #endif
854
+ }
855
+
768
856
  static ggml_backend_buffer_t
769
857
  ggml_backend_sycl_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft,
770
858
  size_t size) try {
859
+ ggml_check_sycl();
860
+
771
861
  ggml_backend_sycl_buffer_type_context * buft_ctx = (ggml_backend_sycl_buffer_type_context *)buft->context;
772
862
  ggml_sycl_set_device(buft_ctx->device);
773
863
  const queue_ptr stream = buft_ctx->stream;
774
864
  size = std::max(size, (size_t)1); // syclMalloc returns null for size 0
865
+ /*
866
+ Alignment below ensures best performance. While in theory it could lead to
867
+ wasting memory, this is acceptable because in practice only few buffers are
868
+ allocated and even less exceed the minimum size accepted here for USM system
869
+ allocations.
870
+ */
871
+ size_t alignment = MEM_SIZE_2M;
872
+ size_t aligned_size = ((size + alignment - 1) / alignment) * alignment;
873
+ bool use_usm_system = check_usm_system(buft_ctx->device, aligned_size);
775
874
 
776
875
  void * dev_ptr;
777
- SYCL_CHECK(CHECK_TRY_ERROR(dev_ptr = (void *)ggml_sycl_malloc_device(size, *stream)));
778
- if (!dev_ptr) {
779
- GGML_LOG_ERROR("%s: can't allocate %lu Bytes of memory on device\n", __func__, size);
780
- return nullptr;
876
+ if (use_usm_system) {
877
+ dev_ptr = (void *)aligned_malloc_host(alignment, aligned_size);
878
+ if (!dev_ptr) {
879
+ GGML_LOG_ERROR("%s: can't allocate %lu Bytes of memory on host\n", __func__, size);
880
+ return nullptr;
881
+ }
882
+ } else {
883
+ SYCL_CHECK(CHECK_TRY_ERROR(dev_ptr = (void *)ggml_sycl_malloc_device(size, *stream)));
884
+ if (!dev_ptr) {
885
+ GGML_LOG_ERROR("%s: can't allocate %lu Bytes of memory on device\n", __func__, size);
886
+ return nullptr;
887
+ }
781
888
  }
782
- ggml_backend_sycl_buffer_context * ctx = new ggml_backend_sycl_buffer_context(buft_ctx->device, dev_ptr, buft_ctx->stream);
889
+ ggml_backend_sycl_buffer_context * ctx = new ggml_backend_sycl_buffer_context(buft_ctx->device, dev_ptr, buft_ctx->stream, use_usm_system);
783
890
  return ggml_backend_buffer_init(buft, ggml_backend_sycl_buffer_interface, ctx, size);
784
891
  }
785
892
  catch (sycl::exception const &exc) {
@@ -897,6 +1004,7 @@ static int64_t get_row_rounding(ggml_type type, const std::array<float, GGML_SYC
897
1004
  }
898
1005
 
899
1006
  switch(type) {
1007
+ case GGML_TYPE_Q1_0:
900
1008
  case GGML_TYPE_Q4_0:
901
1009
  case GGML_TYPE_Q4_1:
902
1010
  return max_compute_capability >= VER_GEN9 ? 128 : 64;
@@ -1306,22 +1414,6 @@ static const char * ggml_backend_sycl_host_buffer_type_name(ggml_backend_buffer_
1306
1414
  GGML_UNUSED(buft);
1307
1415
  }
1308
1416
 
1309
- inline void * aligned_malloc_host(size_t alignment, size_t size) {
1310
- #ifdef _WIN32
1311
- return _aligned_malloc(size, alignment);
1312
- #else
1313
- return aligned_alloc(alignment, size);
1314
- #endif
1315
- }
1316
-
1317
- inline void free_aligned_mem_host(void * memblock) {
1318
- #ifdef _WIN32
1319
- _aligned_free(memblock);
1320
- #else
1321
- free(memblock);
1322
- #endif
1323
- }
1324
-
1325
1417
  static void ggml_backend_sycl_host_buffer_free_buffer(ggml_backend_buffer_t buffer) {
1326
1418
  free_aligned_mem_host((void *)buffer->context);
1327
1419
  }
@@ -1498,7 +1590,7 @@ struct ggml_sycl_pool_leg : public ggml_sycl_pool {
1498
1590
  };
1499
1591
 
1500
1592
  // pool with virtual memory management
1501
- #if defined(GGML_SYCL_USE_VMM)
1593
+ #if defined(GGML_SYCL_SUPPORT_VMM)
1502
1594
  struct ggml_sycl_pool_vmm : public ggml_sycl_pool {
1503
1595
  static const size_t SYCL_POOL_VMM_MAX_SIZE = 1ull << 35; // 32 GB
1504
1596
 
@@ -1610,7 +1702,7 @@ struct ggml_sycl_pool_vmm : public ggml_sycl_pool {
1610
1702
  GGML_ASSERT(ptr == reinterpret_cast<void *>(pool_addr + pool_used));
1611
1703
  }
1612
1704
  };
1613
- #endif // defined(GGML_SYCL_USE_VMM)
1705
+ #endif // defined(GGML_SYCL_SUPPORT_VMM)
1614
1706
 
1615
1707
  struct ggml_sycl_pool_host : public ggml_sycl_pool {
1616
1708
  queue_ptr qptr;
@@ -1692,11 +1784,11 @@ std::unique_ptr<ggml_sycl_pool> ggml_backend_sycl_context::new_pool_for_host(que
1692
1784
  }
1693
1785
 
1694
1786
  std::unique_ptr<ggml_sycl_pool> ggml_backend_sycl_context::new_pool_for_device(queue_ptr qptr, int device) {
1695
- #if defined(GGML_SYCL_USE_VMM)
1787
+ #if defined(GGML_SYCL_SUPPORT_VMM)
1696
1788
  if (g_ggml_sycl_enable_vmm && ggml_sycl_info().devices[device].vmm) {
1697
1789
  return std::unique_ptr<ggml_sycl_pool>(new ggml_sycl_pool_vmm(qptr, device));
1698
1790
  }
1699
- #endif // defined(GGML_SYCL_USE_VMM)
1791
+ #endif // defined(GGML_SYCL_SUPPORT_VMM)
1700
1792
  return std::unique_ptr<ggml_sycl_pool>(new ggml_sycl_pool_leg(qptr, device));
1701
1793
  }
1702
1794
 
@@ -1947,69 +2039,6 @@ static void scale_f32(const float * x, float * dst, const float scale, const flo
1947
2039
  }
1948
2040
 
1949
2041
 
1950
- template <typename Ti, typename To>
1951
- static void pool2d_nchw_kernel(
1952
- const int ih, const int iw, const int oh, const int ow,
1953
- const int kh, const int kw, const int sh, const int sw,
1954
- const int ph, const int pw, const int parallel_elements,
1955
- const Ti* src, To* dst, const enum ggml_op_pool op,
1956
- const sycl::nd_item<3> &item_ct1) {
1957
- int idx = item_ct1.get_local_id(2) +
1958
- item_ct1.get_group(2) * item_ct1.get_local_range(2);
1959
- if (idx >= parallel_elements) {
1960
- return;
1961
- }
1962
-
1963
- const int I_HW = ih * iw;
1964
- const int O_HW = oh * ow;
1965
- const int nc = idx / O_HW;
1966
- const int cur_oh = idx % O_HW / ow;
1967
- const int cur_ow = idx % O_HW % ow;
1968
- const Ti* i_ptr = src + nc * I_HW;
1969
- To* o_ptr = dst + nc * O_HW;
1970
- const int start_h = cur_oh * sh - ph;
1971
- const int bh = sycl::max(0, start_h);
1972
- const int eh = sycl::min(ih, start_h + kh);
1973
- const int start_w = cur_ow * sw - pw;
1974
- const int bw = sycl::max(0, start_w);
1975
- const int ew = sycl::min(iw, start_w + kw);
1976
-
1977
- To res = 0;
1978
-
1979
- switch (op) {
1980
- case GGML_OP_POOL_AVG: res = 0; break;
1981
- case GGML_OP_POOL_MAX: res = -FLT_MAX; break;
1982
- default:
1983
- res = (To) sycl::nan(uint32_t(0));
1984
- break;
1985
- }
1986
-
1987
- for (int i = bh; i < eh; i += 1) {
1988
- for (int j = bw; j < ew; j += 1) {
1989
- #if DPCT_COMPATIBILITY_TEMP >= 350
1990
- /*
1991
- DPCT1098:106: The '*' expression is used instead of the __ldg
1992
- call. These two expressions do not provide the exact same
1993
- functionality. Check the generated code for potential precision
1994
- and/or performance issues.
1995
- */
1996
- Ti cur = *(i_ptr + i * iw + j);
1997
- #else
1998
- Ti cur = i_ptr[i * iw + j];
1999
- #endif
2000
- switch (op) {
2001
- case GGML_OP_POOL_AVG: res += (cur / (kh * kw)); break;
2002
- case GGML_OP_POOL_MAX: res = sycl::max(res, (To)cur); break;
2003
- default:
2004
- res = (To) sycl::nan(uint32_t(0));
2005
- break;
2006
- }
2007
- }
2008
- }
2009
- o_ptr[cur_oh * ow + cur_ow] = res;
2010
- }
2011
-
2012
-
2013
2042
  static void ggml_mul_mat_p021_f16_f32_sycl(const void *vx, const float *y,
2014
2043
  float *dst, const int ncols_x,
2015
2044
  const int nrows_x,
@@ -2087,11 +2116,148 @@ static int next_power_of_2(int x) {
2087
2116
  return n;
2088
2117
  }
2089
2118
 
2119
+ static void init_argsort_indices_padded(
2120
+ int * idx,
2121
+ const int nrows,
2122
+ const int ncols_pad,
2123
+ const sycl::nd_item<1> & item_ct1) {
2124
+ const size_t gid = item_ct1.get_local_range(0) * item_ct1.get_group(0) + item_ct1.get_local_id(0);
2125
+ const size_t total = (size_t) nrows * (size_t) ncols_pad;
2126
+
2127
+ if (gid >= total) {
2128
+ return;
2129
+ }
2130
+
2131
+ idx[gid] = (int) (gid % (size_t) ncols_pad);
2132
+ }
2133
+
2134
+ template <ggml_sort_order order>
2135
+ static void argsort_f32_i32_global_pass(const float * x,
2136
+ int * idx,
2137
+ const int ncols,
2138
+ const int nrows,
2139
+ const int ncols_pad,
2140
+ const int j,
2141
+ const int k,
2142
+ const sycl::nd_item<1> & item_ct1) {
2143
+ const size_t gid = item_ct1.get_local_range(0) * item_ct1.get_group(0) + item_ct1.get_local_id(0);
2144
+ const size_t total = (size_t) nrows * (size_t) ncols_pad;
2145
+
2146
+ if (gid >= total) {
2147
+ return;
2148
+ }
2149
+
2150
+ const int row = (int) (gid / (size_t) ncols_pad);
2151
+ const int col = (int) (gid % (size_t) ncols_pad);
2152
+ const int ixj = col ^ j;
2153
+
2154
+ if (ixj <= col || ixj >= ncols_pad) {
2155
+ return;
2156
+ }
2157
+
2158
+ const size_t base = (size_t) row * (size_t) ncols_pad;
2159
+ const size_t pos_a = base + (size_t) col;
2160
+ const size_t pos_b = base + (size_t) ixj;
2161
+
2162
+ const int a = idx[pos_a];
2163
+ const int b = idx[pos_b];
2164
+
2165
+ bool do_swap = false;
2166
+
2167
+ if ((col & k) == 0) {
2168
+ if (a >= ncols ||
2169
+ (b < ncols &&
2170
+ (order == GGML_SORT_ORDER_ASC ?
2171
+ x[(size_t) row * (size_t) ncols + (size_t) a] > x[(size_t) row * (size_t) ncols + (size_t) b] :
2172
+ x[(size_t) row * (size_t) ncols + (size_t) a] < x[(size_t) row * (size_t) ncols + (size_t) b]))) {
2173
+ do_swap = true;
2174
+ }
2175
+ } else {
2176
+ if (b >= ncols ||
2177
+ (a < ncols &&
2178
+ (order == GGML_SORT_ORDER_ASC ?
2179
+ x[(size_t) row * (size_t) ncols + (size_t) a] < x[(size_t) row * (size_t) ncols + (size_t) b] :
2180
+ x[(size_t) row * (size_t) ncols + (size_t) a] > x[(size_t) row * (size_t) ncols + (size_t) b]))) {
2181
+ do_swap = true;
2182
+ }
2183
+ }
2184
+
2185
+ if (do_swap) {
2186
+ idx[pos_a] = b;
2187
+ idx[pos_b] = a;
2188
+ }
2189
+ }
2190
+
2191
+ static void copy_argsort_indices_unpadded(const int * idx_padded,
2192
+ int * dst,
2193
+ const int nrows,
2194
+ const int ncols,
2195
+ const int ncols_pad,
2196
+ const sycl::nd_item<1> & item_ct1) {
2197
+ const size_t gid = item_ct1.get_local_range(0) * item_ct1.get_group(0) + item_ct1.get_local_id(0);
2198
+ const size_t total = (size_t) nrows * (size_t) ncols;
2199
+
2200
+ if (gid >= total) {
2201
+ return;
2202
+ }
2203
+
2204
+ const int row = (int) (gid / (size_t) ncols);
2205
+ const int col = (int) (gid % (size_t) ncols);
2206
+
2207
+ dst[(size_t) row * (size_t) ncols + (size_t) col] = idx_padded[(size_t) row * (size_t) ncols_pad + (size_t) col];
2208
+ }
2209
+
2090
2210
  static void argsort_f32_i32_sycl(const float *x, int *dst, const int ncols,
2091
2211
  const int nrows, ggml_sort_order order,
2092
- queue_ptr stream, int device) {
2212
+ queue_ptr stream, int device, ggml_sycl_pool & pool) {
2093
2213
  // bitonic sort requires ncols to be power of 2
2094
2214
  const int ncols_pad = next_power_of_2(ncols);
2215
+ const size_t shared_mem = (size_t) ncols_pad * sizeof(int);
2216
+ const size_t smpbo = ggml_sycl_info().devices[device].smpbo;
2217
+
2218
+ if (shared_mem > smpbo) {
2219
+ ggml_sycl_pool_alloc<int> idx_padded_alloc(pool, (size_t) nrows * (size_t) ncols_pad);
2220
+ int * idx_padded = idx_padded_alloc.get();
2221
+
2222
+ constexpr size_t block_size = 256;
2223
+ const size_t total_padded = (size_t) nrows * (size_t) ncols_pad;
2224
+ const size_t nblocks_padded = (total_padded + block_size - 1) / block_size;
2225
+
2226
+ stream->parallel_for(
2227
+ sycl::nd_range<1>(sycl::range<1>(nblocks_padded * block_size), sycl::range<1>(block_size)),
2228
+ [=](sycl::nd_item<1> item_ct1) { init_argsort_indices_padded(idx_padded, nrows, ncols_pad, item_ct1); });
2229
+
2230
+ for (int k = 2; k <= ncols_pad; k *= 2) {
2231
+ for (int j = k / 2; j > 0; j /= 2) {
2232
+ if (order == GGML_SORT_ORDER_ASC) {
2233
+ stream->parallel_for(
2234
+ sycl::nd_range<1>(sycl::range<1>(nblocks_padded * block_size), sycl::range<1>(block_size)),
2235
+ [=](sycl::nd_item<1> item_ct1) {
2236
+ argsort_f32_i32_global_pass<GGML_SORT_ORDER_ASC>(x, idx_padded, ncols, nrows, ncols_pad, j,
2237
+ k, item_ct1);
2238
+ });
2239
+ } else if (order == GGML_SORT_ORDER_DESC) {
2240
+ stream->parallel_for(
2241
+ sycl::nd_range<1>(sycl::range<1>(nblocks_padded * block_size), sycl::range<1>(block_size)),
2242
+ [=](sycl::nd_item<1> item_ct1) {
2243
+ argsort_f32_i32_global_pass<GGML_SORT_ORDER_DESC>(x, idx_padded, ncols, nrows, ncols_pad, j,
2244
+ k, item_ct1);
2245
+ });
2246
+ } else {
2247
+ GGML_ABORT("invalid sort order");
2248
+ }
2249
+ }
2250
+ }
2251
+
2252
+ const size_t total = (size_t) nrows * (size_t) ncols;
2253
+ const size_t nblocks = (total + block_size - 1) / block_size;
2254
+ stream->parallel_for(sycl::nd_range<1>(sycl::range<1>(nblocks * block_size), sycl::range<1>(block_size)),
2255
+ [=](sycl::nd_item<1> item_ct1) {
2256
+ copy_argsort_indices_unpadded(idx_padded, dst, nrows, ncols, ncols_pad, item_ct1);
2257
+ });
2258
+
2259
+ return;
2260
+ }
2095
2261
 
2096
2262
  int nth = 1;
2097
2263
  int max_block_size = ggml_sycl_info().max_work_group_sizes[device];
@@ -2104,8 +2270,6 @@ static void argsort_f32_i32_sycl(const float *x, int *dst, const int ncols,
2104
2270
 
2105
2271
  const sycl::range<3> block_dims(1, 1, nth);
2106
2272
  const sycl::range<3> block_nums(1, nrows, 1);
2107
- const size_t shared_mem = ncols_pad * sizeof(int);
2108
- GGML_ASSERT(shared_mem<=ggml_sycl_info().devices[device].smpbo);
2109
2273
 
2110
2274
  if (order == GGML_SORT_ORDER_ASC) {
2111
2275
  stream->submit([&](sycl::handler &cgh) {
@@ -2428,7 +2592,7 @@ inline void ggml_sycl_op_mul_mat_sycl(
2428
2592
 
2429
2593
  #if GGML_SYCL_DNNL && defined(GGML_SYCL_HAS_BF16)
2430
2594
  // Fast path for bf16 src0
2431
- if (src0->type == GGML_TYPE_BF16 && !g_ggml_sycl_disable_dnn && ggml_is_contiguous(src0) &&
2595
+ if (src0->type == GGML_TYPE_BF16 && g_ggml_sycl_enable_dnn && ggml_is_contiguous(src0) &&
2432
2596
  row_diff == src0->ne[1]) {
2433
2597
  using bf16_t = sycl::ext::oneapi::bfloat16;
2434
2598
  ggml_sycl_pool_alloc<bf16_t> src1_as_bf16(ctx.pool(), src1_ncols*ne10);
@@ -2481,7 +2645,7 @@ inline void ggml_sycl_op_mul_mat_sycl(
2481
2645
  : src1_as_f16.get();
2482
2646
 
2483
2647
  #if GGML_SYCL_DNNL
2484
- if (!g_ggml_sycl_disable_dnn) {
2648
+ if (g_ggml_sycl_enable_dnn) {
2485
2649
  DnnlGemmWrapper::row_gemm(ctx,row_diff, src1_ncols , ne10, src0_ptr,
2486
2650
  DnnlGemmWrapper::to_dt<sycl::half>(), src1_ptr, DnnlGemmWrapper::to_dt<sycl::half>(),
2487
2651
  dst_dd_i, DnnlGemmWrapper::to_dt<float>(), stream);
@@ -2531,7 +2695,7 @@ inline void ggml_sycl_op_mul_mat_sycl(
2531
2695
  const int64_t gemm_flops = (int64_t)row_diff * src1_ncols * ne10;
2532
2696
  const bool use_mkl_direct = gemm_flops < 256 * 256 * 256;
2533
2697
  #if GGML_SYCL_DNNL
2534
- if (!g_ggml_sycl_disable_dnn && !use_mkl_direct) {
2698
+ if (g_ggml_sycl_enable_dnn && !use_mkl_direct) {
2535
2699
  DnnlGemmWrapper::row_gemm(ctx, row_diff, src1_ncols, ne10, src0_ddf_i,
2536
2700
  DnnlGemmWrapper::to_dt<float>(), src1_ddf1_i, DnnlGemmWrapper::to_dt<float>(),
2537
2701
  dst_dd_i, DnnlGemmWrapper::to_dt<float>(), stream);
@@ -2558,45 +2722,6 @@ catch (sycl::exception const &exc) {
2558
2722
  std::exit(1);
2559
2723
  }
2560
2724
 
2561
- static void ggml_sycl_op_pool2d(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
2562
- GGML_ASSERT(dst->src[0]->type == GGML_TYPE_F32);
2563
- GGML_ASSERT( dst->type == GGML_TYPE_F32);
2564
- dpct::queue_ptr main_stream = ctx.stream();
2565
- SYCL_CHECK(ggml_sycl_set_device(ctx.device));
2566
- const float * src0_dd = static_cast<const float *>(dst->src[0]->data);
2567
- float * dst_dd = static_cast<float *>(dst->data);
2568
-
2569
- const int32_t * opts = (const int32_t *)dst->op_params;
2570
- enum ggml_op_pool op = static_cast<ggml_op_pool>(opts[0]);
2571
- const int k0 = opts[1];
2572
- const int k1 = opts[2];
2573
- const int s0 = opts[3];
2574
- const int s1 = opts[4];
2575
- const int p0 = opts[5];
2576
- const int p1 = opts[6];
2577
-
2578
- const int64_t IH = dst->src[0]->ne[1];
2579
- const int64_t IW = dst->src[0]->ne[0];
2580
-
2581
- const int64_t N = dst->ne[3];
2582
- const int64_t OC = dst->ne[2];
2583
- const int64_t OH = dst->ne[1];
2584
- const int64_t OW = dst->ne[0];
2585
-
2586
- const int parallel_elements = N * OC * OH * OW;
2587
- const int num_blocks = (parallel_elements + SYCL_POOL2D_BLOCK_SIZE - 1) / SYCL_POOL2D_BLOCK_SIZE;
2588
- sycl::range<3> block_nums(1, 1, num_blocks);
2589
- main_stream->parallel_for(
2590
- sycl::nd_range<3>(block_nums *
2591
- sycl::range<3>(1, 1, SYCL_IM2COL_BLOCK_SIZE),
2592
- sycl::range<3>(1, 1, SYCL_IM2COL_BLOCK_SIZE)),
2593
- [=](sycl::nd_item<3> item_ct1) {
2594
- pool2d_nchw_kernel(IH, IW, OH, OW, k1, k0, s1, s0, p1, p0,
2595
- parallel_elements, src0_dd, dst_dd, op,
2596
- item_ct1);
2597
- });
2598
- }
2599
-
2600
2725
  inline void ggml_sycl_op_sum(ggml_backend_sycl_context & ctx, ggml_tensor *dst) {
2601
2726
  GGML_ASSERT(dst->src[0]->type == GGML_TYPE_F32);
2602
2727
  GGML_ASSERT( dst->type == GGML_TYPE_F32);
@@ -2663,7 +2788,7 @@ inline void ggml_sycl_op_argsort(ggml_backend_sycl_context & ctx, ggml_tensor *
2663
2788
  enum ggml_sort_order order = (enum ggml_sort_order) dst->op_params[0];
2664
2789
 
2665
2790
  argsort_f32_i32_sycl(src0_dd, (int *)dst_dd, ncols, nrows, order,
2666
- main_stream, ctx.device);
2791
+ main_stream, ctx.device, ctx.pool());
2667
2792
  }
2668
2793
 
2669
2794
  static void ggml_sycl_op_top_k(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
@@ -3056,7 +3181,7 @@ static void ggml_sycl_op_mul_mat(ggml_backend_sycl_context & ctx, const ggml_ten
3056
3181
  src1_ddf_i_source += (i0 * ne11 + src1_col_0) * ne10;
3057
3182
 
3058
3183
  SYCL_CHECK(
3059
- CHECK_TRY_ERROR(dev2dev_memcpy(*stream, *main_stream, src1_ddf_i, src1_ddf_i_source,
3184
+ CHECK_TRY_ERROR(dev2dev_memcpy(i, *stream, ctx.device, *main_stream, src1_ddf_i, src1_ddf_i_source,
3060
3185
  src1_ncols * ne10 * sizeof(float))));
3061
3186
  }
3062
3187
  }
@@ -3390,7 +3515,7 @@ static void ggml_sycl_mul_mat_batched_sycl(ggml_backend_sycl_context & ctx, cons
3390
3515
  const int64_t r3 = ne13 / ne03;
3391
3516
 
3392
3517
  #if GGML_SYCL_DNNL
3393
- if (!g_ggml_sycl_disable_dnn) {
3518
+ if (g_ggml_sycl_enable_dnn) {
3394
3519
  int64_t str_a0 = nb00 / type_size_src0;
3395
3520
  int64_t str_a1 = nb01 / type_size_src0;
3396
3521
  int64_t str_a2 = nb02 / type_size_src0;
@@ -3546,6 +3671,7 @@ inline bool ggml_sycl_supports_mmq(enum ggml_type type) {
3546
3671
 
3547
3672
  inline bool ggml_sycl_supports_reorder_mul_mat_sycl(enum ggml_type type) {
3548
3673
  switch (type) {
3674
+ case GGML_TYPE_Q1_0:
3549
3675
  case GGML_TYPE_Q4_0:
3550
3676
  case GGML_TYPE_Q8_0:
3551
3677
  return true;
@@ -3561,8 +3687,13 @@ inline bool ggml_sycl_supports_reorder_mul_mat_sycl(enum ggml_type type) {
3561
3687
 
3562
3688
  inline bool ggml_sycl_supports_reorder_dmmv(enum ggml_type type) {
3563
3689
  switch (type) {
3690
+ case GGML_TYPE_Q1_0:
3564
3691
  case GGML_TYPE_Q4_0:
3565
3692
  case GGML_TYPE_Q8_0:
3693
+ case GGML_TYPE_Q3_K:
3694
+ case GGML_TYPE_Q4_K:
3695
+ case GGML_TYPE_Q5_K:
3696
+ case GGML_TYPE_Q6_K:
3566
3697
  return true;
3567
3698
  default:
3568
3699
  return false;
@@ -3571,6 +3702,7 @@ inline bool ggml_sycl_supports_reorder_dmmv(enum ggml_type type) {
3571
3702
 
3572
3703
  inline bool ggml_sycl_supports_reorder_mmvq(enum ggml_type type) {
3573
3704
  switch (type) {
3705
+ case GGML_TYPE_Q1_0:
3574
3706
  case GGML_TYPE_Q4_0:
3575
3707
  case GGML_TYPE_Q8_0:
3576
3708
  case GGML_TYPE_Q3_K:
@@ -3585,6 +3717,7 @@ inline bool ggml_sycl_supports_reorder_mmvq(enum ggml_type type) {
3585
3717
 
3586
3718
  static bool ggml_sycl_supports_dmmv(enum ggml_type type) {
3587
3719
  switch (type) {
3720
+ case GGML_TYPE_Q1_0:
3588
3721
  case GGML_TYPE_Q4_0:
3589
3722
  case GGML_TYPE_Q4_1:
3590
3723
  case GGML_TYPE_Q5_0:
@@ -3793,6 +3926,149 @@ static bool reorder_qw_q4_k(uint8_t * data_device, size_t size, size_t offset, d
3793
3926
  return true;
3794
3927
  }
3795
3928
 
3929
+ // Reorder each expert slice into a self-contained SoA layout.
3930
+ static bool reorder_qw_q4_k_moe(uint8_t * data_device, size_t expert_bytes, int64_t n_expert, dpct::queue_ptr stream) {
3931
+ GGML_ASSERT(expert_bytes % sizeof(block_q4_K) == 0);
3932
+ const int blocks_per_expert = (int) (expert_bytes / sizeof(block_q4_K));
3933
+ const size_t total_bytes = expert_bytes * (size_t) n_expert;
3934
+
3935
+ sycl_reorder_temp_buffer tmp(stream, total_bytes);
3936
+ if (!tmp) {
3937
+ GGML_LOG_WARN("%s: failed to allocate %zu bytes for reorder temp buffer, skipping reorder\n", __func__, total_bytes);
3938
+ return false;
3939
+ }
3940
+ uint8_t * tmp_buf = static_cast<uint8_t *>(tmp.ptr);
3941
+
3942
+ sycl::event copy_event;
3943
+ SYCL_CHECK(CHECK_TRY_ERROR(copy_event = stream->memcpy(tmp_buf, data_device, total_bytes)));
3944
+ if (!g_ggml_sycl_use_async_mem_op) {
3945
+ copy_event.wait();
3946
+ }
3947
+
3948
+ const int total_blocks = blocks_per_expert * (int) n_expert;
3949
+ auto reorder_event = stream->parallel_for(total_blocks, [=](auto gb_) {
3950
+ const int gb = gb_;
3951
+ const int e = gb / blocks_per_expert;
3952
+ const int ib = gb % blocks_per_expert;
3953
+ const block_q4_K * x = (const block_q4_K *) (tmp_buf + (size_t) e * expert_bytes);
3954
+ uint8_t * base = data_device + (size_t) e * expert_bytes;
3955
+
3956
+ auto * qs_ptr = base;
3957
+ auto * scales_ptr = qs_ptr + QK_K / 2 * blocks_per_expert;
3958
+ auto * dm_ptr = (sycl::half2 *) (scales_ptr + K_SCALE_SIZE * blocks_per_expert);
3959
+
3960
+ for (int j = 0; j < QK_K / 2; ++j) {
3961
+ qs_ptr[ib * (QK_K / 2) + j] = x[ib].qs[j];
3962
+ }
3963
+ for (int j = 0; j < K_SCALE_SIZE; ++j) {
3964
+ scales_ptr[ib * K_SCALE_SIZE + j] = x[ib].scales[j];
3965
+ }
3966
+ dm_ptr[ib] = x[ib].dm;
3967
+ });
3968
+ if (!g_ggml_sycl_use_async_mem_op) {
3969
+ reorder_event.wait_and_throw();
3970
+ }
3971
+ return true;
3972
+ }
3973
+
3974
+ // Reorder each Q5_K expert slice into [qs][qh][scales][dm].
3975
+ static bool reorder_qw_q5_k_moe(uint8_t * data_device, size_t expert_bytes, int64_t n_expert, dpct::queue_ptr stream) {
3976
+ GGML_ASSERT(expert_bytes % sizeof(block_q5_K) == 0);
3977
+ const int blocks_per_expert = (int) (expert_bytes / sizeof(block_q5_K));
3978
+ const size_t total_bytes = expert_bytes * (size_t) n_expert;
3979
+
3980
+ sycl_reorder_temp_buffer tmp(stream, total_bytes);
3981
+ if (!tmp) {
3982
+ GGML_LOG_WARN("%s: failed to allocate %zu bytes for reorder temp buffer, skipping reorder\n", __func__, total_bytes);
3983
+ return false;
3984
+ }
3985
+ uint8_t * tmp_buf = static_cast<uint8_t *>(tmp.ptr);
3986
+
3987
+ sycl::event copy_event;
3988
+ SYCL_CHECK(CHECK_TRY_ERROR(copy_event = stream->memcpy(tmp_buf, data_device, total_bytes)));
3989
+ if (!g_ggml_sycl_use_async_mem_op) {
3990
+ copy_event.wait();
3991
+ }
3992
+
3993
+ const int total_blocks = blocks_per_expert * (int) n_expert;
3994
+ auto reorder_event = stream->parallel_for(total_blocks, [=](auto gb_) {
3995
+ const int gb = gb_;
3996
+ const int e = gb / blocks_per_expert;
3997
+ const int ib = gb % blocks_per_expert;
3998
+ const block_q5_K * x = (const block_q5_K *) (tmp_buf + (size_t) e * expert_bytes);
3999
+ uint8_t * base = data_device + (size_t) e * expert_bytes;
4000
+
4001
+ auto * qs_ptr = base;
4002
+ auto * qh_ptr = qs_ptr + (QK_K / 2) * blocks_per_expert;
4003
+ auto * scales_ptr = qh_ptr + (QK_K / 8) * blocks_per_expert;
4004
+ auto * dm_ptr = (sycl::half2 *) (scales_ptr + K_SCALE_SIZE * blocks_per_expert);
4005
+
4006
+ for (int j = 0; j < QK_K / 2; ++j) {
4007
+ qs_ptr[ib * (QK_K / 2) + j] = x[ib].qs[j];
4008
+ }
4009
+ for (int j = 0; j < QK_K / 8; ++j) {
4010
+ qh_ptr[ib * (QK_K / 8) + j] = x[ib].qh[j];
4011
+ }
4012
+ for (int j = 0; j < K_SCALE_SIZE; ++j) {
4013
+ scales_ptr[ib * K_SCALE_SIZE + j] = x[ib].scales[j];
4014
+ }
4015
+ dm_ptr[ib] = x[ib].dm;
4016
+ });
4017
+ if (!g_ggml_sycl_use_async_mem_op) {
4018
+ reorder_event.wait_and_throw();
4019
+ }
4020
+ return true;
4021
+ }
4022
+
4023
+ // Reorder each Q6_K expert slice into [ql][qh][scales][d].
4024
+ static bool reorder_qw_q6_k_moe(uint8_t * data_device, size_t expert_bytes, int64_t n_expert, dpct::queue_ptr stream) {
4025
+ GGML_ASSERT(expert_bytes % sizeof(block_q6_K) == 0);
4026
+ const int blocks_per_expert = (int) (expert_bytes / sizeof(block_q6_K));
4027
+ const size_t total_bytes = expert_bytes * (size_t) n_expert;
4028
+
4029
+ sycl_reorder_temp_buffer tmp(stream, total_bytes);
4030
+ if (!tmp) {
4031
+ GGML_LOG_WARN("%s: failed to allocate %zu bytes for reorder temp buffer, skipping reorder\n", __func__, total_bytes);
4032
+ return false;
4033
+ }
4034
+ uint8_t * tmp_buf = static_cast<uint8_t *>(tmp.ptr);
4035
+
4036
+ sycl::event copy_event;
4037
+ SYCL_CHECK(CHECK_TRY_ERROR(copy_event = stream->memcpy(tmp_buf, data_device, total_bytes)));
4038
+ if (!g_ggml_sycl_use_async_mem_op) {
4039
+ copy_event.wait();
4040
+ }
4041
+
4042
+ const int total_blocks = blocks_per_expert * (int) n_expert;
4043
+ auto reorder_event = stream->parallel_for(total_blocks, [=](auto gb_) {
4044
+ const int gb = gb_;
4045
+ const int e = gb / blocks_per_expert;
4046
+ const int ib = gb % blocks_per_expert;
4047
+ const block_q6_K * x = (const block_q6_K *) (tmp_buf + (size_t) e * expert_bytes);
4048
+ uint8_t * base = data_device + (size_t) e * expert_bytes;
4049
+
4050
+ auto * ql_ptr = base;
4051
+ auto * qh_ptr = ql_ptr + (QK_K / 2) * blocks_per_expert;
4052
+ auto * scales_ptr = qh_ptr + (QK_K / 4) * blocks_per_expert;
4053
+ auto * d_ptr = (sycl::half *) (scales_ptr + (QK_K / 16) * blocks_per_expert);
4054
+
4055
+ for (int j = 0; j < QK_K / 2; ++j) {
4056
+ ql_ptr[ib * (QK_K / 2) + j] = x[ib].ql[j];
4057
+ }
4058
+ for (int j = 0; j < QK_K / 4; ++j) {
4059
+ qh_ptr[ib * (QK_K / 4) + j] = x[ib].qh[j];
4060
+ }
4061
+ for (int j = 0; j < QK_K / 16; ++j) {
4062
+ scales_ptr[ib * (QK_K / 16) + j] = x[ib].scales[j];
4063
+ }
4064
+ d_ptr[ib] = x[ib].d;
4065
+ });
4066
+ if (!g_ggml_sycl_use_async_mem_op) {
4067
+ reorder_event.wait_and_throw();
4068
+ }
4069
+ return true;
4070
+ }
4071
+
3796
4072
  static bool reorder_qw_q3_k(uint8_t * data_device, size_t size, size_t offset, dpct::queue_ptr stream) {
3797
4073
  GGML_ASSERT(size % sizeof(block_q3_K) == 0);
3798
4074
  GGML_ASSERT(offset % sizeof(block_q3_K) == 0);
@@ -3948,6 +4224,22 @@ static bool reorder_qw(const ggml_tensor * src0, dpct::queue_ptr stream) {
3948
4224
  size_t nrows = src0->ne[1];
3949
4225
  size_t size = ggml_nbytes(src0);
3950
4226
 
4227
+ // MoE expert weights are addressed per expert via nb[2], so each slice must
4228
+ // remain self-contained after reorder.
4229
+ if (src0->ne[2] > 1) {
4230
+ GGML_ASSERT((size_t) size == (size_t) src0->ne[2] * src0->nb[2]);
4231
+ switch (src0->type) {
4232
+ case GGML_TYPE_Q4_K:
4233
+ return reorder_qw_q4_k_moe(data_device, src0->nb[2], src0->ne[2], stream);
4234
+ case GGML_TYPE_Q5_K:
4235
+ return reorder_qw_q5_k_moe(data_device, src0->nb[2], src0->ne[2], stream);
4236
+ case GGML_TYPE_Q6_K:
4237
+ return reorder_qw_q6_k_moe(data_device, src0->nb[2], src0->ne[2], stream);
4238
+ default:
4239
+ return false;
4240
+ }
4241
+ }
4242
+
3951
4243
  switch (src0->type) {
3952
4244
  case GGML_TYPE_Q4_0:
3953
4245
  return reorder_qw_q4_0(data_device, ncols, nrows, size, 0, stream);
@@ -3962,18 +4254,17 @@ static bool reorder_qw(const ggml_tensor * src0, dpct::queue_ptr stream) {
3962
4254
  case GGML_TYPE_Q6_K:
3963
4255
  return reorder_qw_q6_k(data_device, size, 0, stream);
3964
4256
  default:
3965
- GGML_ABORT("reorder_qw() called with unsupported type");
3966
4257
  return false;
3967
4258
  }
3968
4259
  }
3969
4260
 
3970
4261
  static bool should_reorder_tensor(ggml_backend_sycl_context& ctx, const ggml_tensor * dst) {
3971
- return !g_ggml_sycl_disable_optimize && //allow optimize, controlled by $GGML_SYCL_DISABLE_OPT
3972
- ctx.opt_feature.reorder && //allow this device due to good perf, skip the devices with bad perf.
3973
- dst->op == GGML_OP_MUL_MAT && //limit to some supported cases of Q4_0, to do for more cases.
3974
- // ne[1] <= 8 so multi-column decode (spec / MTP verify) also bootstraps the reorder;
3975
- // all reorderable types have a _switch_ncols kernel.
3976
- dst->src[1]->ne[1] <= 8 && dst->src[1]->ne[2]==1 && dst->src[1]->ne[3]==1;
4262
+ return g_ggml_sycl_enable_optimize && //allow optimize, controlled by $GGML_SYCL_ENABLE_OPT
4263
+ ctx.opt_feature.reorder && //allow this device due to good perf, skip the devices with bad perf.
4264
+ dst->op == GGML_OP_MUL_MAT && //limit to some supported cases of Q4_0, to do for more cases.
4265
+ // ne[1] <= 8 so multi-column decode (spec / MTP verify) also bootstraps the reorder;
4266
+ // all reorderable types have a _switch_ncols kernel.
4267
+ dst->src[1]->ne[1] <= 8 && dst->src[1]->ne[2]==1 && dst->src[1]->ne[3]==1;
3977
4268
  }
3978
4269
 
3979
4270
  static void opt_for_reorder(ggml_backend_sycl_context * ctx, const ggml_tensor * src0, const ggml_tensor * /* src1 */,
@@ -4010,6 +4301,23 @@ static void opt_for_reorder(ggml_backend_sycl_context * ctx, const ggml_tensor *
4010
4301
  }
4011
4302
  }
4012
4303
 
4304
+ // Lazily reorder supported MoE expert weights once their fused path is used.
4305
+ static void opt_for_reorder_id(ggml_backend_sycl_context * ctx, const ggml_tensor * src0) {
4306
+ if (!g_ggml_sycl_enable_optimize || !ctx->opt_feature.reorder) {
4307
+ return;
4308
+ }
4309
+ if (src0->type != GGML_TYPE_Q4_K && src0->type != GGML_TYPE_Q5_K && src0->type != GGML_TYPE_Q6_K) {
4310
+ return;
4311
+ }
4312
+ ggml_tensor_extra_gpu * extra = static_cast<ggml_tensor_extra_gpu *>(src0->extra);
4313
+ if (!extra || extra->optimized_feature.reorder) {
4314
+ return;
4315
+ }
4316
+ if (reorder_qw(src0, ctx->stream())) {
4317
+ extra->optimized_feature.reorder = true;
4318
+ }
4319
+ }
4320
+
4013
4321
 
4014
4322
  static bool can_use_dequantize_mul_mat_vec(const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
4015
4323
  // The F16/BF16 qk=1 kernel iterates with stride 2*DMMV_X, requiring ne[0] to be
@@ -4115,11 +4423,6 @@ static void ggml_sycl_mul_mat(ggml_backend_sycl_context & ctx, const ggml_tensor
4115
4423
  }
4116
4424
 
4117
4425
 
4118
- struct mmid_row_mapping {
4119
- int32_t i1;
4120
- int32_t i2;
4121
- };
4122
-
4123
4426
  __dpct_inline__ static void k_copy_src1_to_contiguous(
4124
4427
  const char *__restrict__ src1_original, char *__restrict__ src1_contiguous,
4125
4428
  const mmid_row_mapping *__restrict__ row_mapping,
@@ -4175,11 +4478,6 @@ static bool ggml_sycl_mul_mat_id_mmvq_fused(
4175
4478
  if (ne10 != src0->ne[0] || ne10 % QK8_1 != 0) return false;
4176
4479
  if (!ggml_is_contiguous(src1)) return false;
4177
4480
 
4178
- // Reorder layout not supported; fall back.
4179
- const ggml_tensor_extra_gpu * src0_extra =
4180
- static_cast<const ggml_tensor_extra_gpu *>(src0->extra);
4181
- if (src0_extra && src0_extra->optimized_feature.reorder) return false;
4182
-
4183
4481
  const int64_t n_ids_per_group = ids->ne[0];
4184
4482
  if (ids->ne[1] != 1) return false;
4185
4483
  if (ne11 != 1 && ne11 != n_ids_per_group) return false;
@@ -4189,16 +4487,37 @@ static bool ggml_sycl_mul_mat_id_mmvq_fused(
4189
4487
  const int n_experts_used = (int) n_ids_per_group;
4190
4488
  const int nrows = (int) src0->ne[1];
4191
4489
 
4490
+ // Lazily reorder the (Q4_K) expert weights into a per-expert SoA layout, then run the reorder
4491
+ // GEMV. Placed after the bail checks so a non-dispatchable op does not pay the reorder cost.
4492
+ opt_for_reorder_id(&ctx, src0);
4493
+ const ggml_tensor_extra_gpu * src0_extra =
4494
+ static_cast<const ggml_tensor_extra_gpu *>(src0->extra);
4495
+ const bool use_reorder = src0_extra && src0_extra->optimized_feature.reorder;
4496
+
4192
4497
  ggml_sycl_pool_alloc<char> src1_q8_alloc(ctx.pool(),
4193
4498
  (size_t) ne11 * src1_padded_cols * sizeof(block_q8_1) / QK8_1);
4194
4499
  char * src1_ddq = src1_q8_alloc.get();
4195
- quantize_row_q8_1_sycl<quantize_q8_1>(
4196
- (const float *) src1->data, src1_ddq, (int) ne10, (int) ne11,
4197
- src1_padded_cols, stream);
4500
+ if (use_reorder) {
4501
+ quantize_row_q8_1_sycl<quantize_and_reorder_q8_1_soa>(
4502
+ (const float *) src1->data, src1_ddq, (int) ne10, (int) ne11,
4503
+ src1_padded_cols, stream);
4504
+ } else {
4505
+ quantize_row_q8_1_sycl<quantize_q8_1>(
4506
+ (const float *) src1->data, src1_ddq, (int) ne10, (int) ne11,
4507
+ src1_padded_cols, stream);
4508
+ }
4198
4509
 
4199
4510
  const size_t bytes_per_qrow = (size_t) src1_padded_cols * sizeof(block_q8_1) / QK8_1;
4200
4511
  const size_t src1_row_stride = (ne11 == 1) ? 0 : bytes_per_qrow;
4201
4512
 
4513
+ if (use_reorder) {
4514
+ return ggml_sycl_mul_mat_vec_q_id_reorder(
4515
+ src0->type, src0->data, src1_ddq, (const int32_t *) ids->data,
4516
+ (float *) dst->data, (int) ne10, nrows, n_experts_used,
4517
+ /*expert_weight_stride=*/ src0->nb[2],
4518
+ /*dst_row_stride=*/ dst->nb[1],
4519
+ src1_row_stride, stream);
4520
+ }
4202
4521
  return ggml_sycl_mul_mat_vec_q_id(
4203
4522
  src0->type, src0->data, src1_ddq, (const int32_t *) ids->data,
4204
4523
  (float *) dst->data, (int) ne10, nrows, n_experts_used,
@@ -4274,6 +4593,8 @@ static void ggml_sycl_mul_mat_id(ggml_backend_sycl_context & ctx,
4274
4593
 
4275
4594
  SYCL_CHECK(CHECK_TRY_ERROR(
4276
4595
  stream->memcpy(ids_host.data(), ids_dev, ggml_nbytes(ids))));
4596
+
4597
+ // also ensures ctx.mmid_row_mapping_host is drained before we use it again
4277
4598
  SYCL_CHECK(CHECK_TRY_ERROR(stream->wait()));
4278
4599
 
4279
4600
  ggml_tensor src0_row = *src0;
@@ -4331,7 +4652,7 @@ static void ggml_sycl_mul_mat_id(ggml_backend_sycl_context & ctx,
4331
4652
  // where each expert's slice starts and the previous ends (row indices, right-exclusive)
4332
4653
  std::vector<int64_t> expert_row_offsets;
4333
4654
  // the sources (slot/token pairs) of contiguous rows to guide k_copy_src1_to_contiguous
4334
- std::vector<mmid_row_mapping> routed_row_src;
4655
+ std::vector<mmid_row_mapping> & routed_row_src = ctx.mmid_row_mapping_host;
4335
4656
 
4336
4657
  mmid_counting_sort_rows(ids, ids_host.data(), n_ids, n_as, n_routed_rows,
4337
4658
  expert_row_counts, expert_row_offsets, routed_row_src);
@@ -4435,6 +4756,11 @@ static void ggml_sycl_pool2d(ggml_backend_sycl_context & ctx, ggml_tensor * dst)
4435
4756
  ggml_sycl_op_pool2d(ctx, dst);
4436
4757
  }
4437
4758
 
4759
+ static void ggml_sycl_pool1d(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
4760
+ scope_op_debug_print scope_dbg_print(__func__, dst, /*num_src=*/1);
4761
+ ggml_sycl_op_pool1d(ctx, dst);
4762
+ }
4763
+
4438
4764
  static void ggml_sycl_im2col(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
4439
4765
  scope_op_debug_print scope_dbg_print(__func__, dst, /*num_src=*/2);
4440
4766
  ggml_sycl_op_im2col(ctx, dst);
@@ -4445,6 +4771,16 @@ static void ggml_sycl_im2col_3d(ggml_backend_sycl_context & ctx, ggml_tensor * d
4445
4771
  ggml_sycl_op_im2col_3d(ctx, dst);
4446
4772
  }
4447
4773
 
4774
+ static void ggml_sycl_col2im_1d(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
4775
+ scope_op_debug_print scope_dbg_print(__func__, dst, /*num_src=*/1);
4776
+ ggml_sycl_op_col2im_1d(ctx, dst);
4777
+ }
4778
+
4779
+ static void ggml_sycl_conv_3d(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
4780
+ scope_op_debug_print scope_dbg_print(__func__, dst, /*num_src=*/2);
4781
+ ggml_sycl_op_conv_3d(ctx, dst);
4782
+ }
4783
+
4448
4784
  static void ggml_sycl_sum(ggml_backend_sycl_context & ctx, ggml_tensor * dst) {
4449
4785
  scope_op_debug_print scope_dbg_print(__func__, dst, /*num_src=*/1);
4450
4786
  GGML_ASSERT(ggml_is_contiguous(dst->src[0]));
@@ -4508,9 +4844,21 @@ static bool ggml_sycl_compute_forward(ggml_backend_sycl_context & ctx, struct gg
4508
4844
  case GGML_OP_ARGMAX:
4509
4845
  ggml_sycl_argmax(ctx, dst);
4510
4846
  break;
4847
+ case GGML_OP_CONV_2D:
4848
+ ggml_sycl_op_conv2d(ctx, dst);
4849
+ break;
4850
+ case GGML_OP_CONV_2D_DW:
4851
+ ggml_sycl_op_conv2d_dw(ctx, dst);
4852
+ break;
4853
+ case GGML_OP_CONV_3D:
4854
+ ggml_sycl_conv_3d(ctx, dst);
4855
+ break;
4511
4856
  case GGML_OP_CONV_TRANSPOSE_1D:
4512
4857
  ggml_sycl_op_conv_transpose_1d(ctx, dst);
4513
4858
  break;
4859
+ case GGML_OP_CONV_TRANSPOSE_2D:
4860
+ ggml_sycl_op_conv2d_transpose(ctx, dst);
4861
+ break;
4514
4862
  case GGML_OP_REPEAT:
4515
4863
  ggml_sycl_repeat(ctx, dst);
4516
4864
  break;
@@ -4592,6 +4940,9 @@ static bool ggml_sycl_compute_forward(ggml_backend_sycl_context & ctx, struct gg
4592
4940
  case GGML_UNARY_OP_EXP:
4593
4941
  ggml_sycl_exp(ctx, dst);
4594
4942
  break;
4943
+ case GGML_UNARY_OP_EXPM1:
4944
+ ggml_sycl_expm1(ctx, dst);
4945
+ break;
4595
4946
  case GGML_UNARY_OP_SOFTPLUS:
4596
4947
  ggml_sycl_softplus(ctx, dst);
4597
4948
  break;
@@ -4733,6 +5084,12 @@ static bool ggml_sycl_compute_forward(ggml_backend_sycl_context & ctx, struct gg
4733
5084
  case GGML_OP_SOFT_MAX_BACK:
4734
5085
  ggml_sycl_op_soft_max_back(ctx, dst);
4735
5086
  break;
5087
+ case GGML_OP_CROSS_ENTROPY_LOSS:
5088
+ ggml_sycl_cross_entropy_loss(ctx, dst);
5089
+ break;
5090
+ case GGML_OP_CROSS_ENTROPY_LOSS_BACK:
5091
+ ggml_sycl_cross_entropy_loss_back(ctx, dst);
5092
+ break;
4736
5093
  case GGML_OP_ROPE:
4737
5094
  ggml_sycl_rope(ctx, dst);
4738
5095
  break;
@@ -4745,9 +5102,15 @@ static bool ggml_sycl_compute_forward(ggml_backend_sycl_context & ctx, struct gg
4745
5102
  case GGML_OP_IM2COL_3D:
4746
5103
  ggml_sycl_im2col_3d(ctx, dst);
4747
5104
  break;
5105
+ case GGML_OP_COL2IM_1D:
5106
+ ggml_sycl_col2im_1d(ctx, dst);
5107
+ break;
4748
5108
  case GGML_OP_POOL_2D:
4749
5109
  ggml_sycl_pool2d(ctx, dst);
4750
5110
  break;
5111
+ case GGML_OP_POOL_1D:
5112
+ ggml_sycl_pool1d(ctx, dst);
5113
+ break;
4751
5114
  case GGML_OP_SUM:
4752
5115
  ggml_sycl_sum(ctx, dst);
4753
5116
  break;
@@ -5022,7 +5385,10 @@ static ggml_status ggml_backend_sycl_graph_compute(ggml_backend_t backend, ggml_
5022
5385
  auto * sycl_ctx = static_cast<ggml_backend_sycl_context *>(backend->context);
5023
5386
 
5024
5387
  #ifdef GGML_SYCL_GRAPH
5025
- bool use_sycl_graph = !g_ggml_sycl_disable_graph && check_graph_compatibility(cgraph);
5388
+ bool use_sycl_graph = false;
5389
+ if (g_ggml_sycl_enable_graph) {
5390
+ use_sycl_graph = check_graph_compatibility(cgraph);
5391
+ }
5026
5392
  if (use_sycl_graph) {
5027
5393
  const bool graph_support = dpct::get_device(sycl_ctx->device).has(sycl::aspect::ext_oneapi_limited_graph);
5028
5394
  if (!graph_support) {
@@ -5208,7 +5574,7 @@ static ggml_backend_buffer_t ggml_backend_sycl_device_buffer_from_host_ptr(ggml_
5208
5574
  return nullptr;
5209
5575
  }
5210
5576
 
5211
- static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
5577
+ static bool do_ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
5212
5578
  ggml_backend_sycl_device_context *sycl_ctx =
5213
5579
  (ggml_backend_sycl_device_context *)dev->context;
5214
5580
  int device = sycl_ctx->device;
@@ -5222,6 +5588,10 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5222
5588
  }
5223
5589
  return false;
5224
5590
  }
5591
+ case GGML_OP_CONV_2D:
5592
+ case GGML_OP_CONV_2D_DW:
5593
+ case GGML_OP_CONV_TRANSPOSE_2D:
5594
+ return true;
5225
5595
  case GGML_OP_UNARY:
5226
5596
  switch (ggml_get_unary_op(op)) {
5227
5597
  case GGML_UNARY_OP_SGN:
@@ -5238,6 +5608,7 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5238
5608
  case GGML_UNARY_OP_GELU_QUICK:
5239
5609
  case GGML_UNARY_OP_GELU_ERF:
5240
5610
  case GGML_UNARY_OP_EXP:
5611
+ case GGML_UNARY_OP_EXPM1:
5241
5612
  case GGML_UNARY_OP_SOFTPLUS:
5242
5613
  case GGML_UNARY_OP_ELU:
5243
5614
  case GGML_UNARY_OP_CEIL:
@@ -5245,11 +5616,7 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5245
5616
  case GGML_UNARY_OP_FLOOR:
5246
5617
  case GGML_UNARY_OP_ROUND:
5247
5618
  case GGML_UNARY_OP_TRUNC:
5248
- #if defined (GGML_SYCL_F16)
5249
- return ggml_is_contiguous(op->src[0]) && (op->type == op->src[0]->type);
5250
- #else
5251
- return ggml_is_contiguous(op->src[0]) && (op->src[0]->type == GGML_TYPE_F32 && op->type == GGML_TYPE_F32) && (op->type == op->src[0]->type);
5252
- #endif
5619
+ return true;
5253
5620
  default:
5254
5621
  return false;
5255
5622
  }
@@ -5272,19 +5639,12 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5272
5639
  struct ggml_tensor * a = op->src[0];
5273
5640
  struct ggml_tensor * b = op->src[1];
5274
5641
 
5275
- // disable Q1_0 until implementation
5276
- if (a->type == GGML_TYPE_Q1_0 || b->type == GGML_TYPE_Q1_0) {
5277
- return false;
5278
- }
5279
-
5280
5642
  if (a->ne[3] != b->ne[3]) {
5281
5643
  return false;
5282
5644
  }
5283
5645
 
5284
5646
  ggml_type src0_type = op->src[0]->type;
5285
5647
 
5286
-
5287
-
5288
5648
  // TODO: The configuration below needs more work to be supported with oneDNN
5289
5649
  if (ggml_is_permuted(a) && !ggml_is_contiguous(a) &&
5290
5650
  a->ne[2] > 1 && a->ne[3] > 1 && src0_type == GGML_TYPE_F16) {
@@ -5299,7 +5659,11 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5299
5659
  return true;
5300
5660
  }
5301
5661
  case GGML_OP_OUT_PROD:
5302
- return op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32 && op->src[1]->type == GGML_TYPE_F32 && op->ne[2] == 1 && op->ne[3] == 1;
5662
+ return op->type == GGML_TYPE_F32 &&
5663
+ (op->src[0]->type == GGML_TYPE_F32 ||
5664
+ (op->src[0]->type == GGML_TYPE_Q1_0 && op->src[0]->ne[2] == op->src[1]->ne[2] &&
5665
+ op->src[0]->ne[3] == op->src[1]->ne[3])) &&
5666
+ op->src[1]->type == GGML_TYPE_F32;
5303
5667
  case GGML_OP_GET_ROWS:
5304
5668
  {
5305
5669
  switch (op->src[0]->type) {
@@ -5342,80 +5706,114 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5342
5706
 
5343
5707
  case GGML_OP_SET_ROWS:
5344
5708
  {
5345
- return ((op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16 || op->type == GGML_TYPE_BF16 ||
5709
+
5710
+ auto res = ((op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16 || op->type == GGML_TYPE_BF16 ||
5346
5711
  op->type == GGML_TYPE_Q8_0 || op->type == GGML_TYPE_Q5_1 || op->type == GGML_TYPE_Q5_0 ||
5347
- op->type == GGML_TYPE_Q4_1 || op->type == GGML_TYPE_Q4_0 || op->type == GGML_TYPE_IQ4_NL) &&
5712
+ op->type == GGML_TYPE_Q1_0 ||
5713
+ op->type == GGML_TYPE_Q4_1 || op->type == GGML_TYPE_Q4_0 || op->type == GGML_TYPE_IQ4_NL ||
5714
+ op->type == GGML_TYPE_MXFP4 || op->type == GGML_TYPE_NVFP4) &&
5715
+ op->src[0]->type == GGML_TYPE_F32 &&
5348
5716
  (op->src[1]->type == GGML_TYPE_I64 || op->src[1]->type == GGML_TYPE_I32));
5717
+ return res;
5349
5718
  }
5350
5719
  break;
5351
5720
  case GGML_OP_CPY:
5352
5721
  {
5353
5722
  ggml_type src0_type = op->src[0]->type;
5354
5723
  ggml_type src1_type = op->src[1]->type;
5355
- if (src0_type == src1_type && (ggml_is_contiguous(op->src[0]) && ggml_is_contiguous(op->src[1])) && src0_type != GGML_TYPE_BF16) {
5356
- return true;
5357
- }
5358
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F32) {
5359
- return true;
5360
- }
5361
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_F16) {
5362
- return true;
5363
- }
5364
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q8_0) {
5365
- return true;
5366
- }
5367
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q4_0) {
5368
- return true;
5369
- }
5370
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q4_1) {
5371
- return true;
5372
- }
5373
- if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F16) {
5374
- return true;
5375
- }
5376
- if (src0_type == GGML_TYPE_F16 && src1_type == GGML_TYPE_F32) {
5377
- return true;
5378
- }
5379
- if (src0_type == GGML_TYPE_Q8_0 && src1_type == GGML_TYPE_F32) {
5380
- return true;
5381
- }
5382
- if (src0_type == GGML_TYPE_Q4_0 && src1_type == GGML_TYPE_F32) {
5383
- return true;
5384
- }
5385
- if (src0_type == GGML_TYPE_Q4_1 && src1_type == GGML_TYPE_F32) {
5386
- return true;
5387
- }
5388
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q5_0) {
5389
- return true;
5390
- }
5391
- if (src0_type == GGML_TYPE_Q5_0 && src1_type == GGML_TYPE_F32) {
5392
- return true;
5393
- }
5394
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_Q5_1) {
5395
- return true;
5396
- }
5397
- if (src0_type == GGML_TYPE_Q5_1 && src1_type == GGML_TYPE_F32) {
5398
- return true;
5399
- }
5400
- if (src0_type == GGML_TYPE_F32 && src1_type == GGML_TYPE_IQ4_NL) {
5401
- return true;
5402
- }
5403
- if(src0_type == GGML_TYPE_Q8_0 && src1_type == GGML_TYPE_Q8_0) {
5404
- return true;
5724
+
5725
+ if (src0_type == GGML_TYPE_F16) {
5726
+ if (src1_type == GGML_TYPE_Q2_K ||
5727
+ src1_type == GGML_TYPE_Q3_K ||
5728
+ src1_type == GGML_TYPE_Q4_K ||
5729
+ src1_type == GGML_TYPE_Q5_K ||
5730
+ src1_type == GGML_TYPE_Q6_K ||
5731
+ src1_type == GGML_TYPE_IQ2_XXS ||
5732
+ src1_type == GGML_TYPE_IQ2_XS ||
5733
+ src1_type == GGML_TYPE_IQ2_S ||
5734
+ src1_type == GGML_TYPE_IQ3_XXS ||
5735
+ src1_type == GGML_TYPE_IQ1_S ||
5736
+ src1_type == GGML_TYPE_IQ1_M ||
5737
+ src1_type == GGML_TYPE_IQ3_S ||
5738
+ src1_type == GGML_TYPE_IQ4_XS) {
5739
+ return false;
5740
+ }
5405
5741
  }
5406
- if(src0_type == GGML_TYPE_Q5_0 && src1_type == GGML_TYPE_Q5_0) {
5407
- return true;
5742
+
5743
+ if (src0_type == GGML_TYPE_BF16) {
5744
+ if (src1_type == GGML_TYPE_Q4_0 || //big error in ut
5745
+ src1_type == GGML_TYPE_Q4_1 || //big error in ut
5746
+ src1_type == GGML_TYPE_Q8_0 || //big error in ut
5747
+ src1_type == GGML_TYPE_Q2_K ||
5748
+ src1_type == GGML_TYPE_Q3_K ||
5749
+ src1_type == GGML_TYPE_Q4_K ||
5750
+ src1_type == GGML_TYPE_Q5_K ||
5751
+ src1_type == GGML_TYPE_Q6_K ||
5752
+ src1_type == GGML_TYPE_IQ2_XXS ||
5753
+ src1_type == GGML_TYPE_IQ2_XS ||
5754
+ src1_type == GGML_TYPE_IQ2_S ||
5755
+ src1_type == GGML_TYPE_IQ3_XXS ||
5756
+ src1_type == GGML_TYPE_IQ1_S ||
5757
+ src1_type == GGML_TYPE_IQ1_M ||
5758
+ src1_type == GGML_TYPE_IQ3_S ||
5759
+ src1_type == GGML_TYPE_IQ4_XS) {
5760
+ return false;
5761
+ }
5408
5762
  }
5409
- if(src0_type == GGML_TYPE_Q5_1 && src1_type == GGML_TYPE_Q5_1) {
5410
- return true;
5763
+
5764
+ if (src0_type == GGML_TYPE_F32) {
5765
+ if (src1_type == GGML_TYPE_Q2_K ||
5766
+ src1_type == GGML_TYPE_Q3_K ||
5767
+ src1_type == GGML_TYPE_Q4_K ||
5768
+ src1_type == GGML_TYPE_Q5_K ||
5769
+ src1_type == GGML_TYPE_Q6_K ||
5770
+ src1_type == GGML_TYPE_IQ2_XXS ||
5771
+ src1_type == GGML_TYPE_IQ2_XS ||
5772
+ src1_type == GGML_TYPE_IQ2_S ||
5773
+ src1_type == GGML_TYPE_IQ3_XXS ||
5774
+ src1_type == GGML_TYPE_IQ1_S ||
5775
+ src1_type == GGML_TYPE_IQ1_M ||
5776
+ src1_type == GGML_TYPE_IQ3_S ||
5777
+ src1_type == GGML_TYPE_IQ4_XS) {
5778
+ return false;
5779
+ }
5411
5780
  }
5412
- if(src0_type == GGML_TYPE_Q4_0 && src1_type == GGML_TYPE_Q4_0) {
5413
- return true;
5781
+
5782
+ if (src1_type == GGML_TYPE_F32) {
5783
+ if (src0_type == GGML_TYPE_Q1_0 ||
5784
+ src0_type == GGML_TYPE_NVFP4 ||
5785
+ src0_type == GGML_TYPE_Q2_K ||
5786
+ src0_type == GGML_TYPE_Q3_K ||
5787
+ src0_type == GGML_TYPE_Q4_K ||
5788
+ src0_type == GGML_TYPE_Q5_K ||
5789
+ src0_type == GGML_TYPE_Q6_K ||
5790
+ src0_type == GGML_TYPE_IQ2_XXS ||
5791
+ src0_type == GGML_TYPE_IQ2_XS ||
5792
+ src0_type == GGML_TYPE_IQ2_S ||
5793
+ src0_type == GGML_TYPE_IQ3_XXS ||
5794
+ src0_type == GGML_TYPE_IQ1_S ||
5795
+ src0_type == GGML_TYPE_IQ1_M ||
5796
+ src0_type == GGML_TYPE_IQ3_S ||
5797
+ src0_type == GGML_TYPE_IQ4_NL ||
5798
+ src0_type == GGML_TYPE_IQ4_XS
5799
+ ) {
5800
+ return false;
5801
+ }
5414
5802
  }
5415
- if(src0_type == GGML_TYPE_Q4_1 && src1_type == GGML_TYPE_Q4_1) {
5416
- return true;
5803
+
5804
+ if (src0_type == src1_type) {
5805
+ if (src1_type == GGML_TYPE_IQ2_XXS ||
5806
+ src1_type == GGML_TYPE_IQ2_XS ||
5807
+ src1_type == GGML_TYPE_IQ2_S ||
5808
+ src1_type == GGML_TYPE_IQ3_XXS ||
5809
+ src1_type == GGML_TYPE_IQ3_S ||
5810
+ src1_type == GGML_TYPE_IQ1_S ||
5811
+ src1_type == GGML_TYPE_IQ1_M) {
5812
+ return false;
5813
+ }
5417
5814
  }
5418
- return false;
5815
+
5816
+ return true;
5419
5817
  }
5420
5818
  case GGML_OP_REPEAT_BACK:
5421
5819
  {
@@ -5447,11 +5845,6 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5447
5845
  case GGML_OP_COS:
5448
5846
  case GGML_OP_CLAMP:
5449
5847
  case GGML_OP_LOG:
5450
- #if defined (GGML_SYCL_F16)
5451
- return ((op->type == GGML_TYPE_F32 || op->type == GGML_SYCL_F16) && (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_SYCL_F16) && (op->type == op->src[0]->type));
5452
- #else
5453
- return (op->type == GGML_TYPE_F32 && op->src[0]->type == GGML_TYPE_F32) && (op->type == op->src[0]->type);
5454
- #endif
5455
5848
  case GGML_OP_NORM:
5456
5849
  case GGML_OP_L2_NORM:
5457
5850
  case GGML_OP_GROUP_NORM:
@@ -5462,7 +5855,7 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5462
5855
  case GGML_OP_SCALE:
5463
5856
  return true;
5464
5857
  case GGML_OP_CONT:
5465
- return op->src[0]->type != GGML_TYPE_BF16;
5858
+ return true;
5466
5859
  case GGML_OP_TRI:
5467
5860
  {
5468
5861
  const ggml_tensor * src0 = op->src[0];
@@ -5485,13 +5878,26 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5485
5878
  case GGML_OP_IM2COL_3D:
5486
5879
  case GGML_OP_UPSCALE:
5487
5880
  return true;
5881
+ case GGML_OP_COL2IM_1D:
5882
+ return ggml_is_contiguous(op->src[0]) &&
5883
+ (op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16
5884
+ #ifdef GGML_SYCL_HAS_BF16
5885
+ || op->type == GGML_TYPE_BF16
5886
+ #endif
5887
+ ) &&
5888
+ op->src[0]->type == op->type;
5889
+ case GGML_OP_CONV_3D:
5890
+ return op->type == GGML_TYPE_F32 &&
5891
+ (op->src[0]->type == GGML_TYPE_F32 || op->src[0]->type == GGML_TYPE_F16) &&
5892
+ op->src[1]->type == GGML_TYPE_F32 &&
5893
+ ggml_is_contiguous(op->src[0]) &&
5894
+ ggml_is_contiguous(op->src[1]);
5488
5895
  case GGML_OP_SUM:
5489
5896
  case GGML_OP_SUM_ROWS:
5490
5897
  case GGML_OP_MEAN:
5491
5898
  return ggml_is_contiguous(op->src[0]);
5492
5899
  case GGML_OP_ARGSORT:
5493
- return op->src[0]->ne[0] * sizeof(int) <=
5494
- ggml_sycl_info().devices[device].smpbo;
5900
+ return true;
5495
5901
  case GGML_OP_TOP_K: {
5496
5902
  const ggml_tensor * src0 = op->src[0];
5497
5903
  const int k = op->ne[0];
@@ -5502,9 +5908,9 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5502
5908
  k > 0 && k <= 32;
5503
5909
  }
5504
5910
  case GGML_OP_POOL_2D:
5505
- return true;
5911
+ case GGML_OP_POOL_1D:
5506
5912
  case GGML_OP_ACC:
5507
- return ggml_is_contiguous(op->src[0]) && ggml_is_contiguous(op->src[1]);
5913
+ return true;
5508
5914
  case GGML_OP_PAD:
5509
5915
  if (ggml_get_op_params_i32(op, 8) != 0) {
5510
5916
  return false;
@@ -5537,6 +5943,8 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5537
5943
  case GGML_OP_FILL:
5538
5944
  case GGML_OP_CUMSUM:
5539
5945
  case GGML_OP_DIAG:
5946
+ case GGML_OP_CROSS_ENTROPY_LOSS:
5947
+ case GGML_OP_CROSS_ENTROPY_LOSS_BACK:
5540
5948
  return true;
5541
5949
  case GGML_OP_SOLVE_TRI:
5542
5950
  return op->src[0]->ne[0] <= SYCL_SOLVE_TRI_MAX_N && op->src[1]->ne[0] <= SYCL_SOLVE_TRI_MAX_K;
@@ -5549,6 +5957,13 @@ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const g
5549
5957
  GGML_UNUSED(dev);
5550
5958
  }
5551
5959
 
5960
+ static bool ggml_backend_sycl_device_supports_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
5961
+ bool res = do_ggml_backend_sycl_device_supports_op(dev, op);
5962
+ GGML_SYCL_DEBUG("[SYCL] call %s op->op=%s op->type=%s -> %s\n", __func__, ggml_op_name(op->op),
5963
+ ggml_type_name(op->type), res ? "true" : "false");
5964
+ return res;
5965
+ }
5966
+
5552
5967
  static bool ggml_backend_sycl_device_supports_buft(ggml_backend_dev_t dev, ggml_backend_buffer_type_t buft) {
5553
5968
  if (buft->iface.get_name != ggml_backend_sycl_buffer_type_get_name) {
5554
5969
  return false;
@@ -5664,6 +6079,250 @@ static ggml_backend_dev_t ggml_backend_sycl_reg_get_device(ggml_backend_reg_t re
5664
6079
  return ctx->devices[index];
5665
6080
  }
5666
6081
 
6082
+ // ==========================================================================
6083
+ // Tensor parallelism (--split-mode tensor) for the SYCL backend.
6084
+ //
6085
+ // The meta-backend invokes these three entry points via get_proc_address:
6086
+ // * ggml_backend_sycl_comm_init - one-time per-graph setup
6087
+ // * ggml_backend_sycl_comm_allreduce_tensor - per-allreduce step
6088
+ // * ggml_backend_sycl_comm_free - tear-down
6089
+ //
6090
+ // For N=2 (dual-GPU), this is a degenerate ring allreduce with dual paths
6091
+ // chosen by tensor size:
6092
+ //
6093
+ // * Small (nelem < 32K): FP32 direct memcpy + per-device ADD
6094
+ // kernel. The kernel depends_on() its corresponding memcpy event
6095
+ // so it doesn't read partial data. Both devices run in parallel.
6096
+ //
6097
+ // * Large (nelem >= 32K): BF16-compressed. Each device compresses
6098
+ // its FP32 partial to BF16 locally, cross-device memcpys
6099
+ // to the peer (half the PCI bandwidth), where it is decompressed
6100
+ // and added into the local FP32 partial. 6 SYCL submissions per
6101
+ // allreduce (2 compress + 2 memcpy + 2 decompress-add) vs the
6102
+ // 4 for the small path, but the bandwidth saving > 6 GB/s PCIe x 2
6103
+ // dominates for larger tensors.
6104
+ //
6105
+ // Storage: A persistent uint8_t buffer per device, sized to
6106
+ // 4 * nelem bytes. Both paths reinterpret the same bytes (small path
6107
+ // as nelem floats; large path as outbox + inbox = 2*nelem uint16_t
6108
+ // each, using the full 4*nelem byte budget either way). Single
6109
+ // alloc+free per device keeps the SYCL pool's strict-LIFO invariant
6110
+ // trivial.
6111
+ //
6112
+ // For non-(N=2 FP32 contiguous) cases, comm_init or comm_allreduce_tensor
6113
+ // returns null/false, causing the meta-backend to use its generic
6114
+ // butterfly all-reduce fallback.
6115
+ // ==========================================================================
6116
+
6117
+ struct ggml_backend_sycl_comm_context {
6118
+ std::vector<ggml_backend_t> backends;
6119
+ // ONE persistent per-device byte buffer, 4*nelem bytes. Both the
6120
+ // FP32 small-tensor path and the BF16 large-tensor path share it
6121
+ // by reinterpreting.
6122
+ std::unique_ptr<ggml_sycl_pool_alloc<uint8_t>> buf0;
6123
+ std::unique_ptr<ggml_sycl_pool_alloc<uint8_t>> buf1;
6124
+ int64_t buf_nelem = 0;
6125
+ };
6126
+
6127
+ void * ggml_backend_sycl_comm_init(ggml_backend_t * backends, size_t n_backends) try {
6128
+ for (size_t i = 0; i < n_backends; ++i) {
6129
+ if (!ggml_backend_is_sycl(backends[i])) {
6130
+ return nullptr;
6131
+ }
6132
+ }
6133
+
6134
+ // Initial version: N=2 only. For N!=2, returning null makes the
6135
+ // meta-backend skip this backend-specific allreduce entirely.
6136
+ if (n_backends != 2) {
6137
+ return nullptr;
6138
+ }
6139
+
6140
+ auto * ctx = new ggml_backend_sycl_comm_context;
6141
+ ctx->backends.assign(backends, backends + n_backends);
6142
+ auto * sctx0 = (ggml_backend_sycl_context *) backends[0]->context;
6143
+ auto * sctx1 = (ggml_backend_sycl_context *) backends[1]->context;
6144
+ ctx->buf0 = std::make_unique<ggml_sycl_pool_alloc<uint8_t>>(sctx0->pool());
6145
+ ctx->buf1 = std::make_unique<ggml_sycl_pool_alloc<uint8_t>>(sctx1->pool());
6146
+ return ctx;
6147
+ }
6148
+ catch (const sycl::exception &) { return nullptr; }
6149
+ catch (...) { return nullptr; }
6150
+
6151
+ void ggml_backend_sycl_comm_free(void * comm_ctx_v) {
6152
+ auto * comm_ctx = static_cast<ggml_backend_sycl_comm_context *>(comm_ctx_v);
6153
+ if (comm_ctx == nullptr) {
6154
+ return;
6155
+ }
6156
+
6157
+ // Sync both per-device queues so the pool_alloc destructors don't
6158
+ // return memory still in use by the last kernel.
6159
+ if (comm_ctx->backends.size() == 2) {
6160
+ auto * sctx0 = (ggml_backend_sycl_context *) comm_ctx->backends[0]->context;
6161
+ auto * sctx1 = (ggml_backend_sycl_context *) comm_ctx->backends[1]->context;
6162
+ try {
6163
+ sctx0->stream()->wait();
6164
+ sctx1->stream()->wait();
6165
+ } catch (...) { /* best effort during shutdown */ }
6166
+ }
6167
+
6168
+ delete comm_ctx;
6169
+ }
6170
+
6171
+ bool ggml_backend_sycl_comm_allreduce_tensor(void * comm_ctx_v, struct ggml_tensor ** tensors) try {
6172
+ if (comm_ctx_v == nullptr) {
6173
+ return false;
6174
+ }
6175
+
6176
+ auto * comm_ctx = static_cast<ggml_backend_sycl_comm_context *>(comm_ctx_v);
6177
+ const size_t n_backends = comm_ctx->backends.size();
6178
+
6179
+ // Fast path: N=2, F32/F16, contiguous, matching shapes.
6180
+ if (n_backends != 2) {
6181
+ return false;
6182
+ }
6183
+ // Accept F32 or F16 inputs natively (types must match). F16 takes the
6184
+ // direct 2-byte memcpy + add path below; other types return false so the
6185
+ // meta-backend uses its generic all-reduce.
6186
+ if (tensors[0]->type != tensors[1]->type) {
6187
+ return false;
6188
+ }
6189
+ if (tensors[0]->type != GGML_TYPE_F32 && tensors[0]->type != GGML_TYPE_F16) {
6190
+ return false;
6191
+ }
6192
+ if (!ggml_is_contiguous(tensors[0]) || !ggml_is_contiguous(tensors[1])) {
6193
+ return false;
6194
+ }
6195
+ if (ggml_nelements(tensors[0]) != ggml_nelements(tensors[1])) {
6196
+ return false;
6197
+ }
6198
+
6199
+ const int64_t nelem = ggml_nelements(tensors[0]);
6200
+ const size_t nbytes = ggml_nbytes(tensors[0]);
6201
+ if (nelem == 0) {
6202
+ return true;
6203
+ }
6204
+
6205
+ auto * ctx0 = (ggml_backend_sycl_context *) comm_ctx->backends[0]->context;
6206
+ auto * ctx1 = (ggml_backend_sycl_context *) comm_ctx->backends[1]->context;
6207
+ queue_ptr q0 = ctx0->stream();
6208
+ queue_ptr q1 = ctx1->stream();
6209
+
6210
+ // Grow per-device byte buffers if needed (4 * nelem bytes each).
6211
+ if (comm_ctx->buf_nelem < nelem) {
6212
+ comm_ctx->buf0->realloc(nelem * 4);
6213
+ comm_ctx->buf1->realloc(nelem * 4);
6214
+ comm_ctx->buf_nelem = nelem;
6215
+ }
6216
+ uint8_t * buf0 = comm_ctx->buf0->get();
6217
+ uint8_t * buf1 = comm_ctx->buf1->get();
6218
+
6219
+ // F16 native path: direct 2-byte cross-device copy + add, skipping the
6220
+ // F32 round-trip the meta-backend fallback would force. Cross-device copies
6221
+ // go through dev2dev_memcpy because the two devices are in separate SYCL
6222
+ // contexts (a raw peer-USM q->memcpy would be a silent no-op).
6223
+ if (tensors[0]->type == GGML_TYPE_F16) {
6224
+ sycl::half * f16_out0 = (sycl::half *) tensors[0]->data;
6225
+ sycl::half * f16_out1 = (sycl::half *) tensors[1]->data;
6226
+ sycl::half * f16_tmp0 = (sycl::half *) buf0;
6227
+ sycl::half * f16_tmp1 = (sycl::half *) buf1;
6228
+
6229
+ q0->wait();
6230
+ q1->wait();
6231
+ dev2dev_memcpy(ctx0->device, *q0, ctx1->device, *q1, f16_tmp0, tensors[1]->data, nbytes);
6232
+ dev2dev_memcpy(ctx1->device, *q1, ctx0->device, *q0, f16_tmp1, tensors[0]->data, nbytes);
6233
+
6234
+ q0->submit([&](sycl::handler & h) {
6235
+ h.parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6236
+ f16_out0[i] = (sycl::half) ((float) f16_out0[i] + (float) f16_tmp0[i]);
6237
+ });
6238
+ });
6239
+ q1->submit([&](sycl::handler & h) {
6240
+ h.parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6241
+ f16_out1[i] = (sycl::half) ((float) f16_out1[i] + (float) f16_tmp1[i]);
6242
+ });
6243
+ });
6244
+ return true;
6245
+ }
6246
+
6247
+ float * out0 = (float *) tensors[0]->data;
6248
+ float * out1 = (float *) tensors[1]->data;
6249
+
6250
+ // BF16 threshold: above this, the PCIe savings from halving the
6251
+ // cross-device bytes outweigh the 2 extra compress kernels.
6252
+ // Below: stay on the FP32 fast path. Threshold mirrors the CUDA
6253
+ // NCCL allreduce pattern for n_backends=2.
6254
+ static constexpr int64_t BF16_THRESHOLD = 32768;
6255
+
6256
+ if (nelem < BF16_THRESHOLD) {
6257
+ // FP32 small path: 4 SYCL submissions per allreduce.
6258
+ float * tmp0 = (float *) buf0;
6259
+ float * tmp1 = (float *) buf1;
6260
+
6261
+ // COMM-D2D-FIX: the two devices are in SEPARATE SYCL contexts, so a raw
6262
+ // q->memcpy of a peer USM pointer is a silent no-op. Route cross-device
6263
+ // copies through dev2dev_memcpy (L0 direct copy / host staging). It is
6264
+ // synchronous, so wait for the local partials to be produced first.
6265
+ q0->wait();
6266
+ q1->wait();
6267
+ dev2dev_memcpy(ctx0->device, *q0, ctx1->device, *q1, tmp0, tensors[1]->data, nbytes);
6268
+ dev2dev_memcpy(ctx1->device, *q1, ctx0->device, *q0, tmp1, tensors[0]->data, nbytes);
6269
+
6270
+ q0->submit([&](sycl::handler & h) {
6271
+ h.parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6272
+ out0[i] += tmp0[i];
6273
+ });
6274
+ });
6275
+ q1->submit([&](sycl::handler & h) {
6276
+ h.parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6277
+ out1[i] += tmp1[i];
6278
+ });
6279
+ });
6280
+ return true;
6281
+ }
6282
+
6283
+ // BF16 large path: 6 SYCL submissions per allreduce, but the
6284
+ // cross-device memcpy is HALF the bytes. Pure bit-shift
6285
+ // conversion (no rounding) — matches ggml's truncating fp32->bf16.
6286
+ uint16_t * outbox0 = (uint16_t *) buf0;
6287
+ uint16_t * inbox0 = outbox0 + nelem;
6288
+ uint16_t * outbox1 = (uint16_t *) buf1;
6289
+ uint16_t * inbox1 = outbox1 + nelem;
6290
+
6291
+ // Phase A: compress each device's local partial in parallel.
6292
+ sycl::event c0 = q0->parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6293
+ outbox0[i] = (uint16_t) (sycl::bit_cast<uint32_t>(out0[i]) >> 16);
6294
+ });
6295
+
6296
+ sycl::event c1 = q1->parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6297
+ outbox1[i] = (uint16_t) (sycl::bit_cast<uint32_t>(out1[i]) >> 16);
6298
+ });
6299
+
6300
+ // Phase B: COMM-D2D-FIX-BF16 cross-device copy of compressed bytes via
6301
+ // dev2dev_memcpy (separate SYCL contexts; sync copy after compress).
6302
+ const size_t bf16_bytes = nelem * sizeof(uint16_t);
6303
+ c0.wait();
6304
+ c1.wait();
6305
+ dev2dev_memcpy(ctx0->device, *q0, ctx1->device, *q1, inbox0, outbox1, bf16_bytes);
6306
+ dev2dev_memcpy(ctx1->device, *q1, ctx0->device, *q0, inbox1, outbox0, bf16_bytes);
6307
+
6308
+ // Phase C: decompress + add into local FP32 partial.
6309
+ q0->submit([&](sycl::handler & h) {
6310
+ h.parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6311
+ out0[i] += sycl::bit_cast<float>(((uint32_t) inbox0[i]) << 16);
6312
+ });
6313
+ });
6314
+
6315
+ q1->submit([&](sycl::handler & h) {
6316
+ h.parallel_for(sycl::range<1>(nelem), [=](sycl::id<1> i) {
6317
+ out1[i] += sycl::bit_cast<float>(((uint32_t) inbox1[i]) << 16);
6318
+ });
6319
+ });
6320
+
6321
+ return true;
6322
+ }
6323
+ catch (const sycl::exception &) { return false; }
6324
+ catch (...) { return false; }
6325
+
5667
6326
  static void *ggml_backend_sycl_reg_get_proc_address(ggml_backend_reg_t reg, const char *name) {
5668
6327
  GGML_UNUSED(reg);
5669
6328
 
@@ -5671,6 +6330,17 @@ static void *ggml_backend_sycl_reg_get_proc_address(ggml_backend_reg_t reg, cons
5671
6330
  return (void *)ggml_backend_sycl_split_buffer_type;
5672
6331
  }
5673
6332
 
6333
+ // Tensor parallelism (--split-mode tensor) entry points.
6334
+ if (strcmp(name, "ggml_backend_comm_init") == 0) {
6335
+ return (void *)ggml_backend_sycl_comm_init;
6336
+ }
6337
+ if (strcmp(name, "ggml_backend_comm_free") == 0) {
6338
+ return (void *)ggml_backend_sycl_comm_free;
6339
+ }
6340
+ if (strcmp(name, "ggml_backend_comm_allreduce_tensor") == 0) {
6341
+ return (void *)ggml_backend_sycl_comm_allreduce_tensor;
6342
+ }
6343
+
5674
6344
  // SYCL doesn't support registering host memory, left here for reference
5675
6345
  // "ggml_backend_register_host_buffer"
5676
6346
  // "ggml_backend_unregister_host_buffer"