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.
- checksums.yaml +4 -4
- data/README.md +5 -4
- data/ext/options.rb +1 -1
- data/ext/ruby_whisper.c +0 -1
- data/ext/ruby_whisper.h +7 -1
- data/ext/ruby_whisper_context.c +50 -1
- data/ext/ruby_whisper_log_settable.h +1 -2
- data/ext/ruby_whisper_params.c +9 -8
- data/ext/ruby_whisper_transcribe.cpp +0 -19
- data/ext/ruby_whisper_vad_context.c +30 -10
- data/ext/ruby_whisper_vad_context_detect.cpp +8 -9
- data/ext/ruby_whisper_vad_params.c +4 -4
- data/ext/ruby_whisper_vad_segment.c +2 -2
- data/ext/sources/CMakeLists.txt +2 -1
- data/ext/sources/cmake/parakeet.pc.in +2 -2
- data/ext/sources/cmake/whisper.pc.in +2 -2
- data/ext/sources/examples/cli/cli.cpp +9 -1
- data/ext/sources/examples/common-ggml.cpp +2 -0
- data/ext/sources/examples/vad-speech-segments/speech.cpp +3 -2
- data/ext/sources/ggml/CMakeLists.txt +3 -4
- data/ext/sources/ggml/include/ggml-cuda.h +0 -3
- data/ext/sources/ggml/include/ggml-sycl.h +8 -0
- data/ext/sources/ggml/include/ggml.h +3 -1
- data/ext/sources/ggml/src/CMakeLists.txt +8 -1
- data/ext/sources/ggml/src/ggml-backend-meta.cpp +7 -4
- data/ext/sources/ggml/src/ggml-common.h +13 -2
- data/ext/sources/ggml/src/ggml-cpu/CMakeLists.txt +1 -1
- data/ext/sources/ggml/src/ggml-cpu/amx/mmq.cpp +5 -6
- data/ext/sources/ggml/src/ggml-cpu/arch/arm/quants.c +78 -4
- data/ext/sources/ggml/src/ggml-cpu/arch/x86/quants.c +142 -4
- data/ext/sources/ggml/src/ggml-cpu/arch-fallback.h +7 -2
- data/ext/sources/ggml/src/ggml-cpu/ggml-cpu.c +14 -0
- data/ext/sources/ggml/src/ggml-cpu/llamafile/sgemm.cpp +26 -19
- data/ext/sources/ggml/src/ggml-cpu/ops.cpp +129 -46
- data/ext/sources/ggml/src/ggml-cpu/quants.c +51 -0
- data/ext/sources/ggml/src/ggml-cpu/quants.h +3 -0
- data/ext/sources/ggml/src/ggml-cpu/simd-gemm.h +1 -1
- data/ext/sources/ggml/src/ggml-cpu/simd-mappings.h +11 -0
- data/ext/sources/ggml/src/ggml-cpu/vec.cpp +2 -2
- data/ext/sources/ggml/src/ggml-cuda/binbcast.cu +90 -46
- data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
- data/ext/sources/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
- data/ext/sources/ggml/src/ggml-cuda/common.cuh +4 -0
- data/ext/sources/ggml/src/ggml-cuda/concat.cu +33 -21
- data/ext/sources/ggml/src/ggml-cuda/conv-transpose-1d.cu +14 -12
- data/ext/sources/ggml/src/ggml-cuda/convert.cu +86 -34
- data/ext/sources/ggml/src/ggml-cuda/cpy.cu +80 -29
- data/ext/sources/ggml/src/ggml-cuda/fattn-common.cuh +9 -5
- data/ext/sources/ggml/src/ggml-cuda/fattn-mma-f16.cuh +4 -0
- data/ext/sources/ggml/src/ggml-cuda/fattn-tile.cuh +9 -5
- data/ext/sources/ggml/src/ggml-cuda/fattn.cu +27 -21
- data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cu +40 -25
- data/ext/sources/ggml/src/ggml-cuda/gated_delta_net.cuh +10 -0
- data/ext/sources/ggml/src/ggml-cuda/getrows.cu +15 -12
- data/ext/sources/ggml/src/ggml-cuda/ggml-cuda.cu +718 -1248
- data/ext/sources/ggml/src/ggml-cuda/mmq.cu +7 -0
- data/ext/sources/ggml/src/ggml-cuda/mmvq.cu +77 -40
- data/ext/sources/ggml/src/ggml-cuda/out-prod.cu +55 -12
- data/ext/sources/ggml/src/ggml-cuda/set-rows.cu +64 -4
- data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +1 -0
- data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +1 -0
- data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +1 -0
- data/ext/sources/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +1 -0
- data/ext/sources/ggml/src/ggml-cuda/topk-moe.cu +7 -1
- data/ext/sources/ggml/src/ggml-cuda/vendors/hip.h +1 -0
- data/ext/sources/ggml/src/ggml-cuda/vendors/musa.h +1 -0
- data/ext/sources/ggml/src/ggml-hexagon/CMakeLists.txt +0 -5
- data/ext/sources/ggml/src/ggml-hexagon/ggml-hexagon.cpp +1634 -1293
- data/ext/sources/ggml/src/ggml-hexagon/htp/CMakeLists.txt +11 -40
- data/ext/sources/ggml/src/ggml-hexagon/htp/cmake-toolchain.cmake +13 -15
- data/ext/sources/ggml/src/ggml-hexagon/htp/concat-ops.c +1 -1
- data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.c +1749 -399
- data/ext/sources/ggml/src/ggml-hexagon/htp/flash-attn-ops.h +303 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hex-common.h +80 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hex-dma.h +26 -23
- data/ext/sources/ggml/src/ggml-hexagon/htp/hex-profile.h +64 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hex-utils.h +1 -83
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-fa-kernels.h +555 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-mm-kernels-tiled.h +1303 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.c +9 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-queue.h +27 -4
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-utils.h +59 -37
- data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ctx.h +11 -3
- data/ext/sources/ggml/src/ggml-hexagon/htp/htp-ops.h +52 -12
- data/ext/sources/ggml/src/ggml-hexagon/htp/htp-vtcm.h +19 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/htp_iface.idl +2 -1
- data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-base.h +14 -30
- data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-exp.h +39 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-fa-kernels.h +232 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-flat.h +1511 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-mm-kernels-tiled.h +1200 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/hvx-sigmoid.h +39 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/main.c +127 -32
- data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.c +3023 -4425
- data/ext/sources/ggml/src/ggml-hexagon/htp/matmul-ops.h +650 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp/rope-ops.c +48 -13
- data/ext/sources/ggml/src/ggml-hexagon/htp/ssm-conv.c +10 -9
- data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.c +15 -3
- data/ext/sources/ggml/src/ggml-hexagon/htp/worker-pool.h +8 -0
- data/ext/sources/ggml/src/ggml-hexagon/htp-opnode.h +168 -50
- data/ext/sources/ggml/src/ggml-hexagon/libggml-htp.inf +0 -4
- data/ext/sources/ggml/src/ggml-hip/CMakeLists.txt +5 -0
- data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.cpp +69 -5
- data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.h +4 -1
- data/ext/sources/ggml/src/ggml-metal/ggml-metal-device.m +27 -6
- data/ext/sources/ggml/src/ggml-metal/ggml-metal-impl.h +38 -0
- data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.cpp +132 -2
- data/ext/sources/ggml/src/ggml-metal/ggml-metal-ops.h +2 -0
- data/ext/sources/ggml/src/ggml-metal/ggml-metal.metal +345 -87
- data/ext/sources/ggml/src/ggml-opencl/CMakeLists.txt +13 -0
- data/ext/sources/ggml/src/ggml-opencl/fa_tune.h +92 -0
- data/ext/sources/ggml/src/ggml-opencl/ggml-opencl.cpp +4060 -357
- data/ext/sources/ggml/src/ggml-opencl/kernels/cvt.cl +198 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f16.cl +81 -41
- data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32.cl +88 -39
- data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_f16.cl +1995 -96
- data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q4_0.cl +1615 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_f32_q8_0.cl +1486 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/flash_attn_pre_f16.cl +156 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_mxfp4_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_0_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_1_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q4_k_f32_ns.cl +71 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_0_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_1_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q5_k_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_moe_q6_k_f32_ns.cl +74 -6
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemm_noshuffle_q1_0_f32.cl +94 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q1_0_f32.cl +121 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/gemv_noshuffle_q8_0_f32.cl +1 -1
- data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mm_q1_0_f32_l4_lm.cl +156 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_f16_f32_l4.cl +1149 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32.cl +141 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/mul_mv_q1_0_f32_flat.cl +190 -0
- data/ext/sources/ggml/src/ggml-opencl/kernels/norm.cl +5 -2
- data/ext/sources/ggml/src/ggml-opencl/kernels/set_rows.cl +500 -0
- data/ext/sources/ggml/src/ggml-opencl/libdl.h +79 -0
- data/ext/sources/ggml/src/ggml-openvino/.clang-format +0 -5
- data/ext/sources/ggml/src/ggml-openvino/CMakeLists.txt +2 -4
- data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.cpp +733 -130
- data/ext/sources/ggml/src/ggml-openvino/ggml-decoder.h +76 -23
- data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.cpp +57 -3
- data/ext/sources/ggml/src/ggml-openvino/ggml-openvino-extra.h +29 -8
- data/ext/sources/ggml/src/ggml-openvino/ggml-openvino.cpp +307 -59
- data/ext/sources/ggml/src/ggml-openvino/ggml-quants.cpp +66 -0
- data/ext/sources/ggml/src/ggml-openvino/ggml-quants.h +10 -4
- data/ext/sources/ggml/src/ggml-openvino/openvino/decoder.h +56 -16
- data/ext/sources/ggml/src/ggml-openvino/openvino/frontend.h +1 -1
- data/ext/sources/ggml/src/ggml-openvino/openvino/input_model.h +4 -4
- data/ext/sources/ggml/src/ggml-openvino/openvino/node_context.h +94 -37
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/add_id.cpp +76 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/argsort.cpp +47 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/clamp.cpp +33 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/concat.cpp +48 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/cont.cpp +8 -16
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/cpy.cpp +14 -1
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/div.cpp +146 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/flash_attn_ext.cpp +108 -21
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.cpp +282 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/gated_delta_net.hpp +65 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/get_rows.cpp +2 -9
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_geglu.cpp +21 -7
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/glu_swiglu.cpp +41 -8
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/im2col.cpp +120 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/l2_norm.cpp +44 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/mul_mat_id.cpp +226 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/mulmat.cpp +19 -9
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/norm.cpp +58 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/pad.cpp +95 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/permute.cpp +58 -13
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/repeat.cpp +74 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/reshape.cpp +13 -6
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/rms_norm.cpp +1 -1
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/rope.cpp +134 -38
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/set_rows.cpp +3 -3
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/softmax.cpp +126 -49
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/ssm_conv.cpp +59 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/sum_rows.cpp +27 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/transpose.cpp +32 -1
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_silu.cpp +1 -1
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_softplus.cpp +38 -0
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/view.cpp +90 -25
- data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.cpp +41 -23
- data/ext/sources/ggml/src/ggml-openvino/openvino/op_table.h +18 -5
- data/ext/sources/ggml/src/ggml-openvino/openvino/pass/mark_decompression_convert_constant_folding.h +1 -1
- data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.cpp +43 -40
- data/ext/sources/ggml/src/ggml-openvino/openvino/translate_session.h +5 -4
- data/ext/sources/ggml/src/ggml-openvino/openvino/utils.cpp +548 -3
- data/ext/sources/ggml/src/ggml-openvino/openvino/utils.h +28 -26
- data/ext/sources/ggml/src/ggml-openvino/utils.cpp +383 -94
- data/ext/sources/ggml/src/ggml-openvino/utils.h +11 -8
- data/ext/sources/ggml/src/ggml-quants.c +76 -0
- data/ext/sources/ggml/src/ggml-quants.h +3 -0
- data/ext/sources/ggml/src/ggml-sycl/CMakeLists.txt +5 -5
- data/ext/sources/ggml/src/ggml-sycl/backend.hpp +2 -0
- data/ext/sources/ggml/src/ggml-sycl/binbcast.cpp +12 -0
- data/ext/sources/ggml/src/ggml-sycl/col2im-1d.cpp +102 -0
- data/ext/sources/ggml/src/ggml-sycl/col2im-1d.hpp +8 -0
- data/ext/sources/ggml/src/ggml-sycl/common.cpp +6 -8
- data/ext/sources/ggml/src/ggml-sycl/common.hpp +19 -2
- data/ext/sources/ggml/src/ggml-sycl/concat.cpp +21 -1
- data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.cpp +158 -0
- data/ext/sources/ggml/src/ggml-sycl/conv2d-dw.hpp +10 -0
- data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.cpp +125 -0
- data/ext/sources/ggml/src/ggml-sycl/conv2d-transpose.hpp +10 -0
- data/ext/sources/ggml/src/ggml-sycl/conv2d.cpp +150 -0
- data/ext/sources/ggml/src/ggml-sycl/conv2d.hpp +10 -0
- data/ext/sources/ggml/src/ggml-sycl/conv3d.cpp +224 -0
- data/ext/sources/ggml/src/ggml-sycl/conv3d.hpp +8 -0
- data/ext/sources/ggml/src/ggml-sycl/convert.cpp +6 -0
- data/ext/sources/ggml/src/ggml-sycl/cpy.cpp +706 -0
- data/ext/sources/ggml/src/ggml-sycl/cpy.hpp +281 -0
- data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.cpp +255 -0
- data/ext/sources/ggml/src/ggml-sycl/cross_entropy_loss.hpp +7 -0
- data/ext/sources/ggml/src/ggml-sycl/dequantize.hpp +15 -0
- data/ext/sources/ggml/src/ggml-sycl/dmmv.cpp +492 -319
- data/ext/sources/ggml/src/ggml-sycl/dpct/helper.hpp +15 -7
- data/ext/sources/ggml/src/ggml-sycl/element_wise.cpp +215 -115
- data/ext/sources/ggml/src/ggml-sycl/element_wise.hpp +2 -0
- data/ext/sources/ggml/src/ggml-sycl/ggml-sycl.cpp +1006 -336
- data/ext/sources/ggml/src/ggml-sycl/mmvq.cpp +252 -67
- data/ext/sources/ggml/src/ggml-sycl/mmvq.hpp +17 -0
- data/ext/sources/ggml/src/ggml-sycl/norm.cpp +103 -49
- data/ext/sources/ggml/src/ggml-sycl/outprod.cpp +45 -9
- data/ext/sources/ggml/src/ggml-sycl/pool.cpp +185 -0
- data/ext/sources/ggml/src/ggml-sycl/pool.hpp +22 -0
- data/ext/sources/ggml/src/ggml-sycl/presets.hpp +3 -1
- data/ext/sources/ggml/src/ggml-sycl/set_rows.cpp +10 -2
- data/ext/sources/ggml/src/ggml-sycl/softmax.cpp +9 -10
- data/ext/sources/ggml/src/ggml-sycl/vecdotq.hpp +35 -0
- data/ext/sources/ggml/src/ggml-vulkan/CMakeLists.txt +5 -0
- data/ext/sources/ggml/src/ggml-vulkan/ggml-vulkan.cpp +833 -215
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/col2im_1d.comp +61 -0
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv2d_mm.comp +1 -1
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/conv3d_mm.comp +431 -0
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/diag.comp +3 -3
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn.comp +1 -0
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/flash_attn_cm1.comp +1 -0
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/generic_unary_head.glsl +21 -19
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/get_rows_back.comp +25 -0
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_head.glsl +23 -4
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/glu_main.glsl +14 -18
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/l2_norm.comp +4 -7
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mat_vecq.comp +21 -24
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm.comp +31 -23
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_cm2.comp +6 -5
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/mul_mm_funcs.glsl +84 -67
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/norm.comp +10 -10
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/repeat_back.comp +3 -3
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/roll.comp +3 -3
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tri.comp +3 -3
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/unary.comp +168 -0
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/vulkan-shaders-gen.cpp +121 -74
- data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu-shader-lib.hpp +26 -19
- data/ext/sources/ggml/src/ggml-webgpu/ggml-webgpu.cpp +31 -36
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/common_decls.tmpl +16 -2
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/flash_attn_vec_split.wgsl +7 -7
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/get_rows.wgsl +21 -0
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_decls.tmpl +439 -320
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_id_vec.wgsl +2 -2
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec.wgsl +45 -39
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_acc.tmpl +586 -465
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/mul_mat_vec_q_acc.tmpl +63 -69
- data/ext/sources/ggml/src/ggml-webgpu/wgsl-shaders/quantize_q8.wgsl +14 -9
- data/ext/sources/ggml/src/ggml.c +36 -14
- data/ext/sources/include/whisper.h +21 -0
- data/ext/sources/src/whisper.cpp +164 -14
- data/lib/whisper/log_settable.rb +5 -8
- data/lib/whisper/model/uri.rb +0 -7
- data/sig/whisper.rbs +6 -0
- data/test/test_vad.rb +9 -0
- data/test/test_vad_context.rb +2 -2
- data/whispercpp.gemspec +1 -1
- metadata +62 -37
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-flash-attn-ops.c +0 -1878
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-matmul-ops.c +0 -2066
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-ops.c +0 -6
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-ops.h +0 -88
- data/ext/sources/ggml/src/ggml-hexagon/htp/hmx-profile.h +0 -34
- data/ext/sources/ggml/src/ggml-hexagon/htp/vtcm-utils.h +0 -16
- data/ext/sources/ggml/src/ggml-openvino/openvino/op/unary_gelu.cpp +0 -25
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/abs.comp +0 -21
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/ceil.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/clamp.comp +0 -17
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/cos.comp +0 -17
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/elu.comp +0 -27
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/exp.comp +0 -20
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/floor.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu.comp +0 -25
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_erf.comp +0 -39
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/gelu_quick.comp +0 -23
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardsigmoid.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/hardswish.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/leaky_relu.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/neg.comp +0 -20
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/relu.comp +0 -21
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/round.comp +0 -29
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sgn.comp +0 -21
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sigmoid.comp +0 -20
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/silu.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sin.comp +0 -17
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/softplus.comp +0 -23
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/sqrt.comp +0 -17
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/square.comp +0 -17
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/step.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/tanh.comp +0 -20
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/trunc.comp +0 -22
- data/ext/sources/ggml/src/ggml-vulkan/vulkan-shaders/xielu.comp +0 -35
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
#include "ggml-cuda/argsort.cuh"
|
|
12
12
|
#include "ggml-cuda/binbcast.cuh"
|
|
13
13
|
#include "ggml-cuda/clamp.cuh"
|
|
14
|
+
#include "ggml-cuda/col2im-1d.cuh"
|
|
14
15
|
#include "ggml-cuda/concat.cuh"
|
|
15
16
|
#include "ggml-cuda/conv-transpose-1d.cuh"
|
|
16
17
|
#include "ggml-cuda/conv2d.cuh"
|
|
@@ -542,12 +543,42 @@ struct ggml_cuda_pool_vmm : public ggml_cuda_pool {
|
|
|
542
543
|
// the memory allocation handle is no longer needed after mapping
|
|
543
544
|
CU_CHECK(cuMemRelease(handle));
|
|
544
545
|
|
|
545
|
-
// set
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
546
|
+
// VMM Bug fix for P2P access if GGML_CUDA_P2P is set, or if NCCL build
|
|
547
|
+
bool use_peer_access = getenv("GGML_CUDA_P2P") != nullptr;
|
|
548
|
+
#if defined(GGML_USE_NCCL)
|
|
549
|
+
use_peer_access = true;
|
|
550
|
+
#endif // defined(GGML_USE_NCCL)
|
|
551
|
+
|
|
552
|
+
if (use_peer_access) {
|
|
553
|
+
// NCCL implicitly enables peer access (cudaDeviceEnablePeerAccess), and
|
|
554
|
+
// GGML_CUDA_P2P enables it explicitly. Unlike cudaMalloc buffers, VMM
|
|
555
|
+
// allocations do not become peer-accessible from that alone, so access
|
|
556
|
+
// must be granted explicitly here.
|
|
557
|
+
std::vector<CUmemAccessDesc> access_descs;
|
|
558
|
+
const int device_count = ggml_cuda_info().device_count;
|
|
559
|
+
for (int id = 0; id < device_count; ++id) {
|
|
560
|
+
if (id != device) {
|
|
561
|
+
int can_access_peer = 0;
|
|
562
|
+
CUDA_CHECK(cudaDeviceCanAccessPeer(&can_access_peer, id, device));
|
|
563
|
+
if (!can_access_peer) {
|
|
564
|
+
continue;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
CUmemAccessDesc access = {};
|
|
568
|
+
access.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
|
|
569
|
+
access.location.id = id;
|
|
570
|
+
access.flags = CU_MEM_ACCESS_FLAGS_PROT_READWRITE;
|
|
571
|
+
access_descs.push_back(access);
|
|
572
|
+
}
|
|
573
|
+
CU_CHECK(cuMemSetAccess(start_ptr, reserve_size, access_descs.data(), access_descs.size()));
|
|
574
|
+
} else {
|
|
575
|
+
// set access for non P2P
|
|
576
|
+
CUmemAccessDesc access = {};
|
|
577
|
+
access.location.type = CU_MEM_LOCATION_TYPE_DEVICE;
|
|
578
|
+
access.location.id = device;
|
|
579
|
+
access.flags = CU_MEM_ACCESS_FLAGS_PROT_READWRITE;
|
|
580
|
+
CU_CHECK(cuMemSetAccess(start_ptr, reserve_size, &access, 1));
|
|
581
|
+
}
|
|
551
582
|
|
|
552
583
|
// add to the pool
|
|
553
584
|
pool_size += reserve_size;
|
|
@@ -622,18 +653,6 @@ ggml_backend_cuda_context::~ggml_backend_cuda_context() {
|
|
|
622
653
|
|
|
623
654
|
// cuda buffer
|
|
624
655
|
|
|
625
|
-
struct ggml_backend_cuda_device_context {
|
|
626
|
-
int device;
|
|
627
|
-
std::string name;
|
|
628
|
-
std::string description;
|
|
629
|
-
std::string pci_bus_id;
|
|
630
|
-
int op_offload_min_batch_size;
|
|
631
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
632
|
-
std::mutex device_mutex;
|
|
633
|
-
int active_count = 0;
|
|
634
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
635
|
-
};
|
|
636
|
-
|
|
637
656
|
struct ggml_backend_cuda_buffer_context {
|
|
638
657
|
int device;
|
|
639
658
|
void * dev_ptr = nullptr;
|
|
@@ -651,13 +670,6 @@ struct ggml_backend_cuda_buffer_context {
|
|
|
651
670
|
|
|
652
671
|
static void ggml_backend_cuda_buffer_free_buffer(ggml_backend_buffer_t buffer) {
|
|
653
672
|
ggml_backend_cuda_buffer_context * ctx = (ggml_backend_cuda_buffer_context *)buffer->context;
|
|
654
|
-
|
|
655
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
656
|
-
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) buffer->buft->device->context;
|
|
657
|
-
std::lock_guard<std::mutex> lock(dev_ctx->device_mutex);
|
|
658
|
-
dev_ctx->active_count--;
|
|
659
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
660
|
-
|
|
661
673
|
delete ctx;
|
|
662
674
|
}
|
|
663
675
|
|
|
@@ -810,12 +822,6 @@ static ggml_backend_buffer_t ggml_backend_cuda_buffer_type_alloc_buffer(ggml_bac
|
|
|
810
822
|
|
|
811
823
|
ggml_backend_cuda_buffer_context * ctx = new ggml_backend_cuda_buffer_context(buft_ctx->device, dev_ptr);
|
|
812
824
|
|
|
813
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
814
|
-
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) buft->device->context;
|
|
815
|
-
std::lock_guard<std::mutex> lock(dev_ctx->device_mutex);
|
|
816
|
-
dev_ctx->active_count++;
|
|
817
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
818
|
-
|
|
819
825
|
return ggml_backend_buffer_init(buft, ggml_backend_cuda_buffer_interface, ctx, size);
|
|
820
826
|
}
|
|
821
827
|
|
|
@@ -878,299 +884,6 @@ ggml_backend_buffer_type_t ggml_backend_cuda_buffer_type(int device) {
|
|
|
878
884
|
return &ggml_backend_cuda_buffer_types[device];
|
|
879
885
|
}
|
|
880
886
|
|
|
881
|
-
// cuda split buffer
|
|
882
|
-
|
|
883
|
-
static int64_t get_row_rounding(const std::array<float, GGML_CUDA_MAX_DEVICES> & tensor_split) {
|
|
884
|
-
int64_t row_rounding = 0;
|
|
885
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
886
|
-
if (tensor_split[id] >= (id + 1 < ggml_backend_cuda_get_device_count() ? tensor_split[id + 1] : 1.0f)) {
|
|
887
|
-
continue;
|
|
888
|
-
}
|
|
889
|
-
|
|
890
|
-
const int cc = ggml_cuda_info().devices[id].cc;
|
|
891
|
-
row_rounding = std::max(row_rounding, (int64_t)get_mmq_y_host(cc));
|
|
892
|
-
}
|
|
893
|
-
return row_rounding;
|
|
894
|
-
}
|
|
895
|
-
|
|
896
|
-
static void get_row_split(int64_t * row_low, int64_t * row_high, const ggml_tensor * tensor, const std::array<float, GGML_CUDA_MAX_DEVICES> & tensor_split, int id) {
|
|
897
|
-
const int64_t nrows = ggml_nrows(tensor);
|
|
898
|
-
const int64_t rounding = get_row_rounding(tensor_split);
|
|
899
|
-
|
|
900
|
-
*row_low = id == 0 ? 0 : nrows*tensor_split[id];
|
|
901
|
-
*row_low -= *row_low % rounding;
|
|
902
|
-
|
|
903
|
-
if (id == ggml_backend_cuda_get_device_count() - 1) {
|
|
904
|
-
*row_high = nrows;
|
|
905
|
-
} else {
|
|
906
|
-
*row_high = nrows*tensor_split[id + 1];
|
|
907
|
-
*row_high -= *row_high % rounding;
|
|
908
|
-
}
|
|
909
|
-
}
|
|
910
|
-
|
|
911
|
-
static size_t ggml_nbytes_split(const struct ggml_tensor * tensor, int nrows_split) {
|
|
912
|
-
static_assert(GGML_MAX_DIMS == 4, "GGML_MAX_DIMS is not 4 - update this function");
|
|
913
|
-
|
|
914
|
-
return nrows_split*ggml_row_size(tensor->type, tensor->ne[0]);
|
|
915
|
-
}
|
|
916
|
-
|
|
917
|
-
struct ggml_backend_cuda_split_buffer_type_context {
|
|
918
|
-
int main_device;
|
|
919
|
-
std::array<float, GGML_CUDA_MAX_DEVICES> tensor_split;
|
|
920
|
-
std::string name;
|
|
921
|
-
};
|
|
922
|
-
|
|
923
|
-
struct ggml_backend_cuda_split_buffer_context {
|
|
924
|
-
~ggml_backend_cuda_split_buffer_context() {
|
|
925
|
-
for (ggml_tensor_extra_gpu * extra : tensor_extras) {
|
|
926
|
-
for (int id = 0; id < GGML_CUDA_MAX_DEVICES; ++id) {
|
|
927
|
-
for (int64_t is = 0; is < GGML_CUDA_MAX_STREAMS; ++is) {
|
|
928
|
-
if (extra->events[id][is] != nullptr) {
|
|
929
|
-
CUDA_CHECK(cudaEventDestroy(extra->events[id][is]));
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
if (extra->data_device[id] != nullptr) {
|
|
933
|
-
CUDA_CHECK(cudaFree(extra->data_device[id]));
|
|
934
|
-
}
|
|
935
|
-
}
|
|
936
|
-
delete extra;
|
|
937
|
-
}
|
|
938
|
-
}
|
|
939
|
-
|
|
940
|
-
std::vector<ggml_tensor_extra_gpu *> tensor_extras;
|
|
941
|
-
};
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
static void ggml_backend_cuda_split_buffer_free_buffer(ggml_backend_buffer_t buffer) {
|
|
945
|
-
ggml_backend_cuda_split_buffer_context * ctx = (ggml_backend_cuda_split_buffer_context *)buffer->context;
|
|
946
|
-
delete ctx;
|
|
947
|
-
}
|
|
948
|
-
|
|
949
|
-
static void * ggml_backend_cuda_split_buffer_get_base(ggml_backend_buffer_t buffer) {
|
|
950
|
-
// the pointers are stored in the tensor extras, this is just a dummy address and never dereferenced
|
|
951
|
-
return (void *)0x1000;
|
|
952
|
-
|
|
953
|
-
GGML_UNUSED(buffer);
|
|
954
|
-
}
|
|
955
|
-
|
|
956
|
-
static enum ggml_status ggml_backend_cuda_split_buffer_init_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor) {
|
|
957
|
-
GGML_ASSERT(tensor->view_src == nullptr); // views of split tensors are not supported
|
|
958
|
-
GGML_ASSERT(ggml_is_contiguous(tensor) && "split buffers only supported for contiguous tensors");
|
|
959
|
-
|
|
960
|
-
ggml_backend_cuda_split_buffer_context * ctx = (ggml_backend_cuda_split_buffer_context *)buffer->context;
|
|
961
|
-
ggml_backend_cuda_split_buffer_type_context * buft_ctx = (ggml_backend_cuda_split_buffer_type_context *)buffer->buft->context;
|
|
962
|
-
|
|
963
|
-
const int64_t ne0 = tensor->ne[0];
|
|
964
|
-
|
|
965
|
-
ggml_tensor_extra_gpu * extra = new ggml_tensor_extra_gpu{};
|
|
966
|
-
ctx->tensor_extras.push_back(extra);
|
|
967
|
-
|
|
968
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
969
|
-
int64_t row_low, row_high;
|
|
970
|
-
get_row_split(&row_low, &row_high, tensor, buft_ctx->tensor_split, id);
|
|
971
|
-
|
|
972
|
-
int64_t nrows_split = row_high - row_low;
|
|
973
|
-
if (nrows_split == 0) {
|
|
974
|
-
continue;
|
|
975
|
-
}
|
|
976
|
-
|
|
977
|
-
size_t size = ggml_nbytes_split(tensor, nrows_split);
|
|
978
|
-
const size_t original_size = size;
|
|
979
|
-
|
|
980
|
-
// pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
|
|
981
|
-
if (ne0 % MATRIX_ROW_PADDING != 0) {
|
|
982
|
-
size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
|
|
983
|
-
}
|
|
984
|
-
|
|
985
|
-
// FIXME: do not crash if cudaMalloc fails
|
|
986
|
-
// currently, init_tensor cannot fail, it needs to be fixed in ggml-backend first
|
|
987
|
-
ggml_cuda_set_device(id);
|
|
988
|
-
char * buf;
|
|
989
|
-
CUDA_CHECK(ggml_cuda_device_malloc((void**)&buf, size, id));
|
|
990
|
-
|
|
991
|
-
// set padding to 0 to avoid possible NaN values
|
|
992
|
-
if (size > original_size) {
|
|
993
|
-
CUDA_CHECK(cudaMemset(buf + original_size, 0, size - original_size));
|
|
994
|
-
}
|
|
995
|
-
|
|
996
|
-
extra->data_device[id] = buf;
|
|
997
|
-
|
|
998
|
-
for (int64_t is = 0; is < GGML_CUDA_MAX_STREAMS; ++is) {
|
|
999
|
-
CUDA_CHECK(cudaEventCreateWithFlags(&extra->events[id][is], cudaEventDisableTiming));
|
|
1000
|
-
}
|
|
1001
|
-
}
|
|
1002
|
-
tensor->extra = extra;
|
|
1003
|
-
return GGML_STATUS_SUCCESS;
|
|
1004
|
-
}
|
|
1005
|
-
|
|
1006
|
-
static void ggml_backend_cuda_split_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor * tensor, const void * data, size_t offset, size_t size) {
|
|
1007
|
-
// split tensors must always be set in their entirety at once
|
|
1008
|
-
GGML_ASSERT(offset == 0);
|
|
1009
|
-
GGML_ASSERT(size == ggml_nbytes(tensor));
|
|
1010
|
-
GGML_ASSERT(ggml_is_contiguous(tensor) && "split buffers only supported for contiguous tensors");
|
|
1011
|
-
|
|
1012
|
-
ggml_backend_cuda_split_buffer_type_context * buft_ctx = (ggml_backend_cuda_split_buffer_type_context *)buffer->buft->context;
|
|
1013
|
-
|
|
1014
|
-
const int64_t ne0 = tensor->ne[0];
|
|
1015
|
-
const size_t nb1 = tensor->nb[1];
|
|
1016
|
-
ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *)tensor->extra;
|
|
1017
|
-
|
|
1018
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1019
|
-
int64_t row_low, row_high;
|
|
1020
|
-
get_row_split(&row_low, &row_high, tensor, buft_ctx->tensor_split, id);
|
|
1021
|
-
|
|
1022
|
-
int64_t nrows_split = row_high - row_low;
|
|
1023
|
-
if (nrows_split == 0) {
|
|
1024
|
-
continue;
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
const size_t offset_split = row_low*nb1;
|
|
1028
|
-
size_t size = ggml_nbytes_split(tensor, nrows_split);
|
|
1029
|
-
const size_t original_size = size;
|
|
1030
|
-
|
|
1031
|
-
// pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
|
|
1032
|
-
if (ne0 % MATRIX_ROW_PADDING != 0) {
|
|
1033
|
-
size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
|
|
1034
|
-
}
|
|
1035
|
-
|
|
1036
|
-
const char * buf_host = (const char *)data + offset_split;
|
|
1037
|
-
CUDA_CHECK(cudaMemcpyAsync(extra->data_device[id], buf_host, original_size, cudaMemcpyHostToDevice, cudaStreamPerThread));
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1041
|
-
CUDA_CHECK(cudaStreamSynchronize(cudaStreamPerThread));
|
|
1042
|
-
}
|
|
1043
|
-
}
|
|
1044
|
-
|
|
1045
|
-
static void ggml_backend_cuda_split_buffer_get_tensor(ggml_backend_buffer_t buffer, const ggml_tensor * tensor, void * data, size_t offset, size_t size) {
|
|
1046
|
-
// split tensors must always be set in their entirety at once
|
|
1047
|
-
GGML_ASSERT(offset == 0);
|
|
1048
|
-
GGML_ASSERT(size == ggml_nbytes(tensor));
|
|
1049
|
-
GGML_ASSERT(ggml_is_contiguous(tensor) && "split buffers only supported for contiguous tensors");
|
|
1050
|
-
|
|
1051
|
-
ggml_backend_cuda_split_buffer_type_context * buft_ctx = (ggml_backend_cuda_split_buffer_type_context *)buffer->buft->context;
|
|
1052
|
-
|
|
1053
|
-
const int64_t ne0 = tensor->ne[0];
|
|
1054
|
-
const size_t nb1 = tensor->nb[1];
|
|
1055
|
-
ggml_tensor_extra_gpu * extra = (ggml_tensor_extra_gpu *)tensor->extra;
|
|
1056
|
-
|
|
1057
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1058
|
-
int64_t row_low, row_high;
|
|
1059
|
-
get_row_split(&row_low, &row_high, tensor, buft_ctx->tensor_split, id);
|
|
1060
|
-
|
|
1061
|
-
int64_t nrows_split = row_high - row_low;
|
|
1062
|
-
if (nrows_split == 0) {
|
|
1063
|
-
continue;
|
|
1064
|
-
}
|
|
1065
|
-
|
|
1066
|
-
const size_t offset_split = row_low*nb1;
|
|
1067
|
-
size_t size = ggml_nbytes_split(tensor, nrows_split);
|
|
1068
|
-
const size_t original_size = size;
|
|
1069
|
-
|
|
1070
|
-
// pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
|
|
1071
|
-
if (ne0 % MATRIX_ROW_PADDING != 0) {
|
|
1072
|
-
size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
char * buf_host = (char *)data + offset_split;
|
|
1076
|
-
CUDA_CHECK(cudaMemcpyAsync(buf_host, extra->data_device[id], original_size, cudaMemcpyDeviceToHost, cudaStreamPerThread));
|
|
1077
|
-
}
|
|
1078
|
-
|
|
1079
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1080
|
-
CUDA_CHECK(cudaStreamSynchronize(cudaStreamPerThread));
|
|
1081
|
-
}
|
|
1082
|
-
}
|
|
1083
|
-
|
|
1084
|
-
static void ggml_backend_cuda_split_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
|
|
1085
|
-
GGML_UNUSED(buffer);
|
|
1086
|
-
GGML_UNUSED(value);
|
|
1087
|
-
}
|
|
1088
|
-
|
|
1089
|
-
static const ggml_backend_buffer_i ggml_backend_cuda_split_buffer_interface = {
|
|
1090
|
-
/* .free_buffer = */ ggml_backend_cuda_split_buffer_free_buffer,
|
|
1091
|
-
/* .get_base = */ ggml_backend_cuda_split_buffer_get_base,
|
|
1092
|
-
/* .init_tensor = */ ggml_backend_cuda_split_buffer_init_tensor,
|
|
1093
|
-
/* .memset_tensor = */ NULL,
|
|
1094
|
-
/* .set_tensor = */ ggml_backend_cuda_split_buffer_set_tensor,
|
|
1095
|
-
/* .get_tensor = */ ggml_backend_cuda_split_buffer_get_tensor,
|
|
1096
|
-
/* .set_tensor_2d = */ NULL,
|
|
1097
|
-
/* .get_tensor_2d = */ NULL,
|
|
1098
|
-
/* .cpy_tensor = */ NULL,
|
|
1099
|
-
/* .clear = */ ggml_backend_cuda_split_buffer_clear,
|
|
1100
|
-
/* .reset = */ NULL,
|
|
1101
|
-
};
|
|
1102
|
-
|
|
1103
|
-
// cuda split buffer type
|
|
1104
|
-
|
|
1105
|
-
static const char * ggml_backend_cuda_split_buffer_type_get_name(ggml_backend_buffer_type_t buft) {
|
|
1106
|
-
ggml_backend_cuda_split_buffer_type_context * ctx = (ggml_backend_cuda_split_buffer_type_context *)buft->context;
|
|
1107
|
-
|
|
1108
|
-
return ctx->name.c_str();
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
|
-
static bool ggml_backend_buft_is_cuda_split(ggml_backend_buffer_type_t buft) {
|
|
1112
|
-
return buft->iface.get_name == ggml_backend_cuda_split_buffer_type_get_name;
|
|
1113
|
-
}
|
|
1114
|
-
|
|
1115
|
-
static ggml_backend_buffer_t ggml_backend_cuda_split_buffer_type_alloc_buffer(ggml_backend_buffer_type_t buft, size_t size) {
|
|
1116
|
-
// since we don't know the exact split after rounding, we cannot allocate the device buffers at this point
|
|
1117
|
-
// instead, we allocate them for each tensor separately in init_tensor
|
|
1118
|
-
// however, the size still represents the maximum cumulative size of all the device buffers after the tensors are allocated,
|
|
1119
|
-
// as returned by get_alloc_size. this limit is enforced during tensor allocation by ggml-alloc, so it must be correct.
|
|
1120
|
-
ggml_backend_cuda_split_buffer_context * ctx = new ggml_backend_cuda_split_buffer_context();
|
|
1121
|
-
|
|
1122
|
-
return ggml_backend_buffer_init(buft, ggml_backend_cuda_split_buffer_interface, ctx, size);
|
|
1123
|
-
}
|
|
1124
|
-
|
|
1125
|
-
static size_t ggml_backend_cuda_split_buffer_type_get_alignment(ggml_backend_buffer_type_t buft) {
|
|
1126
|
-
return 128;
|
|
1127
|
-
|
|
1128
|
-
GGML_UNUSED(buft);
|
|
1129
|
-
}
|
|
1130
|
-
|
|
1131
|
-
static size_t ggml_backend_cuda_split_buffer_type_get_alloc_size(ggml_backend_buffer_type_t buft, const ggml_tensor * tensor) {
|
|
1132
|
-
ggml_backend_cuda_split_buffer_type_context * ctx = (ggml_backend_cuda_split_buffer_type_context *)buft->context;
|
|
1133
|
-
GGML_ASSERT(ggml_is_contiguous(tensor) && "split buffers only supported for contiguous tensors");
|
|
1134
|
-
|
|
1135
|
-
size_t total_size = 0;
|
|
1136
|
-
|
|
1137
|
-
const int64_t ne0 = tensor->ne[0];
|
|
1138
|
-
|
|
1139
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1140
|
-
int64_t row_low, row_high;
|
|
1141
|
-
get_row_split(&row_low, &row_high, tensor, ctx->tensor_split, id);
|
|
1142
|
-
|
|
1143
|
-
int64_t nrows_split = row_high - row_low;
|
|
1144
|
-
if (nrows_split == 0) {
|
|
1145
|
-
continue;
|
|
1146
|
-
}
|
|
1147
|
-
|
|
1148
|
-
total_size += ggml_nbytes_split(tensor, nrows_split);
|
|
1149
|
-
|
|
1150
|
-
// pad last row to a multiple of 512 elements to avoid out-of-bounds memory accesses
|
|
1151
|
-
if (ne0 % MATRIX_ROW_PADDING != 0) {
|
|
1152
|
-
total_size += ggml_row_size(tensor->type, MATRIX_ROW_PADDING - ne0 % MATRIX_ROW_PADDING);
|
|
1153
|
-
}
|
|
1154
|
-
}
|
|
1155
|
-
|
|
1156
|
-
return total_size;
|
|
1157
|
-
}
|
|
1158
|
-
|
|
1159
|
-
static bool ggml_backend_cuda_split_buffer_type_is_host(ggml_backend_buffer_type_t buft) {
|
|
1160
|
-
return false;
|
|
1161
|
-
|
|
1162
|
-
GGML_UNUSED(buft);
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
static const ggml_backend_buffer_type_i ggml_backend_cuda_split_buffer_type_interface = {
|
|
1166
|
-
/* .get_name = */ ggml_backend_cuda_split_buffer_type_get_name,
|
|
1167
|
-
/* .alloc_buffer = */ ggml_backend_cuda_split_buffer_type_alloc_buffer,
|
|
1168
|
-
/* .get_alignment = */ ggml_backend_cuda_split_buffer_type_get_alignment,
|
|
1169
|
-
/* .get_max_size = */ NULL, // defaults to SIZE_MAX
|
|
1170
|
-
/* .get_alloc_size = */ ggml_backend_cuda_split_buffer_type_get_alloc_size,
|
|
1171
|
-
/* .is_host = */ ggml_backend_cuda_split_buffer_type_is_host,
|
|
1172
|
-
};
|
|
1173
|
-
|
|
1174
887
|
// Communication context for multi-GPU AllReduce during tensor parallelism.
|
|
1175
888
|
//
|
|
1176
889
|
// Created once per meta backend instance. Resources for the selected mode
|
|
@@ -1460,48 +1173,6 @@ static bool ggml_backend_cuda_comm_allreduce_tensor(void * comm_ctx_v, struct gg
|
|
|
1460
1173
|
return comm_ctx->try_allreduce(comm_ctx, tensors);
|
|
1461
1174
|
}
|
|
1462
1175
|
|
|
1463
|
-
ggml_backend_buffer_type_t ggml_backend_cuda_split_buffer_type(int main_device, const float * tensor_split) {
|
|
1464
|
-
static std::mutex mutex;
|
|
1465
|
-
std::lock_guard<std::mutex> lock(mutex);
|
|
1466
|
-
|
|
1467
|
-
static std::map<std::pair<int, std::array<float, GGML_CUDA_MAX_DEVICES>>, struct ggml_backend_buffer_type> buft_map;
|
|
1468
|
-
|
|
1469
|
-
std::array<float, GGML_CUDA_MAX_DEVICES> tensor_split_arr = {};
|
|
1470
|
-
|
|
1471
|
-
bool all_zero = tensor_split == nullptr || std::all_of(tensor_split, tensor_split + GGML_CUDA_MAX_DEVICES, [](float x) { return x == 0.0f; });
|
|
1472
|
-
if (all_zero) {
|
|
1473
|
-
tensor_split_arr = ggml_cuda_info().default_tensor_split;
|
|
1474
|
-
} else {
|
|
1475
|
-
float split_sum = 0.0f;
|
|
1476
|
-
for (int i = 0; i < ggml_backend_cuda_get_device_count(); ++i) {
|
|
1477
|
-
tensor_split_arr[i] = split_sum;
|
|
1478
|
-
split_sum += tensor_split[i];
|
|
1479
|
-
}
|
|
1480
|
-
for (int i = 0; i < ggml_backend_cuda_get_device_count(); ++i) {
|
|
1481
|
-
tensor_split_arr[i] /= split_sum;
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
|
|
1485
|
-
auto it = buft_map.find({main_device, tensor_split_arr});
|
|
1486
|
-
if (it != buft_map.end()) {
|
|
1487
|
-
return &it->second;
|
|
1488
|
-
}
|
|
1489
|
-
auto * ctx = new ggml_backend_cuda_split_buffer_type_context{
|
|
1490
|
-
main_device,
|
|
1491
|
-
tensor_split_arr,
|
|
1492
|
-
GGML_CUDA_NAME + std::to_string(main_device) + "_Split",
|
|
1493
|
-
};
|
|
1494
|
-
|
|
1495
|
-
struct ggml_backend_buffer_type buft {
|
|
1496
|
-
/* .iface = */ ggml_backend_cuda_split_buffer_type_interface,
|
|
1497
|
-
/* .device = */ ggml_backend_reg_dev_get(ggml_backend_cuda_reg(), main_device),
|
|
1498
|
-
/* .context = */ ctx,
|
|
1499
|
-
};
|
|
1500
|
-
|
|
1501
|
-
auto result = buft_map.emplace(std::make_pair(main_device, tensor_split_arr), buft);
|
|
1502
|
-
return &result.first->second;
|
|
1503
|
-
}
|
|
1504
|
-
|
|
1505
1176
|
// host buffer type
|
|
1506
1177
|
|
|
1507
1178
|
static const char * ggml_backend_cuda_host_buffer_type_name(ggml_backend_buffer_type_t buft) {
|
|
@@ -1515,12 +1186,6 @@ static bool ggml_backend_buft_is_cuda_host(ggml_backend_buffer_type_t buft) {
|
|
|
1515
1186
|
}
|
|
1516
1187
|
|
|
1517
1188
|
static void ggml_backend_cuda_host_buffer_free_buffer(ggml_backend_buffer_t buffer) {
|
|
1518
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
1519
|
-
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) buffer->buft->device->context;
|
|
1520
|
-
std::lock_guard<std::mutex> lock(dev_ctx->device_mutex);
|
|
1521
|
-
dev_ctx->active_count--;
|
|
1522
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
1523
|
-
|
|
1524
1189
|
CUDA_CHECK(cudaFreeHost(buffer->context));
|
|
1525
1190
|
}
|
|
1526
1191
|
|
|
@@ -1529,8 +1194,6 @@ static void * ggml_cuda_host_malloc(size_t size) {
|
|
|
1529
1194
|
return nullptr;
|
|
1530
1195
|
}
|
|
1531
1196
|
|
|
1532
|
-
ggml_cuda_set_device(0); // cudaMallocHost can create the implicit CUDA device context, make sure that this is consistently done on device 0.
|
|
1533
|
-
|
|
1534
1197
|
void * ptr = nullptr;
|
|
1535
1198
|
cudaError_t err = cudaMallocHost((void **) &ptr, size);
|
|
1536
1199
|
if (err != cudaSuccess) {
|
|
@@ -1556,12 +1219,6 @@ static ggml_backend_buffer_t ggml_backend_cuda_host_buffer_type_alloc_buffer(ggm
|
|
|
1556
1219
|
buffer->buft = buft;
|
|
1557
1220
|
buffer->iface.free_buffer = ggml_backend_cuda_host_buffer_free_buffer;
|
|
1558
1221
|
|
|
1559
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
1560
|
-
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) buft->device->context;
|
|
1561
|
-
std::lock_guard<std::mutex> lock(dev_ctx->device_mutex);
|
|
1562
|
-
dev_ctx->active_count++;
|
|
1563
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
1564
|
-
|
|
1565
1222
|
return buffer;
|
|
1566
1223
|
}
|
|
1567
1224
|
|
|
@@ -1594,572 +1251,6 @@ typedef void (*ggml_cuda_op_mul_mat_t)(
|
|
|
1594
1251
|
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
|
1595
1252
|
const int64_t src1_padded_row_size, cudaStream_t stream);
|
|
1596
1253
|
|
|
1597
|
-
#ifndef GGML_CUDA_PEER_MAX_BATCH_SIZE
|
|
1598
|
-
#define GGML_CUDA_PEER_MAX_BATCH_SIZE 128
|
|
1599
|
-
#endif // GGML_CUDA_PEER_MAX_BATCH_SIZE
|
|
1600
|
-
|
|
1601
|
-
#define MUL_MAT_SRC1_COL_STRIDE 128
|
|
1602
|
-
|
|
1603
|
-
static cudaError_t ggml_cuda_cpy_tensor_2d(
|
|
1604
|
-
void * dst, const struct ggml_tensor * src, int64_t i3, int64_t i2, int64_t i1_low, int64_t i1_high, cudaStream_t stream) {
|
|
1605
|
-
|
|
1606
|
-
const char * src_ptr = (const char *) src->data;
|
|
1607
|
-
char * dst_ptr = (char *) dst;
|
|
1608
|
-
|
|
1609
|
-
const int64_t ne0 = src->ne[0];
|
|
1610
|
-
const int64_t nb0 = src->nb[0];
|
|
1611
|
-
const int64_t nb1 = src->nb[1];
|
|
1612
|
-
const int64_t nb2 = src->nb[2];
|
|
1613
|
-
const int64_t nb3 = src->nb[3];
|
|
1614
|
-
const enum ggml_type type = src->type;
|
|
1615
|
-
const int64_t ts = ggml_type_size(type);
|
|
1616
|
-
const int64_t bs = ggml_blck_size(type);
|
|
1617
|
-
const int64_t i1_diff = i1_high - i1_low;
|
|
1618
|
-
|
|
1619
|
-
const char * x = src_ptr + i1_low*nb1 + i2*nb2 + i3*nb3;
|
|
1620
|
-
if (nb0 == ts && nb1 == ts*ne0/bs) {
|
|
1621
|
-
return cudaMemcpyAsync(dst_ptr, x, i1_diff*nb1, cudaMemcpyDeviceToDevice, stream);
|
|
1622
|
-
} else if (nb0 == ts) {
|
|
1623
|
-
return cudaMemcpy2DAsync(dst_ptr, ts*ne0/bs, x, nb1, ts*ne0/bs, i1_diff, cudaMemcpyDeviceToDevice, stream);
|
|
1624
|
-
} else {
|
|
1625
|
-
for (int64_t i1 = 0; i1 < i1_diff; i1++) {
|
|
1626
|
-
const void * rx = (const void *) ((const char *) x + i1*nb1);
|
|
1627
|
-
void * rd = (void *) (dst_ptr + i1*ts*ne0/bs);
|
|
1628
|
-
// pretend the row is a matrix with cols=1
|
|
1629
|
-
cudaError_t r = cudaMemcpy2DAsync(rd, ts/bs, rx, nb0, ts/bs, ne0, cudaMemcpyDeviceToDevice, stream);
|
|
1630
|
-
if (r != cudaSuccess) {
|
|
1631
|
-
return r;
|
|
1632
|
-
}
|
|
1633
|
-
}
|
|
1634
|
-
return cudaSuccess;
|
|
1635
|
-
}
|
|
1636
|
-
}
|
|
1637
|
-
|
|
1638
|
-
struct cublas_force_compute_type {
|
|
1639
|
-
bool fp32 = false;
|
|
1640
|
-
bool fp16 = false;
|
|
1641
|
-
};
|
|
1642
|
-
|
|
1643
|
-
static const cublas_force_compute_type & ggml_cuda_cublas_get_force_compute_type() {
|
|
1644
|
-
static const cublas_force_compute_type compute_type = [] {
|
|
1645
|
-
cublas_force_compute_type result;
|
|
1646
|
-
|
|
1647
|
-
const bool ggml_cuda_force_cublas_compute_32f_env = getenv("GGML_CUDA_FORCE_CUBLAS_COMPUTE_32F") != nullptr;
|
|
1648
|
-
const bool ggml_cuda_force_cublas_compute_16f_env = getenv("GGML_CUDA_FORCE_CUBLAS_COMPUTE_16F") != nullptr;
|
|
1649
|
-
|
|
1650
|
-
GGML_ASSERT(ggml_cuda_force_cublas_compute_16f_env == false || ggml_cuda_force_cublas_compute_32f_env == false);
|
|
1651
|
-
|
|
1652
|
-
if (ggml_cuda_force_cublas_compute_32f_env) {
|
|
1653
|
-
GGML_LOG_INFO("Detected GGML_CUDA_FORCE_CUBLAS_COMPUTE_32F\n");
|
|
1654
|
-
result.fp32 = true;
|
|
1655
|
-
} else if (ggml_cuda_force_cublas_compute_16f_env) {
|
|
1656
|
-
GGML_LOG_INFO("Detected GGML_CUDA_FORCE_CUBLAS_COMPUTE_16F\n");
|
|
1657
|
-
result.fp16 = true;
|
|
1658
|
-
}
|
|
1659
|
-
|
|
1660
|
-
return result;
|
|
1661
|
-
}();
|
|
1662
|
-
|
|
1663
|
-
return compute_type;
|
|
1664
|
-
}
|
|
1665
|
-
|
|
1666
|
-
static void ggml_cuda_op_mul_mat_cublas(
|
|
1667
|
-
ggml_backend_cuda_context & ctx,
|
|
1668
|
-
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, const char * src0_dd_i, const float * src1_ddf_i,
|
|
1669
|
-
const char * src1_ddq_i, float * dst_dd_i, const int64_t row_low, const int64_t row_high, const int64_t src1_ncols,
|
|
1670
|
-
const int64_t src1_padded_row_size, cudaStream_t stream) {
|
|
1671
|
-
|
|
1672
|
-
GGML_ASSERT(src0_dd_i != nullptr);
|
|
1673
|
-
GGML_ASSERT(src1_ddf_i != nullptr);
|
|
1674
|
-
GGML_ASSERT(dst_dd_i != nullptr);
|
|
1675
|
-
|
|
1676
|
-
const int64_t ne00 = src0->ne[0];
|
|
1677
|
-
const int64_t ne10 = src1->ne[0];
|
|
1678
|
-
|
|
1679
|
-
const int64_t ne0 = dst->ne[0];
|
|
1680
|
-
|
|
1681
|
-
const int64_t row_diff = row_high - row_low;
|
|
1682
|
-
|
|
1683
|
-
int id = ggml_cuda_get_device();
|
|
1684
|
-
|
|
1685
|
-
// the main device has a larger memory buffer to hold the results from all GPUs
|
|
1686
|
-
// ldc == nrows of the matrix that cuBLAS writes into
|
|
1687
|
-
int64_t ldc = id == ctx.device ? ne0 : row_diff;
|
|
1688
|
-
|
|
1689
|
-
const int cc = ggml_cuda_info().devices[id].cc;
|
|
1690
|
-
|
|
1691
|
-
const bool supports_bf16 = GGML_CUDA_CC_IS_NVIDIA(cc) || GGML_CUDA_CC_IS_AMD(cc) ||
|
|
1692
|
-
(GGML_CUDA_CC_IS_MTHREADS(cc) && cc >= GGML_CUDA_CC_QY2);
|
|
1693
|
-
|
|
1694
|
-
const bool use_fp16 =
|
|
1695
|
-
src0->type != GGML_TYPE_NVFP4 &&
|
|
1696
|
-
(src0->type == GGML_TYPE_F16 || ggml_is_quantized(src0->type)) &&
|
|
1697
|
-
ggml_is_contiguous(src0) &&
|
|
1698
|
-
row_diff == src0->ne[1] &&
|
|
1699
|
-
dst->op_params[0] == GGML_PREC_DEFAULT;
|
|
1700
|
-
|
|
1701
|
-
if (supports_bf16 && src0->type == GGML_TYPE_BF16 && ggml_is_contiguous(src0) && row_diff == src0->ne[1]) {
|
|
1702
|
-
ggml_cuda_pool_alloc<nv_bfloat16> src1_as_bf16(ctx.pool(id));
|
|
1703
|
-
if (src1->type != GGML_TYPE_BF16) {
|
|
1704
|
-
const to_bf16_cuda_t to_bf16_cuda = ggml_get_to_bf16_cuda(src1->type);
|
|
1705
|
-
GGML_ASSERT(to_bf16_cuda != nullptr);
|
|
1706
|
-
size_t ne = src1_ncols*ne10;
|
|
1707
|
-
src1_as_bf16.alloc(ne);
|
|
1708
|
-
to_bf16_cuda(src1_ddf_i, src1_as_bf16.get(), ne, stream);
|
|
1709
|
-
}
|
|
1710
|
-
const nv_bfloat16 * src1_ptr = src1->type == GGML_TYPE_BF16 ? (const nv_bfloat16 *) src1_ddf_i : src1_as_bf16.get();
|
|
1711
|
-
const nv_bfloat16 * src0_ptr = (const nv_bfloat16 *)src0_dd_i;
|
|
1712
|
-
ggml_cuda_pool_alloc<nv_bfloat16> dst_bf16(ctx.pool(id), row_diff*src1_ncols);
|
|
1713
|
-
|
|
1714
|
-
const float alpha_f32 = 1.0f;
|
|
1715
|
-
const float beta_f32 = 0.0f;
|
|
1716
|
-
|
|
1717
|
-
CUBLAS_CHECK(cublasSetStream(ctx.cublas_handle(id), stream));
|
|
1718
|
-
CUBLAS_CHECK(
|
|
1719
|
-
cublasGemmEx(ctx.cublas_handle(id), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
1720
|
-
row_diff, src1_ncols, ne10,
|
|
1721
|
-
&alpha_f32, src0_ptr, CUDA_R_16BF, ne00,
|
|
1722
|
-
src1_ptr, CUDA_R_16BF, ne10,
|
|
1723
|
-
&beta_f32, dst_bf16.get(), CUDA_R_16BF, ldc,
|
|
1724
|
-
CUBLAS_COMPUTE_32F,
|
|
1725
|
-
CUBLAS_GEMM_DEFAULT_TENSOR_OP));
|
|
1726
|
-
|
|
1727
|
-
const to_fp32_cuda_t to_fp32_cuda = ggml_get_to_fp32_cuda(GGML_TYPE_BF16);
|
|
1728
|
-
to_fp32_cuda(dst_bf16.get(), dst_dd_i, row_diff*src1_ncols, stream);
|
|
1729
|
-
} else if (fast_fp16_hardware_available(cc) && use_fp16) {
|
|
1730
|
-
// convert src0 and src1 to fp16, multiply as fp16, convert dst to fp32
|
|
1731
|
-
ggml_cuda_pool_alloc<half> src0_as_f16(ctx.pool(id));
|
|
1732
|
-
if (src0->type != GGML_TYPE_F16) {
|
|
1733
|
-
const to_fp16_cuda_t to_fp16_cuda = ggml_get_to_fp16_cuda(src0->type);
|
|
1734
|
-
GGML_ASSERT(to_fp16_cuda != nullptr);
|
|
1735
|
-
size_t ne = row_diff*ne00;
|
|
1736
|
-
src0_as_f16.alloc(ne);
|
|
1737
|
-
to_fp16_cuda(src0_dd_i, src0_as_f16.get(), ne, stream);
|
|
1738
|
-
}
|
|
1739
|
-
const half * src0_ptr = src0->type == GGML_TYPE_F16 ? (const half *) src0_dd_i : src0_as_f16.get();
|
|
1740
|
-
|
|
1741
|
-
ggml_cuda_pool_alloc<half> src1_as_f16(ctx.pool(id));
|
|
1742
|
-
if (src1->type != GGML_TYPE_F16) {
|
|
1743
|
-
const to_fp16_cuda_t to_fp16_cuda = ggml_get_to_fp16_cuda(src1->type);
|
|
1744
|
-
GGML_ASSERT(to_fp16_cuda != nullptr);
|
|
1745
|
-
size_t ne = src1_ncols*ne10;
|
|
1746
|
-
src1_as_f16.alloc(ne);
|
|
1747
|
-
to_fp16_cuda(src1_ddf_i, src1_as_f16.get(), ne, stream);
|
|
1748
|
-
}
|
|
1749
|
-
const half * src1_ptr = src1->type == GGML_TYPE_F16 ? (const half *) src1_ddf_i : src1_as_f16.get();
|
|
1750
|
-
|
|
1751
|
-
CUBLAS_CHECK(cublasSetStream(ctx.cublas_handle(id), stream));
|
|
1752
|
-
|
|
1753
|
-
const auto & force_compute_type = ggml_cuda_cublas_get_force_compute_type();
|
|
1754
|
-
|
|
1755
|
-
if (!force_compute_type.fp16 && (GGML_CUDA_CC_IS_CDNA(cc)
|
|
1756
|
-
|| GGML_CUDA_CC_IS_RDNA4(cc)
|
|
1757
|
-
|| cc == GGML_CUDA_CC_VOLTA
|
|
1758
|
-
|| force_compute_type.fp32))
|
|
1759
|
-
{
|
|
1760
|
-
const float alpha = 1.0f;
|
|
1761
|
-
const float beta = 0.0f;
|
|
1762
|
-
CUBLAS_CHECK(
|
|
1763
|
-
cublasGemmEx(ctx.cublas_handle(id), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
1764
|
-
row_diff, src1_ncols, ne10,
|
|
1765
|
-
&alpha, src0_ptr, CUDA_R_16F, ne00,
|
|
1766
|
-
src1_ptr, CUDA_R_16F, ne10,
|
|
1767
|
-
&beta, dst_dd_i, CUDA_R_32F, ldc,
|
|
1768
|
-
CUBLAS_COMPUTE_32F,
|
|
1769
|
-
CUBLAS_GEMM_DEFAULT_TENSOR_OP));
|
|
1770
|
-
} else {
|
|
1771
|
-
ggml_cuda_pool_alloc<half> dst_f16(ctx.pool(id), row_diff*src1_ncols);
|
|
1772
|
-
|
|
1773
|
-
const half alpha_f16 = 1.0f;
|
|
1774
|
-
const half beta_f16 = 0.0f;
|
|
1775
|
-
|
|
1776
|
-
CUBLAS_CHECK(
|
|
1777
|
-
cublasGemmEx(ctx.cublas_handle(id), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
1778
|
-
row_diff, src1_ncols, ne10,
|
|
1779
|
-
&alpha_f16, src0_ptr, CUDA_R_16F, ne00,
|
|
1780
|
-
src1_ptr, CUDA_R_16F, ne10,
|
|
1781
|
-
&beta_f16, dst_f16.get(), CUDA_R_16F, ldc,
|
|
1782
|
-
CUBLAS_COMPUTE_16F,
|
|
1783
|
-
CUBLAS_GEMM_DEFAULT_TENSOR_OP));
|
|
1784
|
-
|
|
1785
|
-
const to_fp32_cuda_t to_fp32_cuda = ggml_get_to_fp32_cuda(GGML_TYPE_F16);
|
|
1786
|
-
to_fp32_cuda(dst_f16.get(), dst_dd_i, row_diff*src1_ncols, stream);
|
|
1787
|
-
}
|
|
1788
|
-
} else {
|
|
1789
|
-
ggml_cuda_pool_alloc<float> src0_ddq_as_f32(ctx.pool(id));
|
|
1790
|
-
ggml_cuda_pool_alloc<float> src1_ddq_as_f32(ctx.pool(id));
|
|
1791
|
-
|
|
1792
|
-
if (src0->type != GGML_TYPE_F32) {
|
|
1793
|
-
const to_fp32_cuda_t to_fp32_cuda = ggml_get_to_fp32_cuda(src0->type);
|
|
1794
|
-
GGML_ASSERT(to_fp32_cuda != nullptr);
|
|
1795
|
-
src0_ddq_as_f32.alloc(row_diff*ne00);
|
|
1796
|
-
to_fp32_cuda(src0_dd_i, src0_ddq_as_f32.get(), row_diff*ne00, stream);
|
|
1797
|
-
}
|
|
1798
|
-
if (src1->type != GGML_TYPE_F32) {
|
|
1799
|
-
const to_fp32_cuda_t to_fp32_cuda = ggml_get_to_fp32_cuda(src1->type);
|
|
1800
|
-
GGML_ASSERT(to_fp32_cuda != nullptr);
|
|
1801
|
-
src1_ddq_as_f32.alloc(src1_ncols*ne10);
|
|
1802
|
-
to_fp32_cuda(src1_ddf_i, src1_ddq_as_f32.get(), src1_ncols*ne10, stream);
|
|
1803
|
-
}
|
|
1804
|
-
|
|
1805
|
-
const float * src0_ddf_i = src0->type == GGML_TYPE_F32 ? (const float *) src0_dd_i : src0_ddq_as_f32.get();
|
|
1806
|
-
const float * src1_ddf1_i = src1->type == GGML_TYPE_F32 ? (const float *) src1_ddf_i : src1_ddq_as_f32.get();
|
|
1807
|
-
|
|
1808
|
-
const float alpha = 1.0f;
|
|
1809
|
-
const float beta = 0.0f;
|
|
1810
|
-
|
|
1811
|
-
CUBLAS_CHECK(cublasSetStream(ctx.cublas_handle(id), stream));
|
|
1812
|
-
CUBLAS_CHECK(
|
|
1813
|
-
cublasSgemm(ctx.cublas_handle(id), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
1814
|
-
row_diff, src1_ncols, ne10,
|
|
1815
|
-
&alpha, src0_ddf_i, ne00,
|
|
1816
|
-
src1_ddf1_i, ne10,
|
|
1817
|
-
&beta, dst_dd_i, ldc));
|
|
1818
|
-
}
|
|
1819
|
-
|
|
1820
|
-
GGML_UNUSED_VARS(dst, src1_ddq_i, src1_padded_row_size);
|
|
1821
|
-
}
|
|
1822
|
-
|
|
1823
|
-
static cudaError_t ggml_cuda_Memcpy2DPeerAsync(
|
|
1824
|
-
void * dst, int dstDevice, size_t dpitch, void * src, int srcDevice, size_t spitch, size_t width, size_t height, cudaStream_t stream) {
|
|
1825
|
-
|
|
1826
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
1827
|
-
// cudaMemcpy2DAsync may fail with copies between vmm pools of different devices
|
|
1828
|
-
cudaMemcpy3DPeerParms p = {};
|
|
1829
|
-
p.dstDevice = dstDevice;
|
|
1830
|
-
p.dstPtr = make_cudaPitchedPtr(dst, dpitch, dpitch, height);
|
|
1831
|
-
p.srcDevice = srcDevice;
|
|
1832
|
-
p.srcPtr = make_cudaPitchedPtr(src, spitch, spitch, height);
|
|
1833
|
-
p.extent = make_cudaExtent(width, height, 1);
|
|
1834
|
-
return cudaMemcpy3DPeerAsync(&p, stream);
|
|
1835
|
-
#else
|
|
1836
|
-
// HIP does not support cudaMemcpy3DPeerAsync or vmm pools
|
|
1837
|
-
GGML_UNUSED(dstDevice);
|
|
1838
|
-
GGML_UNUSED(srcDevice);
|
|
1839
|
-
return cudaMemcpy2DAsync(dst, dpitch, src, spitch, width, height, cudaMemcpyDeviceToDevice, stream);
|
|
1840
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
static void ggml_cuda_op_mul_mat(
|
|
1844
|
-
ggml_backend_cuda_context & ctx,
|
|
1845
|
-
const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst, ggml_cuda_op_mul_mat_t op,
|
|
1846
|
-
quantize_cuda_t quantize_src1) {
|
|
1847
|
-
|
|
1848
|
-
const int64_t ne00 = src0->ne[0];
|
|
1849
|
-
const int64_t ne01 = src0->ne[1];
|
|
1850
|
-
const int64_t ne02 = src0->ne[2];
|
|
1851
|
-
const int64_t ne03 = src0->ne[3];
|
|
1852
|
-
|
|
1853
|
-
const int64_t ne10 = src1->ne[0];
|
|
1854
|
-
const int64_t ne11 = src1->ne[1];
|
|
1855
|
-
const int64_t ne12 = src1->ne[2];
|
|
1856
|
-
const int64_t ne13 = src1->ne[3];
|
|
1857
|
-
const int64_t nrows1 = ggml_nrows(src1);
|
|
1858
|
-
|
|
1859
|
-
const int64_t ne0 = dst->ne[0];
|
|
1860
|
-
const int64_t ne1 = dst->ne[1];
|
|
1861
|
-
|
|
1862
|
-
// const int64_t nb10 = src1->nb[0];
|
|
1863
|
-
const int64_t nb11 = src1->nb[1];
|
|
1864
|
-
const int64_t nb12 = src1->nb[2];
|
|
1865
|
-
const int64_t nb13 = src1->nb[3];
|
|
1866
|
-
|
|
1867
|
-
const int64_t nb2 = dst->nb[2];
|
|
1868
|
-
const int64_t nb3 = dst->nb[3];
|
|
1869
|
-
|
|
1870
|
-
ggml_backend_cuda_buffer_context * src1_ctx = (ggml_backend_cuda_buffer_context *) src1->buffer->context;
|
|
1871
|
-
ggml_backend_cuda_buffer_context * dst_ctx = (ggml_backend_cuda_buffer_context *) dst->buffer->context;
|
|
1872
|
-
|
|
1873
|
-
GGML_ASSERT(src1->type == GGML_TYPE_F32 || (src1->ne[2] == 1 && src1->ne[3] == 1));
|
|
1874
|
-
|
|
1875
|
-
GGML_ASSERT(ne12 % ne02 == 0);
|
|
1876
|
-
GGML_ASSERT(ne13 % ne03 == 0);
|
|
1877
|
-
|
|
1878
|
-
const int64_t i02_divisor = ne12 / ne02;
|
|
1879
|
-
const int64_t i03_divisor = ne13 / ne03;
|
|
1880
|
-
|
|
1881
|
-
const size_t src0_ts = ggml_type_size(src0->type);
|
|
1882
|
-
const size_t src0_bs = ggml_blck_size(src0->type);
|
|
1883
|
-
const size_t q8_1_ts = sizeof(block_q8_1);
|
|
1884
|
-
const size_t q8_1_bs = QK8_1;
|
|
1885
|
-
|
|
1886
|
-
const bool src0_is_contiguous = ggml_is_contiguous(src0);
|
|
1887
|
-
const bool src1_is_contiguous = ggml_is_contiguous(src1);
|
|
1888
|
-
|
|
1889
|
-
const int64_t src1_padded_col_size = GGML_PAD(ne10, MATRIX_ROW_PADDING);
|
|
1890
|
-
|
|
1891
|
-
const bool split = ggml_backend_buft_is_cuda_split(src0->buffer->buft);
|
|
1892
|
-
GGML_ASSERT(!(split && ne02 > 1));
|
|
1893
|
-
GGML_ASSERT(!(split && ne03 > 1));
|
|
1894
|
-
GGML_ASSERT(!(split && ne02 < ne12));
|
|
1895
|
-
GGML_ASSERT(!(split && ne03 < ne13));
|
|
1896
|
-
|
|
1897
|
-
ggml_tensor_extra_gpu * src0_extra = split ? (ggml_tensor_extra_gpu *) src0->extra : nullptr;
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
std::array<float, GGML_CUDA_MAX_DEVICES> tensor_split;
|
|
1901
|
-
if (split) {
|
|
1902
|
-
ggml_backend_cuda_split_buffer_type_context * buft_ctx = (ggml_backend_cuda_split_buffer_type_context *) src0->buffer->buft->context;
|
|
1903
|
-
tensor_split = buft_ctx->tensor_split;
|
|
1904
|
-
}
|
|
1905
|
-
|
|
1906
|
-
struct dev_data {
|
|
1907
|
-
int cc;
|
|
1908
|
-
|
|
1909
|
-
ggml_cuda_pool_alloc<char> src0_dd_alloc;
|
|
1910
|
-
ggml_cuda_pool_alloc<float> src1_ddf_alloc;
|
|
1911
|
-
ggml_cuda_pool_alloc<char> src1_ddq_alloc;
|
|
1912
|
-
ggml_cuda_pool_alloc<float> dst_dd_alloc;
|
|
1913
|
-
|
|
1914
|
-
char * src0_dd = nullptr;
|
|
1915
|
-
float * src1_ddf = nullptr; // float
|
|
1916
|
-
char * src1_ddq = nullptr; // q8_1
|
|
1917
|
-
float * dst_dd = nullptr;
|
|
1918
|
-
|
|
1919
|
-
int64_t row_low;
|
|
1920
|
-
int64_t row_high;
|
|
1921
|
-
};
|
|
1922
|
-
|
|
1923
|
-
dev_data dev[GGML_CUDA_MAX_DEVICES];
|
|
1924
|
-
|
|
1925
|
-
int used_devices = 0;
|
|
1926
|
-
|
|
1927
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1928
|
-
dev[id].cc = ggml_cuda_info().devices[id].cc;
|
|
1929
|
-
|
|
1930
|
-
// by default, use all rows
|
|
1931
|
-
dev[id].row_low = 0;
|
|
1932
|
-
dev[id].row_high = ne01;
|
|
1933
|
-
|
|
1934
|
-
// for multi GPU, get the row boundaries from tensor split
|
|
1935
|
-
// and round to mul_mat_q tile sizes
|
|
1936
|
-
if (split) {
|
|
1937
|
-
const int64_t rounding = get_row_rounding(tensor_split);
|
|
1938
|
-
|
|
1939
|
-
if (id != 0) {
|
|
1940
|
-
dev[id].row_low = ne01*tensor_split[id];
|
|
1941
|
-
if (dev[id].row_low < ne01) {
|
|
1942
|
-
dev[id].row_low -= dev[id].row_low % rounding;
|
|
1943
|
-
}
|
|
1944
|
-
}
|
|
1945
|
-
|
|
1946
|
-
if (id != ggml_backend_cuda_get_device_count() - 1) {
|
|
1947
|
-
dev[id].row_high = ne01*tensor_split[id + 1];
|
|
1948
|
-
if (dev[id].row_high < ne01) {
|
|
1949
|
-
dev[id].row_high -= dev[id].row_high % rounding;
|
|
1950
|
-
}
|
|
1951
|
-
}
|
|
1952
|
-
}
|
|
1953
|
-
}
|
|
1954
|
-
|
|
1955
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
1956
|
-
if ((!split && id != ctx.device) || dev[id].row_low == dev[id].row_high) {
|
|
1957
|
-
continue;
|
|
1958
|
-
}
|
|
1959
|
-
|
|
1960
|
-
used_devices++;
|
|
1961
|
-
|
|
1962
|
-
const bool src1_on_device = id == src1_ctx->device;
|
|
1963
|
-
const bool dst_on_device = id == dst_ctx->device;
|
|
1964
|
-
|
|
1965
|
-
ggml_cuda_set_device(id);
|
|
1966
|
-
cudaStream_t stream = ctx.stream(id, 0);
|
|
1967
|
-
|
|
1968
|
-
if (src0_is_contiguous) {
|
|
1969
|
-
dev[id].src0_dd = split ? (char *) src0_extra->data_device[id] : (char *) src0->data;
|
|
1970
|
-
} else {
|
|
1971
|
-
// If src0 is not contiguous it will be copied to a temporary buffer.
|
|
1972
|
-
// This buffer needs to be cleared entirely because multiple regions will function as padding.
|
|
1973
|
-
const size_t nbytes_data = ggml_nbytes(src0);
|
|
1974
|
-
const size_t nbytes_padding = ggml_row_size(src0->type, MATRIX_ROW_PADDING - ne00 % MATRIX_ROW_PADDING);
|
|
1975
|
-
dev[id].src0_dd = dev[id].src0_dd_alloc.alloc(ctx.pool(id), nbytes_data + nbytes_padding);
|
|
1976
|
-
CUDA_CHECK(cudaMemsetAsync(dev[id].src0_dd, 0, nbytes_data + nbytes_padding, stream));
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
|
-
// If src0 is on a temporary compute buffer (partial offloading) there may be some padding that needs to be cleared:
|
|
1980
|
-
if (ne00 % MATRIX_ROW_PADDING != 0 && ggml_is_quantized(src0->type) && ggml_backend_buffer_get_usage(src0->buffer) == GGML_BACKEND_BUFFER_USAGE_COMPUTE && src0->view_src == nullptr) {
|
|
1981
|
-
GGML_ASSERT(ggml_is_contiguously_allocated(src0));
|
|
1982
|
-
GGML_ASSERT(!src0->view_src);
|
|
1983
|
-
const size_t nbytes_data = ggml_row_size(src0->type, (dev[id].row_high - dev[id].row_low)*ne00);
|
|
1984
|
-
const size_t nbytes_padding = ggml_row_size(src0->type, MATRIX_ROW_PADDING - ne00 % MATRIX_ROW_PADDING);
|
|
1985
|
-
CUDA_CHECK(cudaMemsetAsync(dev[id].src0_dd + nbytes_data, 0, nbytes_padding, stream));
|
|
1986
|
-
}
|
|
1987
|
-
|
|
1988
|
-
if (src1_on_device && src1_is_contiguous) {
|
|
1989
|
-
dev[id].src1_ddf = (float *) src1->data;
|
|
1990
|
-
} else {
|
|
1991
|
-
dev[id].src1_ddf = dev[id].src1_ddf_alloc.alloc(ctx.pool(id), ggml_nelements(src1));
|
|
1992
|
-
}
|
|
1993
|
-
|
|
1994
|
-
if (quantize_src1) {
|
|
1995
|
-
size_t src_1_ddq_size = nrows1*src1_padded_col_size*q8_1_ts/q8_1_bs;
|
|
1996
|
-
if (quantize_src1 == quantize_mmq_q8_1_cuda) {
|
|
1997
|
-
src_1_ddq_size += get_mmq_x_max_host(dev[id].cc)*sizeof(block_q8_1_mmq);
|
|
1998
|
-
}
|
|
1999
|
-
dev[id].src1_ddq = dev[id].src1_ddq_alloc.alloc(ctx.pool(id), src_1_ddq_size);
|
|
2000
|
-
|
|
2001
|
-
if (src1_on_device && src1_is_contiguous) {
|
|
2002
|
-
quantize_src1(
|
|
2003
|
-
dev[id].src1_ddf, nullptr, dev[id].src1_ddq, src0->type, ne10,
|
|
2004
|
-
nb11/sizeof(float), nb12/sizeof(float), nb13/sizeof(float),
|
|
2005
|
-
src1_padded_col_size, ne11, ne12, ne13, stream);
|
|
2006
|
-
CUDA_CHECK(cudaGetLastError());
|
|
2007
|
-
}
|
|
2008
|
-
}
|
|
2009
|
-
|
|
2010
|
-
if (dst_on_device) {
|
|
2011
|
-
dev[id].dst_dd = (float *) dst->data;
|
|
2012
|
-
} else {
|
|
2013
|
-
const size_t size_dst_ddf = split ? (dev[id].row_high - dev[id].row_low)*ne1 : ggml_nelements(dst);
|
|
2014
|
-
dev[id].dst_dd = dev[id].dst_dd_alloc.alloc(ctx.pool(id), size_dst_ddf);
|
|
2015
|
-
}
|
|
2016
|
-
}
|
|
2017
|
-
|
|
2018
|
-
// if multiple devices are used they need to wait for the main device
|
|
2019
|
-
// here an event is recorded that signals that the main device has finished calculating the input data
|
|
2020
|
-
if (split && used_devices > 1) {
|
|
2021
|
-
ggml_cuda_set_device(ctx.device);
|
|
2022
|
-
CUDA_CHECK(cudaEventRecord(src0_extra->events[ctx.device][0], ctx.stream()));
|
|
2023
|
-
}
|
|
2024
|
-
|
|
2025
|
-
const int64_t src1_col_stride = split && used_devices > 1 ? MUL_MAT_SRC1_COL_STRIDE : ne11;
|
|
2026
|
-
for (int64_t src1_col_0 = 0; src1_col_0 < ne11; src1_col_0 += src1_col_stride) {
|
|
2027
|
-
const int64_t is = split ? (src1_col_0/src1_col_stride) % GGML_CUDA_MAX_STREAMS : 0;
|
|
2028
|
-
const int64_t src1_ncols = src1_col_0 + src1_col_stride > ne11 ? ne11 - src1_col_0 : src1_col_stride;
|
|
2029
|
-
|
|
2030
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
2031
|
-
if ((!split && id != ctx.device) || dev[id].row_low == dev[id].row_high) {
|
|
2032
|
-
continue;
|
|
2033
|
-
}
|
|
2034
|
-
|
|
2035
|
-
const bool src1_on_device = id == src1_ctx->device;
|
|
2036
|
-
const bool dst_on_device = id == dst_ctx->device;
|
|
2037
|
-
const int64_t row_diff = dev[id].row_high - dev[id].row_low;
|
|
2038
|
-
|
|
2039
|
-
ggml_cuda_set_device(id);
|
|
2040
|
-
cudaStream_t stream = ctx.stream(id, is);
|
|
2041
|
-
|
|
2042
|
-
// wait for main GPU data if necessary
|
|
2043
|
-
if (split && (id != ctx.device || is != 0)) {
|
|
2044
|
-
CUDA_CHECK(cudaStreamWaitEvent(stream, src0_extra->events[ctx.device][0], 0));
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
for (int64_t i0 = 0; i0 < ne13*ne12; ++i0) {
|
|
2048
|
-
const int64_t i03 = i0 / ne12;
|
|
2049
|
-
const int64_t i02 = i0 % ne12;
|
|
2050
|
-
|
|
2051
|
-
size_t src1_ddq_i_offset = i0*ne11 * src1_padded_col_size*q8_1_ts/q8_1_bs;
|
|
2052
|
-
if (quantize_src1 == quantize_mmq_q8_1_cuda) {
|
|
2053
|
-
src1_ddq_i_offset += src1_col_0 * sizeof(block_q8_1_mmq);
|
|
2054
|
-
} else {
|
|
2055
|
-
src1_ddq_i_offset += src1_col_0 * src1_padded_col_size*q8_1_ts/q8_1_bs;
|
|
2056
|
-
}
|
|
2057
|
-
|
|
2058
|
-
// for split tensors the data begins at i0 == i0_offset_low
|
|
2059
|
-
const size_t nbytes_src0_matrix = ne01*ne00*src0_ts / src0_bs;
|
|
2060
|
-
char * src0_dd_i = dev[id].src0_dd + ((i03/i03_divisor)*ne02 + (i02/i02_divisor)) * nbytes_src0_matrix;
|
|
2061
|
-
float * src1_ddf_i = dev[id].src1_ddf + (i0*ne11 + src1_col_0) * ne10;
|
|
2062
|
-
char * src1_ddq_i = dev[id].src1_ddq + src1_ddq_i_offset;
|
|
2063
|
-
float * dst_dd_i = dev[id].dst_dd + (i0*ne1 + src1_col_0) * (dst_on_device ? ne0 : row_diff);
|
|
2064
|
-
|
|
2065
|
-
// the main device memory buffer can be on VRAM scratch, with space for all partial results
|
|
2066
|
-
// in that case an offset on dst_ddf_i is needed
|
|
2067
|
-
if (id == ctx.device) {
|
|
2068
|
-
dst_dd_i += dev[id].row_low; // offset is 0 if no tensor split
|
|
2069
|
-
}
|
|
2070
|
-
|
|
2071
|
-
// copy src0, src1 to device if necessary
|
|
2072
|
-
if (src1_is_contiguous) {
|
|
2073
|
-
if (id != ctx.device) {
|
|
2074
|
-
if (quantize_src1) {
|
|
2075
|
-
char * src1_ddq_i_source = dev[ctx.device].src1_ddq + src1_ddq_i_offset;
|
|
2076
|
-
if (quantize_src1 == quantize_mmq_q8_1_cuda) {
|
|
2077
|
-
const size_t pitch = ne11*sizeof(block_q8_1_mmq);
|
|
2078
|
-
const size_t width = src1_ncols*sizeof(block_q8_1_mmq);
|
|
2079
|
-
const size_t height = src1_padded_col_size/(4*QK8_1);
|
|
2080
|
-
CUDA_CHECK(ggml_cuda_Memcpy2DPeerAsync(src1_ddq_i, id, pitch, src1_ddq_i_source, ctx.device, pitch, width, height, stream));
|
|
2081
|
-
} else {
|
|
2082
|
-
CUDA_CHECK(cudaMemcpyPeerAsync(
|
|
2083
|
-
src1_ddq_i, id, src1_ddq_i_source, ctx.device, src1_ncols*src1_padded_col_size*q8_1_ts/q8_1_bs, stream));
|
|
2084
|
-
}
|
|
2085
|
-
} else {
|
|
2086
|
-
float * src1_ddf_i_source = (float *) src1->data;
|
|
2087
|
-
src1_ddf_i_source += (i0*ne11 + src1_col_0) * ne10;
|
|
2088
|
-
CUDA_CHECK(cudaMemcpyPeerAsync(src1_ddf_i, id, src1_ddf_i_source, ctx.device,
|
|
2089
|
-
src1_ncols*ne10*sizeof(float), stream));
|
|
2090
|
-
}
|
|
2091
|
-
}
|
|
2092
|
-
} else if (src1_on_device && !src1_is_contiguous) {
|
|
2093
|
-
CUDA_CHECK(ggml_cuda_cpy_tensor_2d(
|
|
2094
|
-
src1_ddf_i, src1, i03, i02, src1_col_0, src1_col_0+src1_ncols, stream));
|
|
2095
|
-
} else {
|
|
2096
|
-
GGML_ABORT("fatal error");
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
if (quantize_src1 && !src1_is_contiguous) {
|
|
2100
|
-
quantize_src1(
|
|
2101
|
-
src1_ddf_i, nullptr, src1_ddq_i, src0->type, ne10, ne10, ne11*ne10, ne12*ne11*ne10,
|
|
2102
|
-
src1_padded_col_size, src1_ncols, 1, 1, stream);
|
|
2103
|
-
CUDA_CHECK(cudaGetLastError());
|
|
2104
|
-
}
|
|
2105
|
-
|
|
2106
|
-
if (src1_col_0 == 0 && !src0_is_contiguous && i03 % i03_divisor == 0 && i02 % i02_divisor == 0) {
|
|
2107
|
-
CUDA_CHECK(ggml_cuda_cpy_tensor_2d(
|
|
2108
|
-
src0_dd_i, src0, i03/i03_divisor, i02/i02_divisor, dev[id].row_low, dev[id].row_high, stream));
|
|
2109
|
-
}
|
|
2110
|
-
|
|
2111
|
-
// do the computation
|
|
2112
|
-
op(ctx, src0, src1, dst, src0_dd_i, src1_ddf_i, src1_ddq_i, dst_dd_i,
|
|
2113
|
-
dev[id].row_low, dev[id].row_high, src1_ncols, src1_padded_col_size, stream);
|
|
2114
|
-
CUDA_CHECK(cudaGetLastError());
|
|
2115
|
-
|
|
2116
|
-
// copy dst to host or other device if necessary
|
|
2117
|
-
if (!dst_on_device) {
|
|
2118
|
-
void * dst_off_device = dst->data;
|
|
2119
|
-
if (split) {
|
|
2120
|
-
// src0 = weight matrix is saved as a transposed matrix for better memory layout.
|
|
2121
|
-
// dst is NOT transposed.
|
|
2122
|
-
// The outputs of matrix matrix multiplications can therefore NOT simply be concatenated for >1 GPU.
|
|
2123
|
-
// Instead they need to be copied to the correct slice in ne0 = dst row index.
|
|
2124
|
-
// If dst is a vector with ne0 == 1 then you don't have to do this but it still produces correct results.
|
|
2125
|
-
float * dhf_dst_i = (float *) ((char *) dst_off_device + i02*nb2 + i03*nb3);
|
|
2126
|
-
GGML_ASSERT(dst->nb[1] == ne0*sizeof(float));
|
|
2127
|
-
dhf_dst_i += src1_col_0*ne0 + dev[id].row_low;
|
|
2128
|
-
CUDA_CHECK(ggml_cuda_Memcpy2DPeerAsync(
|
|
2129
|
-
dhf_dst_i, ctx.device, ne0*sizeof(float), dst_dd_i, id, row_diff*sizeof(float), row_diff*sizeof(float), src1_ncols, stream));
|
|
2130
|
-
} else {
|
|
2131
|
-
float * dhf_dst_i = (float *) ((char *) dst_off_device + i02*nb2 + i03*nb3);
|
|
2132
|
-
GGML_ASSERT(dst->nb[1] == ne0*sizeof(float));
|
|
2133
|
-
dhf_dst_i += src1_col_0*ne0;
|
|
2134
|
-
CUDA_CHECK(cudaMemcpyAsync(dhf_dst_i, dst_dd_i, src1_ncols*ne0*sizeof(float), cudaMemcpyDeviceToDevice, stream));
|
|
2135
|
-
}
|
|
2136
|
-
}
|
|
2137
|
-
|
|
2138
|
-
// add event for the main device to wait on until other device is done
|
|
2139
|
-
if (split && (id != ctx.device || is != 0)) {
|
|
2140
|
-
CUDA_CHECK(cudaEventRecord(src0_extra->events[id][is], stream));
|
|
2141
|
-
}
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2144
|
-
}
|
|
2145
|
-
|
|
2146
|
-
// main device waits for all other devices to be finished
|
|
2147
|
-
if (split && ggml_backend_cuda_get_device_count() > 1) {
|
|
2148
|
-
int64_t is_max = (ne11 + MUL_MAT_SRC1_COL_STRIDE - 1) / MUL_MAT_SRC1_COL_STRIDE;
|
|
2149
|
-
is_max = is_max <= GGML_CUDA_MAX_STREAMS ? is_max : GGML_CUDA_MAX_STREAMS;
|
|
2150
|
-
|
|
2151
|
-
ggml_cuda_set_device(ctx.device);
|
|
2152
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
2153
|
-
if (dev[id].row_low == dev[id].row_high) {
|
|
2154
|
-
continue;
|
|
2155
|
-
}
|
|
2156
|
-
for (int64_t is = 0; is < is_max; ++is) {
|
|
2157
|
-
CUDA_CHECK(cudaStreamWaitEvent(ctx.stream(), src0_extra->events[id][is], 0));
|
|
2158
|
-
}
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
|
-
|
|
2163
1254
|
static __global__ void k_compute_batched_ptrs(
|
|
2164
1255
|
const void * src0_as_f16, const void * src1_as_f16, char * dst,
|
|
2165
1256
|
const void ** ptrs_src, void ** ptrs_dst,
|
|
@@ -2198,7 +1289,8 @@ struct batched_mul_mat_traits<GGML_TYPE_F32> {
|
|
|
2198
1289
|
static inline const float beta = 0.0f;
|
|
2199
1290
|
static inline const void* get_alpha() { static const float val = alpha; return &val; }
|
|
2200
1291
|
static inline const void* get_beta() { static const float val = beta; return &val; }
|
|
2201
|
-
static inline auto
|
|
1292
|
+
static inline auto convert(ggml_type src_type) { return ggml_get_to_fp32_cuda(src_type); }
|
|
1293
|
+
static inline auto convert_nc(ggml_type src_type) { return ggml_get_to_fp32_nc_cuda(src_type); }
|
|
2202
1294
|
};
|
|
2203
1295
|
|
|
2204
1296
|
template<>
|
|
@@ -2211,7 +1303,8 @@ struct batched_mul_mat_traits<GGML_TYPE_BF16> {
|
|
|
2211
1303
|
static inline const float beta = 0.0f;
|
|
2212
1304
|
static inline const void* get_alpha() { static const float val = alpha; return &val; }
|
|
2213
1305
|
static inline const void* get_beta() { static const float val = beta; return &val; }
|
|
2214
|
-
static inline auto
|
|
1306
|
+
static inline auto convert(ggml_type src_type) { return ggml_get_to_bf16_cuda(src_type); }
|
|
1307
|
+
static inline auto convert_nc(ggml_type src_type) { return ggml_get_to_bf16_nc_cuda(src_type); }
|
|
2215
1308
|
};
|
|
2216
1309
|
|
|
2217
1310
|
template<>
|
|
@@ -2224,18 +1317,15 @@ struct batched_mul_mat_traits<GGML_TYPE_F16> {
|
|
|
2224
1317
|
static inline const half beta = 0.0;
|
|
2225
1318
|
static inline const void* get_alpha() { static const half val = alpha; return &val; }
|
|
2226
1319
|
static inline const void* get_beta() { static const half val = beta; return &val; }
|
|
2227
|
-
static inline auto
|
|
1320
|
+
static inline auto convert(ggml_type src_type) { return ggml_get_to_fp16_cuda(src_type); }
|
|
1321
|
+
static inline auto convert_nc(ggml_type src_type) { return ggml_get_to_fp16_nc_cuda(src_type); }
|
|
2228
1322
|
};
|
|
2229
1323
|
|
|
2230
|
-
template<ggml_type
|
|
2231
|
-
static void
|
|
2232
|
-
using traits = batched_mul_mat_traits<
|
|
1324
|
+
template<ggml_type compute_type>
|
|
1325
|
+
static void ggml_cuda_mul_mat_cublas_impl(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
|
|
1326
|
+
using traits = batched_mul_mat_traits<compute_type>;
|
|
2233
1327
|
using cuda_t = typename traits::cuda_type;
|
|
2234
1328
|
|
|
2235
|
-
GGML_ASSERT(!ggml_is_transposed(src0));
|
|
2236
|
-
GGML_ASSERT(!ggml_is_transposed(src1));
|
|
2237
|
-
GGML_ASSERT(!ggml_backend_buft_is_cuda_split(src0->buffer->buft));
|
|
2238
|
-
GGML_ASSERT(src0->type == src0_type);
|
|
2239
1329
|
GGML_ASSERT(ggml_is_contiguous(dst));
|
|
2240
1330
|
|
|
2241
1331
|
// Byte offsets and tensor dimensions are currently used in an inconsistent way for dst.
|
|
@@ -2247,12 +1337,19 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2247
1337
|
cudaStream_t main_stream = ctx.stream();
|
|
2248
1338
|
CUBLAS_CHECK(cublasSetStream(ctx.cublas_handle(), main_stream));
|
|
2249
1339
|
|
|
1340
|
+
const size_t src0_ts = ggml_type_size(src0->type);
|
|
1341
|
+
GGML_ASSERT(nb00 == src0_ts);
|
|
1342
|
+
int64_t s01 = nb01 / src0_ts;
|
|
1343
|
+
int64_t s02 = nb02 / src0_ts;
|
|
1344
|
+
int64_t s03 = nb03 / src0_ts;
|
|
1345
|
+
|
|
1346
|
+
const size_t src1_ts = ggml_type_size(src1->type);
|
|
1347
|
+
GGML_ASSERT(nb10 == src1_ts);
|
|
1348
|
+
int64_t s11 = nb11 / src1_ts;
|
|
1349
|
+
int64_t s12 = nb12 / src1_ts;
|
|
1350
|
+
int64_t s13 = nb13 / src1_ts;
|
|
1351
|
+
|
|
2250
1352
|
float * dst_ddf = (float *) dst->data;
|
|
2251
|
-
const size_t ts_src1 = ggml_type_size(src1->type);
|
|
2252
|
-
GGML_ASSERT(nb10 == ts_src1);
|
|
2253
|
-
int64_t s11 = nb11 / ts_src1;
|
|
2254
|
-
int64_t s12 = nb12 / ts_src1;
|
|
2255
|
-
int64_t s13 = nb13 / ts_src1;
|
|
2256
1353
|
|
|
2257
1354
|
const cuda_t * src0_ptr = nullptr;
|
|
2258
1355
|
const cuda_t * src1_ptr = nullptr;
|
|
@@ -2263,31 +1360,58 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2263
1360
|
bool is_src0_cont_2 = ggml_is_contiguous_2(src0);
|
|
2264
1361
|
bool is_src1_cont_2 = ggml_is_contiguous_2(src1);
|
|
2265
1362
|
|
|
2266
|
-
|
|
2267
|
-
|
|
1363
|
+
if (src0->type == compute_type) {
|
|
1364
|
+
src0_ptr = (const cuda_t *) src0->data;
|
|
1365
|
+
} else {
|
|
1366
|
+
src0_alloc.alloc(ggml_nelements(src0));
|
|
1367
|
+
|
|
1368
|
+
if (ggml_is_contiguously_allocated(src0)) {
|
|
1369
|
+
const auto convert_func = traits::convert(src0->type);
|
|
1370
|
+
GGML_ASSERT(convert_func != nullptr);
|
|
1371
|
+
convert_func(src0->data, src0_alloc.get(), ggml_nelements(src0), main_stream);
|
|
1372
|
+
const size_t src0_bs = ggml_blck_size(src0->type);
|
|
1373
|
+
s01 *= src0_bs;
|
|
1374
|
+
s02 *= src0_bs;
|
|
1375
|
+
s03 *= src0_bs;
|
|
1376
|
+
} else {
|
|
1377
|
+
const auto convert_func = traits::convert_nc(src0->type);
|
|
1378
|
+
GGML_ASSERT(convert_func != nullptr);
|
|
1379
|
+
convert_func(src0->data, src0_alloc.get(), ne00, ne01, ne02, ne03, s01, s02, s03, main_stream);
|
|
1380
|
+
s01 = ne00;
|
|
1381
|
+
s02 = ne01*s01;
|
|
1382
|
+
s03 = ne02*s02;
|
|
1383
|
+
is_src0_cont_2 = true;
|
|
1384
|
+
}
|
|
1385
|
+
src0_ptr = src0_alloc.get();
|
|
1386
|
+
}
|
|
2268
1387
|
|
|
2269
|
-
|
|
2270
|
-
if (src1->type == src0_type) {
|
|
1388
|
+
if (src1->type == compute_type) {
|
|
2271
1389
|
src1_ptr = (const cuda_t *) src1->data;
|
|
2272
1390
|
} else {
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
1391
|
+
src1_alloc.alloc(ggml_nelements(src1));
|
|
1392
|
+
|
|
1393
|
+
if (ggml_is_contiguously_allocated(src1)) {
|
|
1394
|
+
const auto convert_func = traits::convert(src1->type);
|
|
1395
|
+
GGML_ASSERT(convert_func != nullptr);
|
|
1396
|
+
convert_func(src1->data, src1_alloc.get(), ggml_nelements(src1), main_stream);
|
|
1397
|
+
const size_t src1_bs = ggml_blck_size(src1->type);
|
|
1398
|
+
s11 *= src1_bs;
|
|
1399
|
+
s12 *= src1_bs;
|
|
1400
|
+
s13 *= src1_bs;
|
|
1401
|
+
} else {
|
|
1402
|
+
const auto convert_func = traits::convert_nc(src1->type);
|
|
1403
|
+
GGML_ASSERT(convert_func != nullptr);
|
|
1404
|
+
convert_func(src1->data, src1_alloc.get(), ne10, ne11, ne12, ne13, s11, s12, s13, main_stream);
|
|
1405
|
+
s11 = ne10;
|
|
1406
|
+
s12 = ne11*s11;
|
|
1407
|
+
s13 = ne12*s12;
|
|
1408
|
+
is_src1_cont_2 = true;
|
|
1409
|
+
}
|
|
2280
1410
|
src1_ptr = src1_alloc.get();
|
|
2281
|
-
s11 = ne10;
|
|
2282
|
-
s12 = ne11*s11;
|
|
2283
|
-
s13 = ne12*s12;
|
|
2284
|
-
|
|
2285
|
-
is_src1_cont_2 = true;
|
|
2286
1411
|
}
|
|
2287
1412
|
|
|
2288
|
-
// Setup destination buffer
|
|
2289
1413
|
ggml_cuda_pool_alloc<cuda_t> dst_temp(ctx.pool());
|
|
2290
|
-
char *
|
|
1414
|
+
char * dst_ptr;
|
|
2291
1415
|
size_t nbd2 = dst->nb[2];
|
|
2292
1416
|
size_t nbd3 = dst->nb[3];
|
|
2293
1417
|
|
|
@@ -2298,35 +1422,28 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2298
1422
|
const void * alpha = traits::get_alpha();
|
|
2299
1423
|
const void * beta = traits::get_beta();
|
|
2300
1424
|
|
|
2301
|
-
const
|
|
2302
|
-
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
// so checking necessity of forced fp32 only for fp16 src0_type
|
|
2309
|
-
static_assert(is_src0_type_f16 || traits::compute_type == CUBLAS_COMPUTE_32F);
|
|
2310
|
-
|
|
2311
|
-
const bool need_compute_32f = is_src0_type_f16 && !force_compute_type.fp16 && (GGML_CUDA_CC_IS_CDNA(cc)
|
|
2312
|
-
|| GGML_CUDA_CC_IS_RDNA4(cc)
|
|
2313
|
-
|| cc == GGML_CUDA_CC_VOLTA
|
|
2314
|
-
|| force_compute_type.fp32);
|
|
1425
|
+
const int cc = ggml_cuda_info().devices[ctx.device].cc;
|
|
1426
|
+
bool prefer_f32_output = false;
|
|
1427
|
+
if (compute_type == GGML_TYPE_F16) {
|
|
1428
|
+
prefer_f32_output = cc == GGML_CUDA_CC_VOLTA || GGML_CUDA_CC_IS_RDNA4(cc) || GGML_CUDA_CC_IS_CDNA(cc);
|
|
1429
|
+
} else if (compute_type == GGML_TYPE_BF16) {
|
|
1430
|
+
prefer_f32_output = !GGML_CUDA_CC_IS_RDNA3(cc) && !GGML_CUDA_CC_IS_CDNA(cc);
|
|
1431
|
+
}
|
|
2315
1432
|
|
|
2316
|
-
if (
|
|
2317
|
-
|
|
2318
|
-
dst_t = (char *) dst_ddf; // Direct F32 output
|
|
2319
|
-
} else {
|
|
2320
|
-
dst_t = (char *) dst_temp.alloc(ne_dst);
|
|
2321
|
-
nbd2 /= sizeof(float) / sizeof(cuda_t);
|
|
2322
|
-
nbd3 /= sizeof(float) / sizeof(cuda_t);
|
|
2323
|
-
}
|
|
2324
|
-
} else {
|
|
2325
|
-
dst_t = (char *) dst_ddf;
|
|
1433
|
+
if (prefer_f32_output) {
|
|
1434
|
+
dst_ptr = (char *) dst_ddf;
|
|
2326
1435
|
cu_compute_type = batched_mul_mat_traits<GGML_TYPE_F32>::compute_type;
|
|
2327
1436
|
cu_data_type = batched_mul_mat_traits<GGML_TYPE_F32>::data_type;
|
|
2328
1437
|
alpha = batched_mul_mat_traits<GGML_TYPE_F32>::get_alpha();
|
|
2329
1438
|
beta = batched_mul_mat_traits<GGML_TYPE_F32>::get_beta();
|
|
1439
|
+
} else {
|
|
1440
|
+
if constexpr (compute_type == GGML_TYPE_F32) {
|
|
1441
|
+
dst_ptr = (char *) dst_ddf; // Direct F32 output
|
|
1442
|
+
} else {
|
|
1443
|
+
dst_ptr = (char *) dst_temp.alloc(ne_dst);
|
|
1444
|
+
nbd2 /= sizeof(float) / sizeof(cuda_t);
|
|
1445
|
+
nbd3 /= sizeof(float) / sizeof(cuda_t);
|
|
1446
|
+
}
|
|
2330
1447
|
}
|
|
2331
1448
|
|
|
2332
1449
|
GGML_ASSERT(ne12 % ne02 == 0);
|
|
@@ -2336,19 +1453,38 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2336
1453
|
const int64_t r2 = ne12/ne02;
|
|
2337
1454
|
const int64_t r3 = ne13/ne03;
|
|
2338
1455
|
|
|
2339
|
-
|
|
1456
|
+
// Theoretically cublasGemmStridedBatchedEx would always work, even for a single matrix.
|
|
1457
|
+
// However, for some old NVIDIA and AMD GPUs the strided/Ex GEMM is much slower,
|
|
1458
|
+
// probably because the internal kernel selection logic is suboptimal.
|
|
1459
|
+
if (compute_type == GGML_TYPE_F32 && ne12 == 1 && ne13 == 1) {
|
|
1460
|
+
CUBLAS_CHECK(
|
|
1461
|
+
cublasSgemm(ctx.cublas_handle(), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
1462
|
+
ne01, ne11, ne10,
|
|
1463
|
+
(const float *) alpha, (const float *) src0_ptr, s01,
|
|
1464
|
+
(const float *) src1_ptr, s11,
|
|
1465
|
+
(const float *) beta, (float *) dst_ptr, ne0));
|
|
1466
|
+
} else if (ne12 == 1 && ne13 == 1) {
|
|
1467
|
+
CUBLAS_CHECK(
|
|
1468
|
+
cublasGemmEx(ctx.cublas_handle(), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
1469
|
+
ne01, ne11, ne10,
|
|
1470
|
+
alpha, src0_ptr, cu_data_type_a, s01,
|
|
1471
|
+
src1_ptr, cu_data_type_b, s11,
|
|
1472
|
+
beta, dst_ptr, cu_data_type, ne0,
|
|
1473
|
+
cu_compute_type,
|
|
1474
|
+
CUBLAS_GEMM_DEFAULT_TENSOR_OP));
|
|
1475
|
+
} else if (r2 == 1 && r3 == 1 && is_src0_cont_2 && is_src1_cont_2) {
|
|
2340
1476
|
// with a [0, 2, 1, 3] perm. and ne02==1 the matrix strides need to be determined from dim 3:
|
|
2341
|
-
const int64_t sma = ne02 == 1 ?
|
|
2342
|
-
const int64_t smb = ne12 == 1 ? s13
|
|
1477
|
+
const int64_t sma = ne02 == 1 ? s03 : s02;
|
|
1478
|
+
const int64_t smb = ne12 == 1 ? s13 : s12;
|
|
2343
1479
|
|
|
2344
1480
|
// there is no broadcast and src0, src1 are contiguous across dims 2, 3
|
|
2345
1481
|
// use cublasGemmStridedBatchedEx
|
|
2346
1482
|
CUBLAS_CHECK(
|
|
2347
1483
|
cublasGemmStridedBatchedEx(ctx.cublas_handle(), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
2348
1484
|
ne01, ne11, ne10,
|
|
2349
|
-
alpha, src0_ptr, cu_data_type_a,
|
|
2350
|
-
src1_ptr, cu_data_type_b, s11,
|
|
2351
|
-
beta,
|
|
1485
|
+
alpha, src0_ptr, cu_data_type_a, s01, sma, // strideA
|
|
1486
|
+
src1_ptr, cu_data_type_b, s11, smb, // strideB
|
|
1487
|
+
beta, dst_ptr, cu_data_type, ne0, ne1*ne0, // strideC
|
|
2352
1488
|
ne12*ne13,
|
|
2353
1489
|
cu_compute_type,
|
|
2354
1490
|
CUBLAS_GEMM_DEFAULT_TENSOR_OP));
|
|
@@ -2359,24 +1495,23 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2359
1495
|
ggml_cuda_pool_alloc<const void *> ptrs_src(ctx.pool(), 2*ne23);
|
|
2360
1496
|
ggml_cuda_pool_alloc< void *> ptrs_dst(ctx.pool(), 1*ne23);
|
|
2361
1497
|
|
|
2362
|
-
size_t
|
|
1498
|
+
const size_t src_type_size = sizeof(cuda_t);
|
|
2363
1499
|
|
|
2364
1500
|
const int threads_x = 16;
|
|
2365
1501
|
const int threads_y = 16;
|
|
2366
|
-
dim3 block_dims(threads_x, threads_y);
|
|
1502
|
+
const dim3 block_dims(threads_x, threads_y);
|
|
2367
1503
|
|
|
2368
|
-
dim3 grid_dims(
|
|
1504
|
+
const dim3 grid_dims(
|
|
2369
1505
|
(ne13 + threads_x - 1) / threads_x,
|
|
2370
1506
|
(ne12 + threads_y - 1) / threads_y
|
|
2371
1507
|
);
|
|
2372
1508
|
k_compute_batched_ptrs<<<grid_dims, block_dims, 0, main_stream>>>(
|
|
2373
|
-
src0_ptr, src1_ptr,
|
|
1509
|
+
src0_ptr, src1_ptr, dst_ptr,
|
|
2374
1510
|
ptrs_src.get(), ptrs_dst.get(),
|
|
2375
1511
|
ne12, ne13,
|
|
2376
1512
|
ne23,
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
(src1->type == src0_type) ? nb13 : s13*src1_stride_size,
|
|
1513
|
+
s02*src_type_size, s03*src_type_size,
|
|
1514
|
+
s12*src_type_size, s13*src_type_size,
|
|
2380
1515
|
nbd2, nbd3,
|
|
2381
1516
|
r2, r3);
|
|
2382
1517
|
|
|
@@ -2385,7 +1520,7 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2385
1520
|
CUBLAS_CHECK(
|
|
2386
1521
|
cublasGemmBatchedEx(ctx.cublas_handle(), CUBLAS_OP_T, CUBLAS_OP_N,
|
|
2387
1522
|
ne01, ne11, ne10,
|
|
2388
|
-
alpha, (const void **) (ptrs_src.get() + 0*ne23), cu_data_type_a,
|
|
1523
|
+
alpha, (const void **) (ptrs_src.get() + 0*ne23), cu_data_type_a, s01,
|
|
2389
1524
|
(const void **) (ptrs_src.get() + 1*ne23), cu_data_type_b, s11,
|
|
2390
1525
|
beta, ( void **) (ptrs_dst.get() + 0*ne23), cu_data_type, ne0,
|
|
2391
1526
|
ne23,
|
|
@@ -2394,27 +1529,52 @@ static void ggml_cuda_mul_mat_batched_cublas_impl(ggml_backend_cuda_context & ct
|
|
|
2394
1529
|
}
|
|
2395
1530
|
|
|
2396
1531
|
// Convert output back to F32 if needed
|
|
2397
|
-
if (
|
|
1532
|
+
if (cu_data_type != CUDA_R_32F) {
|
|
2398
1533
|
const to_fp32_cuda_t to_fp32_cuda = ggml_get_to_fp32_cuda(traits::ggml_type_val);
|
|
2399
1534
|
to_fp32_cuda(dst_temp.get(), dst_ddf, ne_dst, main_stream);
|
|
2400
1535
|
}
|
|
2401
1536
|
}
|
|
2402
1537
|
|
|
2403
|
-
static void
|
|
2404
|
-
|
|
1538
|
+
static void ggml_cuda_mul_mat_cublas(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
|
|
1539
|
+
ggml_type compute_type = src0->type;
|
|
1540
|
+
if (ggml_is_quantized(compute_type)) {
|
|
1541
|
+
compute_type = fast_fp16_hardware_available(ggml_cuda_info().devices[ctx.device].cc) ? GGML_TYPE_F16 : GGML_TYPE_F32;
|
|
1542
|
+
} else if (compute_type == GGML_TYPE_F16 && !fast_fp16_hardware_available(ggml_cuda_info().devices[ctx.device].cc)) {
|
|
1543
|
+
compute_type = GGML_TYPE_F32;
|
|
1544
|
+
}
|
|
1545
|
+
if (dst->op_params[0] == GGML_PREC_F32) {
|
|
1546
|
+
compute_type = GGML_TYPE_F32;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
const char * env_c = getenv("GGML_CUDA_CUBLAS_COMPUTE_TYPE");
|
|
1550
|
+
if (env_c != nullptr) {
|
|
1551
|
+
std::string env_cpp = env_c;
|
|
1552
|
+
for (char & c : env_cpp) {
|
|
1553
|
+
c = std::tolower(c);
|
|
1554
|
+
}
|
|
1555
|
+
if (env_cpp == "f32" || env_cpp == "fp32") {
|
|
1556
|
+
compute_type = GGML_TYPE_F32;
|
|
1557
|
+
} else if (env_cpp == "f16" || env_cpp == "fp16") {
|
|
1558
|
+
compute_type = GGML_TYPE_F16;
|
|
1559
|
+
} else if (env_cpp == "bf16") {
|
|
1560
|
+
compute_type = GGML_TYPE_BF16;
|
|
1561
|
+
} else if (env_cpp != "auto") {
|
|
1562
|
+
GGML_LOG_WARN("%s: unknown value for GGML_CUDA_CUBLAS_COMPUTE_TYPE: %s", __func__, env_cpp.c_str());
|
|
1563
|
+
}
|
|
1564
|
+
}
|
|
2405
1565
|
|
|
2406
|
-
switch (
|
|
1566
|
+
switch (compute_type) {
|
|
2407
1567
|
case GGML_TYPE_F32:
|
|
2408
|
-
|
|
1568
|
+
ggml_cuda_mul_mat_cublas_impl<GGML_TYPE_F32>(ctx, src0, src1, dst);
|
|
2409
1569
|
break;
|
|
2410
1570
|
case GGML_TYPE_BF16:
|
|
2411
|
-
|
|
1571
|
+
ggml_cuda_mul_mat_cublas_impl<GGML_TYPE_BF16>(ctx, src0, src1, dst);
|
|
2412
1572
|
break;
|
|
2413
1573
|
case GGML_TYPE_F16:
|
|
2414
|
-
|
|
1574
|
+
ggml_cuda_mul_mat_cublas_impl<GGML_TYPE_F16>(ctx, src0, src1, dst);
|
|
2415
1575
|
break;
|
|
2416
1576
|
default:
|
|
2417
|
-
GGML_ABORT("
|
|
1577
|
+
GGML_ABORT("fatal error");
|
|
2418
1578
|
}
|
|
2419
1579
|
}
|
|
2420
1580
|
|
|
@@ -2422,12 +1582,18 @@ static bool ggml_cuda_should_fuse_mul_mat(const ggml_tensor * ffn_up,
|
|
|
2422
1582
|
const ggml_tensor * ffn_gate,
|
|
2423
1583
|
const ggml_tensor * glu,
|
|
2424
1584
|
const ggml_tensor * ffn_up_bias = nullptr,
|
|
2425
|
-
const ggml_tensor * ffn_gate_bias = nullptr
|
|
1585
|
+
const ggml_tensor * ffn_gate_bias = nullptr,
|
|
1586
|
+
const ggml_tensor * ffn_up_scale = nullptr,
|
|
1587
|
+
const ggml_tensor * ffn_gate_scale = nullptr) {
|
|
2426
1588
|
const bool has_bias = ffn_up_bias != nullptr || ffn_gate_bias != nullptr;
|
|
1589
|
+
const bool has_scale = ffn_up_scale != nullptr || ffn_gate_scale != nullptr;
|
|
2427
1590
|
|
|
2428
1591
|
if (has_bias && (!ffn_up_bias || !ffn_gate_bias)) {
|
|
2429
1592
|
return false;
|
|
2430
1593
|
}
|
|
1594
|
+
if (has_scale && (!ffn_up_scale || !ffn_gate_scale)) {
|
|
1595
|
+
return false;
|
|
1596
|
+
}
|
|
2431
1597
|
|
|
2432
1598
|
const bool is_mul_mat = ffn_up->op == GGML_OP_MUL_MAT && ffn_gate->op == GGML_OP_MUL_MAT && glu->op == GGML_OP_GLU;
|
|
2433
1599
|
const bool is_mul_mat_id = ffn_up->op == GGML_OP_MUL_MAT_ID && ffn_gate->op == GGML_OP_MUL_MAT_ID && glu->op == GGML_OP_GLU;
|
|
@@ -2439,34 +1605,45 @@ static bool ggml_cuda_should_fuse_mul_mat(const ggml_tensor * ffn_up,
|
|
|
2439
1605
|
}
|
|
2440
1606
|
|
|
2441
1607
|
const ggml_op expected_bias_op = is_mul_mat ? GGML_OP_ADD : GGML_OP_ADD_ID;
|
|
1608
|
+
const ggml_tensor * ffn_up_bias_src = has_scale ? ffn_up_scale : ffn_up;
|
|
1609
|
+
const ggml_tensor * ffn_gate_bias_src = has_scale ? ffn_gate_scale : ffn_gate;
|
|
1610
|
+
const ggml_tensor * ffn_up_out = has_bias ? ffn_up_bias : ffn_up_bias_src;
|
|
1611
|
+
const ggml_tensor * ffn_gate_out = has_bias ? ffn_gate_bias : ffn_gate_bias_src;
|
|
2442
1612
|
|
|
2443
|
-
if (
|
|
2444
|
-
|
|
1613
|
+
if (glu->src[0] != ffn_gate_out || glu->src[1] != ffn_up_out) {
|
|
1614
|
+
return false;
|
|
1615
|
+
}
|
|
1616
|
+
|
|
1617
|
+
if (has_scale) {
|
|
1618
|
+
if (ffn_up_scale->op != GGML_OP_MUL || ffn_gate_scale->op != GGML_OP_MUL) {
|
|
2445
1619
|
return false;
|
|
2446
1620
|
}
|
|
1621
|
+
const bool up_has_mm = ffn_up_scale->src[0] == ffn_up || ffn_up_scale->src[1] == ffn_up;
|
|
1622
|
+
const bool gate_has_mm = ffn_gate_scale->src[0] == ffn_gate || ffn_gate_scale->src[1] == ffn_gate;
|
|
1623
|
+
if (!up_has_mm || !gate_has_mm) {
|
|
1624
|
+
return false;
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
2447
1627
|
|
|
2448
|
-
|
|
1628
|
+
if (has_bias) {
|
|
1629
|
+
if (ffn_up_bias->op != expected_bias_op || ffn_gate_bias->op != expected_bias_op) {
|
|
2449
1630
|
return false;
|
|
2450
1631
|
}
|
|
2451
1632
|
|
|
2452
1633
|
if (expected_bias_op == GGML_OP_ADD) {
|
|
2453
|
-
const bool up_has_mul = ffn_up_bias->src[0] ==
|
|
2454
|
-
const bool gate_has_mul = ffn_gate_bias->src[0] ==
|
|
1634
|
+
const bool up_has_mul = ffn_up_bias->src[0] == ffn_up_bias_src || ffn_up_bias->src[1] == ffn_up_bias_src;
|
|
1635
|
+
const bool gate_has_mul = ffn_gate_bias->src[0] == ffn_gate_bias_src || ffn_gate_bias->src[1] == ffn_gate_bias_src;
|
|
2455
1636
|
if (!up_has_mul || !gate_has_mul) {
|
|
2456
1637
|
return false;
|
|
2457
1638
|
}
|
|
2458
1639
|
} else { // GGML_OP_ADD_ID
|
|
2459
|
-
if (ffn_up_bias->src[0] !=
|
|
1640
|
+
if (ffn_up_bias->src[0] != ffn_up_bias_src || ffn_gate_bias->src[0] != ffn_gate_bias_src) {
|
|
2460
1641
|
return false;
|
|
2461
1642
|
}
|
|
2462
1643
|
if (ffn_up_bias->src[2] != ffn_up->src[2] || ffn_gate_bias->src[2] != ffn_gate->src[2]) {
|
|
2463
1644
|
return false;
|
|
2464
1645
|
}
|
|
2465
1646
|
}
|
|
2466
|
-
} else {
|
|
2467
|
-
if (glu->src[0] != ffn_gate && glu->src[1] != ffn_up) {
|
|
2468
|
-
return false;
|
|
2469
|
-
}
|
|
2470
1647
|
}
|
|
2471
1648
|
|
|
2472
1649
|
if (ffn_up->src[0]->type != ffn_gate->src[0]->type || !ggml_are_same_shape(ffn_up->src[0], ffn_gate->src[0]) ||
|
|
@@ -2478,7 +1655,7 @@ static bool ggml_cuda_should_fuse_mul_mat(const ggml_tensor * ffn_up,
|
|
|
2478
1655
|
return false;
|
|
2479
1656
|
}
|
|
2480
1657
|
|
|
2481
|
-
if (
|
|
1658
|
+
if (is_mul_mat_id && ffn_up->src[2] != ffn_gate->src[2]) {
|
|
2482
1659
|
return false;
|
|
2483
1660
|
}
|
|
2484
1661
|
|
|
@@ -2492,14 +1669,6 @@ static bool ggml_cuda_should_fuse_mul_mat(const ggml_tensor * ffn_up,
|
|
|
2492
1669
|
return false;
|
|
2493
1670
|
}
|
|
2494
1671
|
|
|
2495
|
-
const bool split = ggml_backend_buft_is_cuda_split(ffn_up->src[0]->buffer->buft) ||
|
|
2496
|
-
ggml_backend_buft_is_cuda_split(ffn_gate->src[0]->buffer->buft);
|
|
2497
|
-
|
|
2498
|
-
//TODO: add support for fusion for split buffers
|
|
2499
|
-
if (split) {
|
|
2500
|
-
return false;
|
|
2501
|
-
}
|
|
2502
|
-
|
|
2503
1672
|
return true;
|
|
2504
1673
|
}
|
|
2505
1674
|
|
|
@@ -2517,14 +1686,6 @@ static bool ggml_cuda_should_fuse_mul_mat_vec_f(const ggml_tensor * tensor) {
|
|
|
2517
1686
|
const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc;
|
|
2518
1687
|
use_mul_mat_vec_f = use_mul_mat_vec_f && ggml_cuda_should_use_mmvf(src0->type, cc, src0->ne, src0->nb, is_mul_mat_id ? src1->ne[2] : src1->ne[1]);
|
|
2519
1688
|
|
|
2520
|
-
const bool split = ggml_backend_buft_is_cuda_split(src0->buffer->buft) ||
|
|
2521
|
-
ggml_backend_buft_is_cuda_split(src1->buffer->buft);
|
|
2522
|
-
|
|
2523
|
-
//TODO: add support for fusion for split buffers
|
|
2524
|
-
if (split) {
|
|
2525
|
-
return false;
|
|
2526
|
-
}
|
|
2527
|
-
|
|
2528
1689
|
//we only support fusion for ncols_dst = 1
|
|
2529
1690
|
if (tensor->op == GGML_OP_MUL_MAT && dst->ne[1] != 1) {
|
|
2530
1691
|
return false;
|
|
@@ -2564,108 +1725,49 @@ static bool ggml_cuda_should_fuse_mul_mat_vec_q(const ggml_tensor * tensor) {
|
|
|
2564
1725
|
return false;
|
|
2565
1726
|
}
|
|
2566
1727
|
|
|
2567
|
-
|
|
2568
|
-
const bool split = ggml_backend_buft_is_cuda_split(src0->buffer->buft) ||
|
|
2569
|
-
ggml_backend_buft_is_cuda_split(src1->buffer->buft);
|
|
2570
|
-
|
|
2571
|
-
//TODO: add support for fusion for split buffers
|
|
2572
|
-
if (split) {
|
|
2573
|
-
return false;
|
|
2574
|
-
}
|
|
2575
|
-
|
|
2576
1728
|
return use_mul_mat_vec_q;
|
|
2577
1729
|
}
|
|
2578
1730
|
|
|
2579
1731
|
static void ggml_cuda_mul_mat(ggml_backend_cuda_context & ctx, const ggml_tensor * src0, const ggml_tensor * src1, ggml_tensor * dst) {
|
|
2580
|
-
|
|
1732
|
+
GGML_TENSOR_BINARY_OP_LOCALS
|
|
1733
|
+
|
|
1734
|
+
const int32_t hint = ggml_get_op_params_i32(dst, 1);
|
|
1735
|
+
if (hint == GGML_HINT_SRC0_IS_HADAMARD && ggml_cuda_op_fwht(ctx, src1, dst)) {
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
2581
1738
|
|
|
2582
1739
|
// If src0 is a temporary compute buffer it may have some padding that needs to be cleared for mul_mat_vec_q or mul_mat_q.
|
|
2583
1740
|
// But if src0 is also a view of another tensor then this cannot be done safely because it may overwrite valid tensor data.
|
|
2584
1741
|
// Therefore, in such cases use cuBLAS.
|
|
2585
1742
|
const bool bad_padding_clear = ggml_backend_buffer_get_usage(src0->buffer) == GGML_BACKEND_BUFFER_USAGE_COMPUTE
|
|
2586
1743
|
&& ggml_nbytes(src0) != ggml_backend_buffer_get_alloc_size(src0->buffer, src0) && src0->view_src;
|
|
2587
|
-
|
|
2588
|
-
|
|
2589
|
-
&& src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32;
|
|
2590
|
-
bool use_mul_mat_f = !ggml_is_quantized(src0->type)
|
|
2591
|
-
&& src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32;
|
|
2592
|
-
bool use_mul_mat_vec_q = ggml_is_quantized(src0->type) && !bad_padding_clear
|
|
2593
|
-
&& src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32
|
|
2594
|
-
&& src1->ne[1] <= MMVQ_MAX_BATCH_SIZE;
|
|
2595
|
-
bool use_mul_mat_q = ggml_is_quantized(src0->type) && !bad_padding_clear
|
|
2596
|
-
&& src1->type == GGML_TYPE_F32 && dst->type == GGML_TYPE_F32;
|
|
2597
|
-
|
|
2598
|
-
bool any_gpus_with_slow_fp16 = false;
|
|
2599
|
-
|
|
2600
|
-
if (split) {
|
|
2601
|
-
ggml_backend_cuda_split_buffer_type_context * buft_ctx = (ggml_backend_cuda_split_buffer_type_context *) src0->buffer->buft->context;
|
|
2602
|
-
auto & tensor_split = buft_ctx->tensor_split;
|
|
2603
|
-
for (int id = 0; id < ggml_backend_cuda_get_device_count(); ++id) {
|
|
2604
|
-
// skip devices that are not going to do any work:
|
|
2605
|
-
if (tensor_split[id] >= (id + 1 < ggml_backend_cuda_get_device_count() ? tensor_split[id + 1] : 1.0f)) {
|
|
2606
|
-
continue;
|
|
2607
|
-
}
|
|
2608
|
-
|
|
2609
|
-
const int cc = ggml_cuda_info().devices[id].cc;
|
|
2610
|
-
const int warp_size = ggml_cuda_info().devices[id].warp_size;
|
|
2611
|
-
use_mul_mat_q = use_mul_mat_q && ggml_cuda_should_use_mmq(src0->type, cc, src1->ne[1], /*n_experts=*/0);
|
|
2612
|
-
use_mul_mat_f = use_mul_mat_f && ggml_cuda_should_use_mmf(src0->type, cc, warp_size, src0->ne, src0->nb, src1->ne[1], /*mul_mat_id=*/false);
|
|
2613
|
-
use_mul_mat_vec_f = use_mul_mat_vec_f && ggml_cuda_should_use_mmvf(src0->type, cc, src0->ne, src0->nb, src1->ne[1]);
|
|
2614
|
-
use_mul_mat_vec_q = use_mul_mat_vec_q && ggml_cuda_should_use_mmvq(src0->type, cc, src1->ne[1]);
|
|
2615
|
-
any_gpus_with_slow_fp16 = any_gpus_with_slow_fp16 || !fast_fp16_hardware_available(cc);
|
|
2616
|
-
}
|
|
2617
|
-
} else {
|
|
2618
|
-
const int cc = ggml_cuda_info().devices[ctx.device].cc;
|
|
2619
|
-
const int warp_size = ggml_cuda_info().devices[ctx.device].warp_size;
|
|
2620
|
-
use_mul_mat_q = use_mul_mat_q && ggml_cuda_should_use_mmq(src0->type, cc, src1->ne[1], /*n_experts=*/0);
|
|
2621
|
-
use_mul_mat_f = use_mul_mat_f && ggml_cuda_should_use_mmf(src0->type, cc, warp_size, src0->ne, src0->nb, src1->ne[1], /*mul_mat_id=*/false);
|
|
2622
|
-
use_mul_mat_vec_f = use_mul_mat_vec_f && ggml_cuda_should_use_mmvf(src0->type, cc, src0->ne, src0->nb, src1->ne[1]);
|
|
2623
|
-
use_mul_mat_vec_q = use_mul_mat_vec_q && ggml_cuda_should_use_mmvq(src0->type, cc, src1->ne[1]);
|
|
2624
|
-
any_gpus_with_slow_fp16 = any_gpus_with_slow_fp16 || !fast_fp16_hardware_available(cc);
|
|
2625
|
-
}
|
|
2626
|
-
|
|
2627
|
-
// debug helpers
|
|
2628
|
-
//printf("src0: %8d %8d %8d %8d\n", src0->ne[0], src0->ne[1], src0->ne[2], src0->ne[3]);
|
|
2629
|
-
//printf(" %8d %8d %8d %8d\n", src0->nb[0], src0->nb[1], src0->nb[2], src0->nb[3]);
|
|
2630
|
-
//printf("src1: %8d %8d %8d %8d\n", src1->ne[0], src1->ne[1], src1->ne[2], src1->ne[3]);
|
|
2631
|
-
//printf(" %8d %8d %8d %8d\n", src1->nb[0], src1->nb[1], src1->nb[2], src1->nb[3]);
|
|
2632
|
-
//printf("src0 is contiguous %d, transposed %d, type = %s, name = %s\n", ggml_is_contiguous(src0), ggml_is_transposed(src0), ggml_type_name(src0->type), src0->name);
|
|
2633
|
-
//printf("src1 is contiguous %d, transposed %d, type = %s, name = %s\n", ggml_is_contiguous(src1), ggml_is_transposed(src1), ggml_type_name(src1->type), src1->name);
|
|
2634
|
-
|
|
2635
|
-
//TODO update for generic tensor parallelism
|
|
2636
|
-
const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc;
|
|
2637
|
-
bool use_batched_cublas_f16 = src0->type == GGML_TYPE_F16 && (src1->type == GGML_TYPE_F16 || !any_gpus_with_slow_fp16);
|
|
2638
|
-
bool use_batched_cublas_bf16 = src0->type == GGML_TYPE_BF16 && bf16_mma_hardware_available(cc);
|
|
2639
|
-
bool use_batched_cublas_f32 = src0->type == GGML_TYPE_F32;
|
|
2640
|
-
|
|
2641
|
-
const int32_t hint = ggml_get_op_params_i32(dst, 1);
|
|
2642
|
-
if (hint == GGML_HINT_SRC0_IS_HADAMARD && !split && ggml_cuda_op_fwht(ctx, src1, dst)) {
|
|
1744
|
+
if (bad_padding_clear || src1->type != GGML_TYPE_F32 || dst->type != GGML_TYPE_F32) {
|
|
1745
|
+
ggml_cuda_mul_mat_cublas(ctx, src0, src1, dst);
|
|
2643
1746
|
return;
|
|
2644
1747
|
}
|
|
2645
1748
|
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
1749
|
+
const int cc = ggml_cuda_info().devices[ctx.device].cc;
|
|
1750
|
+
const int warp_size = ggml_cuda_info().devices[ctx.device].warp_size;
|
|
1751
|
+
|
|
1752
|
+
if (ggml_cuda_should_use_mmvf(src0->type, cc, src0->ne, src0->nb, ne11)) {
|
|
1753
|
+
// The custom F16 vector kernel can be used over batched cuBLAS GEMM.
|
|
1754
|
+
// But this is only faster for GPUs without tensor cores or with a thin src0 matrix (particularly KQV in attention)
|
|
2649
1755
|
ggml_cuda_mul_mat_vec_f(ctx, src0, src1, nullptr, dst);
|
|
2650
|
-
|
|
1756
|
+
return;
|
|
1757
|
+
}
|
|
1758
|
+
if (ggml_cuda_should_use_mmf(src0->type, cc, warp_size, src0->ne, src0->nb, ne11, /*mul_mat_id =*/ false)) {
|
|
2651
1759
|
ggml_cuda_mul_mat_f(ctx, src0, src1, nullptr, dst);
|
|
2652
|
-
|
|
1760
|
+
return;
|
|
1761
|
+
}
|
|
1762
|
+
if (ggml_cuda_should_use_mmvq(src0->type, cc, ne11)) {
|
|
2653
1763
|
ggml_cuda_mul_mat_vec_q(ctx, src0, src1, nullptr, dst);
|
|
2654
|
-
|
|
1764
|
+
return;
|
|
1765
|
+
}
|
|
1766
|
+
if (ggml_cuda_should_use_mmq(src0->type, cc, ne11, /*n_experts =*/ 0)) {
|
|
2655
1767
|
ggml_cuda_mul_mat_q(ctx, src0, src1, nullptr, dst);
|
|
2656
|
-
|
|
2657
|
-
&& !ggml_is_transposed(src0) && !ggml_is_transposed(src1) && src1->ne[2]*src1->ne[3] > 1) {
|
|
2658
|
-
// general KQ + KQV multi-batch without FlashAttention
|
|
2659
|
-
ggml_cuda_mul_mat_batched_cublas(ctx, src0, src1, dst);
|
|
2660
|
-
} else if (use_mul_mat_vec_f) {
|
|
2661
|
-
ggml_cuda_op_mul_mat(ctx, src0, src1, dst, ggml_cuda_op_mul_mat_vec_f, nullptr);
|
|
2662
|
-
} else if (use_mul_mat_vec_q) {
|
|
2663
|
-
ggml_cuda_op_mul_mat(ctx, src0, src1, dst, ggml_cuda_op_mul_mat_vec_q, quantize_row_q8_1_cuda);
|
|
2664
|
-
} else if (use_mul_mat_q) {
|
|
2665
|
-
ggml_cuda_op_mul_mat(ctx, src0, src1, dst, ggml_cuda_op_mul_mat_q, quantize_mmq_q8_1_cuda);
|
|
2666
|
-
} else {
|
|
2667
|
-
ggml_cuda_op_mul_mat(ctx, src0, src1, dst, ggml_cuda_op_mul_mat_cublas, nullptr);
|
|
1768
|
+
return;
|
|
2668
1769
|
}
|
|
1770
|
+
ggml_cuda_mul_mat_cublas(ctx, src0, src1, dst);
|
|
2669
1771
|
}
|
|
2670
1772
|
|
|
2671
1773
|
static void ggml_cuda_mul_mat_id(ggml_backend_cuda_context & ctx, ggml_tensor * dst) {
|
|
@@ -2675,7 +1777,6 @@ static void ggml_cuda_mul_mat_id(ggml_backend_cuda_context & ctx, ggml_tensor *
|
|
|
2675
1777
|
|
|
2676
1778
|
GGML_ASSERT(src1->type == GGML_TYPE_F32);
|
|
2677
1779
|
GGML_ASSERT(dst->type == GGML_TYPE_F32);
|
|
2678
|
-
GGML_ASSERT(!ggml_backend_buft_is_cuda_split(src0->buffer->buft) && "mul_mat_id does not support split buffers");
|
|
2679
1780
|
|
|
2680
1781
|
GGML_TENSOR_BINARY_OP_LOCALS
|
|
2681
1782
|
|
|
@@ -3090,6 +2191,9 @@ static bool ggml_cuda_compute_forward(ggml_backend_cuda_context & ctx, struct gg
|
|
|
3090
2191
|
case GGML_OP_CONV_TRANSPOSE_1D:
|
|
3091
2192
|
ggml_cuda_op_conv_transpose_1d(ctx,dst);
|
|
3092
2193
|
break;
|
|
2194
|
+
case GGML_OP_COL2IM_1D:
|
|
2195
|
+
ggml_cuda_op_col2im_1d(ctx, dst);
|
|
2196
|
+
break;
|
|
3093
2197
|
case GGML_OP_POOL_2D:
|
|
3094
2198
|
ggml_cuda_op_pool2d(ctx, dst);
|
|
3095
2199
|
break;
|
|
@@ -3179,12 +2283,6 @@ static const char * ggml_backend_cuda_get_name(ggml_backend_t backend) {
|
|
|
3179
2283
|
static void ggml_backend_cuda_free(ggml_backend_t backend) {
|
|
3180
2284
|
ggml_backend_cuda_context * cuda_ctx = (ggml_backend_cuda_context *)backend->context;
|
|
3181
2285
|
|
|
3182
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
3183
|
-
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) backend->device->context;
|
|
3184
|
-
std::lock_guard<std::mutex> lock(dev_ctx->device_mutex);
|
|
3185
|
-
dev_ctx->active_count--;
|
|
3186
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
3187
|
-
|
|
3188
2286
|
delete cuda_ctx;
|
|
3189
2287
|
delete backend;
|
|
3190
2288
|
}
|
|
@@ -3292,6 +2390,11 @@ static void ggml_backend_cuda_synchronize(ggml_backend_t backend) {
|
|
|
3292
2390
|
GGML_UNUSED(backend);
|
|
3293
2391
|
}
|
|
3294
2392
|
|
|
2393
|
+
static bool ggml_cuda_is_view_or_noop(const ggml_tensor * t) {
|
|
2394
|
+
return ggml_is_empty(t) || t->op == GGML_OP_RESHAPE || t->op == GGML_OP_TRANSPOSE ||
|
|
2395
|
+
t->op == GGML_OP_VIEW || t->op == GGML_OP_PERMUTE || t->op == GGML_OP_NONE;
|
|
2396
|
+
}
|
|
2397
|
+
|
|
3295
2398
|
#ifdef USE_CUDA_GRAPH
|
|
3296
2399
|
static bool ggml_cuda_graph_check_compability(ggml_cgraph * cgraph) {
|
|
3297
2400
|
|
|
@@ -3301,17 +2404,10 @@ static bool ggml_cuda_graph_check_compability(ggml_cgraph * cgraph) {
|
|
|
3301
2404
|
for (int i = 0; i < cgraph->n_nodes; i++) {
|
|
3302
2405
|
ggml_tensor * node = cgraph->nodes[i];
|
|
3303
2406
|
|
|
3304
|
-
if (
|
|
2407
|
+
if (ggml_cuda_is_view_or_noop(node)) {
|
|
3305
2408
|
continue;
|
|
3306
2409
|
}
|
|
3307
2410
|
|
|
3308
|
-
if (node->src[0] && node->src[0]->buffer && ggml_backend_buft_is_cuda_split(node->src[0]->buffer->buft)) {
|
|
3309
|
-
use_cuda_graph = false; // Split buffers are not supported by CUDA graph capture
|
|
3310
|
-
#ifndef NDEBUG
|
|
3311
|
-
GGML_LOG_DEBUG("%s: disabling CUDA graphs due to split buffer\n", __func__);
|
|
3312
|
-
#endif
|
|
3313
|
-
}
|
|
3314
|
-
|
|
3315
2411
|
// [TAG_MUL_MAT_ID_CUDA_GRAPHS]
|
|
3316
2412
|
if (node->op == GGML_OP_MUL_MAT_ID) {
|
|
3317
2413
|
const int cc = ggml_cuda_info().devices[ggml_cuda_get_device()].cc;
|
|
@@ -3444,6 +2540,70 @@ static bool ggml_cuda_should_fuse_rope_set_rows(const ggml_tensor * rope,
|
|
|
3444
2540
|
return true;
|
|
3445
2541
|
}
|
|
3446
2542
|
|
|
2543
|
+
// match gated_delta_net + the strided cpy that scatters its state snapshots into the cache
|
|
2544
|
+
// (slot i -> rollback group i, slot 0 newest), so the kernel can write them and skip the cpy.
|
|
2545
|
+
static int ggml_cuda_try_gdn_cache_fusion(
|
|
2546
|
+
const ggml_cgraph * cgraph, int node_idx, ggml_cuda_gated_delta_net_fused_cache & fused_state_cpy) {
|
|
2547
|
+
const ggml_tensor * gdn = cgraph->nodes[node_idx];
|
|
2548
|
+
// the kernel skips the snapshot tail, so the gdn output must not be a graph output
|
|
2549
|
+
if (gdn->op != GGML_OP_GATED_DELTA_NET || gdn->type != GGML_TYPE_F32 ||
|
|
2550
|
+
(gdn->flags & GGML_TENSOR_FLAG_OUTPUT)) {
|
|
2551
|
+
return 0;
|
|
2552
|
+
}
|
|
2553
|
+
|
|
2554
|
+
const ggml_tensor * src_v = gdn->src[2];
|
|
2555
|
+
const int64_t S_v = src_v->ne[0];
|
|
2556
|
+
const int64_t H = src_v->ne[1];
|
|
2557
|
+
const int64_t n_tokens = src_v->ne[2];
|
|
2558
|
+
const int64_t n_seqs = src_v->ne[3];
|
|
2559
|
+
const int64_t D = S_v * S_v * H;
|
|
2560
|
+
const int64_t K = ggml_get_op_params_i32(gdn, 0); // snapshot slot count
|
|
2561
|
+
const int64_t n_written = std::min<int64_t>(n_tokens, K); // newest n_written slots are written
|
|
2562
|
+
|
|
2563
|
+
// snapshot tail starts right after the attention scores
|
|
2564
|
+
const size_t tail_off = ggml_row_size(GGML_TYPE_F32, S_v * H * n_tokens * n_seqs);
|
|
2565
|
+
|
|
2566
|
+
// snapshot cpy is the first real node after the gdn (skip views/no-ops)
|
|
2567
|
+
const ggml_tensor * cpy = nullptr;
|
|
2568
|
+
int skip = 0;
|
|
2569
|
+
for (int j = node_idx + 1; j < cgraph->n_nodes && cpy == nullptr; ++j) {
|
|
2570
|
+
const ggml_tensor * n = cgraph->nodes[j];
|
|
2571
|
+
if (ggml_cuda_is_view_or_noop(n)) {
|
|
2572
|
+
continue;
|
|
2573
|
+
}
|
|
2574
|
+
if (n->op != GGML_OP_CPY || (n->flags & GGML_TENSOR_FLAG_OUTPUT)) {
|
|
2575
|
+
return 0;
|
|
2576
|
+
}
|
|
2577
|
+
cpy = n;
|
|
2578
|
+
skip = j - node_idx;
|
|
2579
|
+
}
|
|
2580
|
+
if (cpy == nullptr) {
|
|
2581
|
+
return 0;
|
|
2582
|
+
}
|
|
2583
|
+
|
|
2584
|
+
const ggml_tensor * src = cpy->src[0]; // view of the gdn snapshot tail
|
|
2585
|
+
const ggml_tensor * dst = cpy->src[1]; // cache view the kernel writes to
|
|
2586
|
+
|
|
2587
|
+
// src must be this gdn's snapshot tail (contiguous, at the tail offset)
|
|
2588
|
+
if (src->op != GGML_OP_VIEW || src->view_src != gdn || src->view_offs != tail_off ||
|
|
2589
|
+
!ggml_is_contiguous(src)) {
|
|
2590
|
+
return 0;
|
|
2591
|
+
}
|
|
2592
|
+
|
|
2593
|
+
// dst is the [D, n_seqs, n_written] cache view; require nb[1] == D (the per-seq stride the kernel
|
|
2594
|
+
// assumes). ggml_cpy pins src to the same element count.
|
|
2595
|
+
const std::array<int64_t, GGML_MAX_DIMS> expected_ne = { D, n_seqs, n_written, 1 };
|
|
2596
|
+
if (dst->op != GGML_OP_VIEW || dst->type != GGML_TYPE_F32 || dst->data == nullptr ||
|
|
2597
|
+
!std::equal(expected_ne.begin(), expected_ne.end(), dst->ne) ||
|
|
2598
|
+
dst->nb[0] != ggml_type_size(GGML_TYPE_F32) || dst->nb[1] != (size_t) ggml_row_size(GGML_TYPE_F32, D)) {
|
|
2599
|
+
return 0;
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
fused_state_cpy.data = (float *) dst->data; // rollback group 0 (newest)
|
|
2603
|
+
fused_state_cpy.slot_stride = K > 1 ? (int64_t) (dst->nb[2] / sizeof(float)) : 0;
|
|
2604
|
+
return skip;
|
|
2605
|
+
}
|
|
2606
|
+
|
|
3447
2607
|
static bool ggml_cuda_topk_moe_fusion(const struct ggml_cgraph * cgraph, int node_idx, ggml_cuda_topk_moe_args & args) {
|
|
3448
2608
|
args.sigmoid = false;
|
|
3449
2609
|
args.softmax = false;
|
|
@@ -3885,6 +3045,20 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
|
|
|
3885
3045
|
|
|
3886
3046
|
ggml_tensor * node = cgraph->nodes[i];
|
|
3887
3047
|
|
|
3048
|
+
// gated_delta_net -> cpy: scatter recurrent-state snapshots into the cache
|
|
3049
|
+
if (node->op == GGML_OP_GATED_DELTA_NET) {
|
|
3050
|
+
ggml_cuda_gated_delta_net_fused_cache fused_state_cpy;
|
|
3051
|
+
const int nodes_to_skip = ggml_cuda_try_gdn_cache_fusion(cgraph, i, fused_state_cpy);
|
|
3052
|
+
if (nodes_to_skip > 0) {
|
|
3053
|
+
#ifdef GGML_CUDA_DEBUG
|
|
3054
|
+
GGML_LOG_INFO("%s: fused gated_delta_net snapshot copies for %s (skipped %d nodes)\n",
|
|
3055
|
+
__func__, node->name, nodes_to_skip);
|
|
3056
|
+
#endif
|
|
3057
|
+
ggml_cuda_op_gated_delta_net_fused_cache(*cuda_ctx, node, fused_state_cpy);
|
|
3058
|
+
return nodes_to_skip;
|
|
3059
|
+
}
|
|
3060
|
+
}
|
|
3061
|
+
|
|
3888
3062
|
//topk-moe
|
|
3889
3063
|
if (cgraph->nodes[i]->op == GGML_OP_UNARY || cgraph->nodes[i]->op == GGML_OP_SOFT_MAX ||
|
|
3890
3064
|
cgraph->nodes[i]->op == GGML_OP_ARGSORT) {
|
|
@@ -3991,18 +3165,21 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
|
|
|
3991
3165
|
(a->ne[2] == 1 && a->ne[3] == 1);
|
|
3992
3166
|
const bool shape_ok = ggml_are_same_shape(a, inv_b) && a->ne[0] == 1 && a->ne[1] == x->ne[1];
|
|
3993
3167
|
|
|
3994
|
-
// x
|
|
3995
|
-
//
|
|
3996
|
-
//
|
|
3997
|
-
// fall back to the naive path.
|
|
3168
|
+
// x is in the supported whitelist and every chain intermediate shares
|
|
3169
|
+
// x's type. launch_snake reads a and inv_b as const float *, so they
|
|
3170
|
+
// stay F32.
|
|
3998
3171
|
const ggml_tensor * sin1 = cgraph->nodes[i + 1];
|
|
3999
3172
|
const bool types_ok = (x->type == GGML_TYPE_F32 || x->type == GGML_TYPE_F16 || x->type == GGML_TYPE_BF16) &&
|
|
4000
|
-
(a->type ==
|
|
3173
|
+
(a->type == GGML_TYPE_F32) && (inv_b->type == GGML_TYPE_F32) &&
|
|
4001
3174
|
(mul0->type == x->type) && (sin1->type == x->type) &&
|
|
4002
3175
|
(sqr->type == x->type) && (mul1->type == x->type) &&
|
|
4003
3176
|
(add->type == x->type);
|
|
4004
3177
|
|
|
4005
|
-
|
|
3178
|
+
// kernel reads x[idx] and a[c] / inv_b[c] linearly, so every operand is contiguous
|
|
3179
|
+
const bool contig_ok = ggml_is_contiguous(x) && ggml_is_contiguous(add) &&
|
|
3180
|
+
ggml_is_contiguous(a) && ggml_is_contiguous(inv_b);
|
|
3181
|
+
|
|
3182
|
+
if (types_ok && shape_ok && dim_ok && contig_ok && x_in_add == x) {
|
|
4006
3183
|
ggml_cuda_op_snake_fused(*cuda_ctx, x, a, inv_b, add);
|
|
4007
3184
|
return 4;
|
|
4008
3185
|
}
|
|
@@ -4047,10 +3224,240 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
|
|
|
4047
3224
|
bool fused_mul_mat_vec = false;
|
|
4048
3225
|
int fused_node_count = 0;
|
|
4049
3226
|
|
|
4050
|
-
|
|
3227
|
+
auto get_mul_mat_scale = [](const ggml_tensor * scale_node, const ggml_tensor * mm_node) -> const ggml_tensor * {
|
|
3228
|
+
const bool scale_lhs_mm = scale_node->src[0] == mm_node;
|
|
3229
|
+
const bool scale_rhs_mm = scale_node->src[1] == mm_node;
|
|
3230
|
+
if (!scale_lhs_mm && !scale_rhs_mm) {
|
|
3231
|
+
return nullptr;
|
|
3232
|
+
}
|
|
3233
|
+
|
|
3234
|
+
const ggml_tensor * scale = scale_lhs_mm ? scale_node->src[1] : scale_node->src[0];
|
|
3235
|
+
if (mm_node->src[0]->type != GGML_TYPE_NVFP4 || scale_node->type != GGML_TYPE_F32 ||
|
|
3236
|
+
scale->type != GGML_TYPE_F32 || !ggml_is_contiguous(scale) || ggml_nelements(scale) != 1 ||
|
|
3237
|
+
!ggml_are_same_shape(scale_node, mm_node)) {
|
|
3238
|
+
return nullptr;
|
|
3239
|
+
}
|
|
3240
|
+
|
|
3241
|
+
return scale;
|
|
3242
|
+
};
|
|
3243
|
+
|
|
3244
|
+
auto get_mul_mat_id_scale = [](const ggml_tensor * reshape, const ggml_tensor * repeat, const ggml_tensor * getrows,
|
|
3245
|
+
const ggml_tensor * scale_node, const ggml_tensor * mm_node) -> const ggml_tensor * {
|
|
3246
|
+
if (repeat->src[0] != reshape || getrows->src[0] != repeat || getrows->src[1] != mm_node->src[2]) {
|
|
3247
|
+
return nullptr;
|
|
3248
|
+
}
|
|
3249
|
+
if (!((scale_node->src[0] == mm_node && scale_node->src[1] == getrows) ||
|
|
3250
|
+
(scale_node->src[0] == getrows && scale_node->src[1] == mm_node))) {
|
|
3251
|
+
return nullptr;
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
const ggml_tensor * scale = reshape->src[0];
|
|
3255
|
+
if (mm_node->src[0]->type != GGML_TYPE_NVFP4 || scale_node->type != GGML_TYPE_F32 ||
|
|
3256
|
+
scale->type != GGML_TYPE_F32 || !ggml_is_contiguous(scale) || ggml_nelements(scale) != mm_node->src[0]->ne[2] ||
|
|
3257
|
+
!ggml_are_same_shape(scale_node, mm_node)) {
|
|
3258
|
+
return nullptr;
|
|
3259
|
+
}
|
|
3260
|
+
|
|
3261
|
+
return scale;
|
|
3262
|
+
};
|
|
3263
|
+
|
|
3264
|
+
auto get_bias_tensor = [](const ggml_tensor * bias_node, const ggml_tensor * mul_node, ggml_op op_bias) -> const ggml_tensor * {
|
|
3265
|
+
if (op_bias == GGML_OP_ADD) {
|
|
3266
|
+
if (bias_node->src[0] == mul_node) {
|
|
3267
|
+
return bias_node->src[1];
|
|
3268
|
+
}
|
|
3269
|
+
if (bias_node->src[1] == mul_node) {
|
|
3270
|
+
return bias_node->src[0];
|
|
3271
|
+
}
|
|
3272
|
+
return nullptr;
|
|
3273
|
+
}
|
|
3274
|
+
GGML_ASSERT(op_bias == GGML_OP_ADD_ID);
|
|
3275
|
+
GGML_ASSERT(bias_node->src[0] == mul_node);
|
|
3276
|
+
return bias_node->src[1];
|
|
3277
|
+
};
|
|
3278
|
+
|
|
3279
|
+
// gate + glu + up, with optional scale/bias on both lanes.
|
|
4051
3280
|
for (ggml_op op : { GGML_OP_MUL_MAT, GGML_OP_MUL_MAT_ID }) {
|
|
4052
3281
|
const ggml_op bias_op = op == GGML_OP_MUL_MAT ? GGML_OP_ADD : GGML_OP_ADD_ID;
|
|
4053
3282
|
|
|
3283
|
+
if (op == GGML_OP_MUL_MAT) {
|
|
3284
|
+
for (const bool with_bias : { false, true }) {
|
|
3285
|
+
const int gate_idx = i;
|
|
3286
|
+
const int gate_scale_idx = i + 1;
|
|
3287
|
+
const int gate_bias_idx = with_bias ? i + 2 : -1;
|
|
3288
|
+
const int up_idx = with_bias ? i + 3 : i + 2;
|
|
3289
|
+
const int up_scale_idx = up_idx + 1;
|
|
3290
|
+
const int up_bias_idx = with_bias ? up_idx + 2 : -1;
|
|
3291
|
+
const int glu_idx = with_bias ? up_idx + 3 : up_idx + 2;
|
|
3292
|
+
|
|
3293
|
+
const int out_nodes[] = { glu_idx };
|
|
3294
|
+
ggml_op ops[7];
|
|
3295
|
+
if (with_bias) {
|
|
3296
|
+
ops[0] = op;
|
|
3297
|
+
ops[1] = GGML_OP_MUL;
|
|
3298
|
+
ops[2] = bias_op;
|
|
3299
|
+
ops[3] = op;
|
|
3300
|
+
ops[4] = GGML_OP_MUL;
|
|
3301
|
+
ops[5] = bias_op;
|
|
3302
|
+
ops[6] = GGML_OP_GLU;
|
|
3303
|
+
} else {
|
|
3304
|
+
ops[0] = op;
|
|
3305
|
+
ops[1] = GGML_OP_MUL;
|
|
3306
|
+
ops[2] = op;
|
|
3307
|
+
ops[3] = GGML_OP_MUL;
|
|
3308
|
+
ops[4] = GGML_OP_GLU;
|
|
3309
|
+
}
|
|
3310
|
+
const int n_ops = with_bias ? 7 : 5;
|
|
3311
|
+
|
|
3312
|
+
if (!ggml_can_fuse_subgraph(cgraph, i, n_ops, ops, out_nodes, 1) ||
|
|
3313
|
+
!ggml_cuda_check_fusion_memory_ranges(cgraph, i, n_ops, out_nodes, 1)) {
|
|
3314
|
+
continue;
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3317
|
+
ggml_tensor * gate_n = cgraph->nodes[gate_idx];
|
|
3318
|
+
ggml_tensor * gate_scale_n = cgraph->nodes[gate_scale_idx];
|
|
3319
|
+
ggml_tensor * gate_out_n = with_bias ? cgraph->nodes[gate_bias_idx] : gate_scale_n;
|
|
3320
|
+
ggml_tensor * up_n = cgraph->nodes[up_idx];
|
|
3321
|
+
ggml_tensor * up_scale_n = cgraph->nodes[up_scale_idx];
|
|
3322
|
+
ggml_tensor * up_out_n = with_bias ? cgraph->nodes[up_bias_idx] : up_scale_n;
|
|
3323
|
+
const ggml_tensor * glu = cgraph->nodes[glu_idx];
|
|
3324
|
+
|
|
3325
|
+
if (!ggml_cuda_should_fuse_mul_mat(up_n, gate_n, glu,
|
|
3326
|
+
with_bias ? up_out_n : nullptr, with_bias ? gate_out_n : nullptr, up_scale_n, gate_scale_n)) {
|
|
3327
|
+
continue;
|
|
3328
|
+
}
|
|
3329
|
+
|
|
3330
|
+
const ggml_tensor * gate_scale = get_mul_mat_scale(gate_scale_n, gate_n);
|
|
3331
|
+
const ggml_tensor * up_scale = get_mul_mat_scale(up_scale_n, up_n);
|
|
3332
|
+
if (!gate_scale || !up_scale) {
|
|
3333
|
+
continue;
|
|
3334
|
+
}
|
|
3335
|
+
|
|
3336
|
+
const ggml_tensor * up_bias = with_bias ? get_bias_tensor(up_out_n, up_scale_n, bias_op) : nullptr;
|
|
3337
|
+
const ggml_tensor * gate_bias = with_bias ? get_bias_tensor(gate_out_n, gate_scale_n, bias_op) : nullptr;
|
|
3338
|
+
if (with_bias && (!ggml_are_same_shape(gate_out_n->src[0], gate_out_n->src[1]) ||
|
|
3339
|
+
!ggml_are_same_shape(up_out_n->src[0], up_out_n->src[1]))) {
|
|
3340
|
+
continue;
|
|
3341
|
+
}
|
|
3342
|
+
|
|
3343
|
+
const ggml_tensor * src0 = up_n->src[0];
|
|
3344
|
+
const ggml_tensor * src1 = up_n->src[1];
|
|
3345
|
+
const ggml_tensor * ids = up_n->src[2];
|
|
3346
|
+
|
|
3347
|
+
ggml_cuda_mm_fusion_args_host fusion_data{};
|
|
3348
|
+
fusion_data.gate = gate_n->src[0];
|
|
3349
|
+
fusion_data.x_bias = up_bias;
|
|
3350
|
+
fusion_data.gate_bias = gate_bias;
|
|
3351
|
+
fusion_data.x_scale = up_scale;
|
|
3352
|
+
fusion_data.gate_scale = gate_scale;
|
|
3353
|
+
fusion_data.glu_op = ggml_get_glu_op(glu);
|
|
3354
|
+
|
|
3355
|
+
if (ggml_cuda_should_fuse_mul_mat_vec_q(up_n)) {
|
|
3356
|
+
ggml_cuda_mul_mat_vec_q(*cuda_ctx, src0, src1, ids, cgraph->nodes[glu_idx], &fusion_data);
|
|
3357
|
+
fused_mul_mat_vec = true;
|
|
3358
|
+
fused_node_count = n_ops;
|
|
3359
|
+
break;
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3363
|
+
if (fused_mul_mat_vec) {
|
|
3364
|
+
break;
|
|
3365
|
+
}
|
|
3366
|
+
} else {
|
|
3367
|
+
for (const bool with_bias : { false, true }) {
|
|
3368
|
+
const int gate_idx = i;
|
|
3369
|
+
const int gate_scale_idx = i + 4;
|
|
3370
|
+
const int gate_bias_idx = with_bias ? i + 5 : -1;
|
|
3371
|
+
const int up_idx = with_bias ? i + 6 : i + 5;
|
|
3372
|
+
const int up_scale_idx = up_idx + 4;
|
|
3373
|
+
const int up_bias_idx = with_bias ? up_idx + 5 : -1;
|
|
3374
|
+
const int glu_idx = with_bias ? up_idx + 6 : up_idx + 5;
|
|
3375
|
+
|
|
3376
|
+
const int out_nodes[] = { glu_idx };
|
|
3377
|
+
ggml_op ops[13];
|
|
3378
|
+
if (with_bias) {
|
|
3379
|
+
ops[0] = op;
|
|
3380
|
+
ops[1] = GGML_OP_RESHAPE;
|
|
3381
|
+
ops[2] = GGML_OP_REPEAT;
|
|
3382
|
+
ops[3] = GGML_OP_GET_ROWS;
|
|
3383
|
+
ops[4] = GGML_OP_MUL;
|
|
3384
|
+
ops[5] = bias_op;
|
|
3385
|
+
ops[6] = op;
|
|
3386
|
+
ops[7] = GGML_OP_RESHAPE;
|
|
3387
|
+
ops[8] = GGML_OP_REPEAT;
|
|
3388
|
+
ops[9] = GGML_OP_GET_ROWS;
|
|
3389
|
+
ops[10] = GGML_OP_MUL;
|
|
3390
|
+
ops[11] = bias_op;
|
|
3391
|
+
ops[12] = GGML_OP_GLU;
|
|
3392
|
+
} else {
|
|
3393
|
+
ops[0] = op;
|
|
3394
|
+
ops[1] = GGML_OP_RESHAPE;
|
|
3395
|
+
ops[2] = GGML_OP_REPEAT;
|
|
3396
|
+
ops[3] = GGML_OP_GET_ROWS;
|
|
3397
|
+
ops[4] = GGML_OP_MUL;
|
|
3398
|
+
ops[5] = op;
|
|
3399
|
+
ops[6] = GGML_OP_RESHAPE;
|
|
3400
|
+
ops[7] = GGML_OP_REPEAT;
|
|
3401
|
+
ops[8] = GGML_OP_GET_ROWS;
|
|
3402
|
+
ops[9] = GGML_OP_MUL;
|
|
3403
|
+
ops[10] = GGML_OP_GLU;
|
|
3404
|
+
}
|
|
3405
|
+
const int n_ops = with_bias ? 13 : 11;
|
|
3406
|
+
|
|
3407
|
+
if (!ggml_can_fuse_subgraph(cgraph, i, n_ops, ops, out_nodes, 1) ||
|
|
3408
|
+
!ggml_cuda_check_fusion_memory_ranges(cgraph, i, n_ops, out_nodes, 1)) {
|
|
3409
|
+
continue;
|
|
3410
|
+
}
|
|
3411
|
+
|
|
3412
|
+
ggml_tensor * gate_n = cgraph->nodes[gate_idx];
|
|
3413
|
+
ggml_tensor * gate_scale_n = cgraph->nodes[gate_scale_idx];
|
|
3414
|
+
ggml_tensor * gate_out_n = with_bias ? cgraph->nodes[gate_bias_idx] : gate_scale_n;
|
|
3415
|
+
ggml_tensor * up_n = cgraph->nodes[up_idx];
|
|
3416
|
+
ggml_tensor * up_scale_n = cgraph->nodes[up_scale_idx];
|
|
3417
|
+
ggml_tensor * up_out_n = with_bias ? cgraph->nodes[up_bias_idx] : up_scale_n;
|
|
3418
|
+
const ggml_tensor * glu = cgraph->nodes[glu_idx];
|
|
3419
|
+
|
|
3420
|
+
if (!ggml_cuda_should_fuse_mul_mat(up_n, gate_n, glu,
|
|
3421
|
+
with_bias ? up_out_n : nullptr, with_bias ? gate_out_n : nullptr, up_scale_n, gate_scale_n)) {
|
|
3422
|
+
continue;
|
|
3423
|
+
}
|
|
3424
|
+
|
|
3425
|
+
const ggml_tensor * gate_scale = get_mul_mat_id_scale(cgraph->nodes[gate_idx + 1], cgraph->nodes[gate_idx + 2],
|
|
3426
|
+
cgraph->nodes[gate_idx + 3], gate_scale_n, gate_n);
|
|
3427
|
+
const ggml_tensor * up_scale = get_mul_mat_id_scale(cgraph->nodes[up_idx + 1], cgraph->nodes[up_idx + 2],
|
|
3428
|
+
cgraph->nodes[up_idx + 3], up_scale_n, up_n);
|
|
3429
|
+
if (!gate_scale || !up_scale) {
|
|
3430
|
+
continue;
|
|
3431
|
+
}
|
|
3432
|
+
|
|
3433
|
+
const ggml_tensor * up_bias = with_bias ? get_bias_tensor(up_out_n, up_scale_n, bias_op) : nullptr;
|
|
3434
|
+
const ggml_tensor * gate_bias = with_bias ? get_bias_tensor(gate_out_n, gate_scale_n, bias_op) : nullptr;
|
|
3435
|
+
|
|
3436
|
+
const ggml_tensor * src0 = up_n->src[0];
|
|
3437
|
+
const ggml_tensor * src1 = up_n->src[1];
|
|
3438
|
+
const ggml_tensor * ids = up_n->src[2];
|
|
3439
|
+
|
|
3440
|
+
ggml_cuda_mm_fusion_args_host fusion_data{};
|
|
3441
|
+
fusion_data.gate = gate_n->src[0];
|
|
3442
|
+
fusion_data.x_bias = up_bias;
|
|
3443
|
+
fusion_data.gate_bias = gate_bias;
|
|
3444
|
+
fusion_data.x_scale = up_scale;
|
|
3445
|
+
fusion_data.gate_scale = gate_scale;
|
|
3446
|
+
fusion_data.glu_op = ggml_get_glu_op(glu);
|
|
3447
|
+
|
|
3448
|
+
if (ggml_cuda_should_fuse_mul_mat_vec_q(up_n)) {
|
|
3449
|
+
ggml_cuda_mul_mat_vec_q(*cuda_ctx, src0, src1, ids, cgraph->nodes[glu_idx], &fusion_data);
|
|
3450
|
+
fused_mul_mat_vec = true;
|
|
3451
|
+
fused_node_count = n_ops;
|
|
3452
|
+
break;
|
|
3453
|
+
}
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3456
|
+
if (fused_mul_mat_vec) {
|
|
3457
|
+
break;
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
|
|
4054
3461
|
if (ggml_cuda_can_fuse(cgraph, i, { op, bias_op, op, bias_op, GGML_OP_GLU }, {})) {
|
|
4055
3462
|
ggml_tensor * glu = cgraph->nodes[i + 4];
|
|
4056
3463
|
ggml_tensor * gate_bias_n = glu->src[0];
|
|
@@ -4070,23 +3477,8 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
|
|
|
4070
3477
|
continue;
|
|
4071
3478
|
}
|
|
4072
3479
|
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
if (bias_node->src[0] == mul_node) {
|
|
4076
|
-
return bias_node->src[1];
|
|
4077
|
-
}
|
|
4078
|
-
if (bias_node->src[1] == mul_node) {
|
|
4079
|
-
return bias_node->src[0];
|
|
4080
|
-
}
|
|
4081
|
-
return (ggml_tensor *) nullptr;
|
|
4082
|
-
}
|
|
4083
|
-
GGML_ASSERT(op_bias == GGML_OP_ADD_ID);
|
|
4084
|
-
GGML_ASSERT(bias_node->src[0] == mul_node);
|
|
4085
|
-
return bias_node->src[1];
|
|
4086
|
-
};
|
|
4087
|
-
|
|
4088
|
-
ggml_tensor * up_bias_tensor = get_bias_tensor(up_bias_n, up_n, bias_op);
|
|
4089
|
-
ggml_tensor * gate_bias_tensor = get_bias_tensor(gate_bias_n, gate_n, bias_op);
|
|
3480
|
+
const ggml_tensor * up_bias_tensor = get_bias_tensor(up_bias_n, up_n, bias_op);
|
|
3481
|
+
const ggml_tensor * gate_bias_tensor = get_bias_tensor(gate_bias_n, gate_n, bias_op);
|
|
4090
3482
|
|
|
4091
3483
|
if (!up_bias_tensor || !gate_bias_tensor) {
|
|
4092
3484
|
continue;
|
|
@@ -4174,7 +3566,95 @@ static int ggml_cuda_try_fuse(ggml_backend_cuda_context * cuda_ctx, ggml_cgraph
|
|
|
4174
3566
|
fused_mul_mat_vec = false;
|
|
4175
3567
|
fused_node_count = 0;
|
|
4176
3568
|
|
|
4177
|
-
//
|
|
3569
|
+
// mul_mat + scale + optional bias
|
|
3570
|
+
for (ggml_op op : { GGML_OP_MUL_MAT, GGML_OP_MUL_MAT_ID }) {
|
|
3571
|
+
const ggml_op bias_op = op == GGML_OP_MUL_MAT ? GGML_OP_ADD : GGML_OP_ADD_ID;
|
|
3572
|
+
|
|
3573
|
+
for (const bool with_bias : { false, true }) {
|
|
3574
|
+
const int n_ops = op == GGML_OP_MUL_MAT ? (with_bias ? 3 : 2) : (with_bias ? 6 : 5);
|
|
3575
|
+
const int out_nodes[] = { i + n_ops - 1 };
|
|
3576
|
+
ggml_op ops[6];
|
|
3577
|
+
if (op == GGML_OP_MUL_MAT) {
|
|
3578
|
+
if (with_bias) {
|
|
3579
|
+
ops[0] = op;
|
|
3580
|
+
ops[1] = GGML_OP_MUL;
|
|
3581
|
+
ops[2] = bias_op;
|
|
3582
|
+
} else {
|
|
3583
|
+
ops[0] = op;
|
|
3584
|
+
ops[1] = GGML_OP_MUL;
|
|
3585
|
+
}
|
|
3586
|
+
} else {
|
|
3587
|
+
if (with_bias) {
|
|
3588
|
+
ops[0] = op;
|
|
3589
|
+
ops[1] = GGML_OP_RESHAPE;
|
|
3590
|
+
ops[2] = GGML_OP_REPEAT;
|
|
3591
|
+
ops[3] = GGML_OP_GET_ROWS;
|
|
3592
|
+
ops[4] = GGML_OP_MUL;
|
|
3593
|
+
ops[5] = bias_op;
|
|
3594
|
+
} else {
|
|
3595
|
+
ops[0] = op;
|
|
3596
|
+
ops[1] = GGML_OP_RESHAPE;
|
|
3597
|
+
ops[2] = GGML_OP_REPEAT;
|
|
3598
|
+
ops[3] = GGML_OP_GET_ROWS;
|
|
3599
|
+
ops[4] = GGML_OP_MUL;
|
|
3600
|
+
}
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
if (!ggml_can_fuse_subgraph(cgraph, i, n_ops, ops, out_nodes, 1) ||
|
|
3604
|
+
!ggml_cuda_check_fusion_memory_ranges(cgraph, i, n_ops, out_nodes, 1)) {
|
|
3605
|
+
continue;
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
ggml_tensor * mm_node = cgraph->nodes[i];
|
|
3609
|
+
ggml_tensor * scale_node = op == GGML_OP_MUL_MAT ? cgraph->nodes[i + 1] : cgraph->nodes[i + 4];
|
|
3610
|
+
ggml_tensor * out_node = with_bias ? cgraph->nodes[i + n_ops - 1] : scale_node;
|
|
3611
|
+
|
|
3612
|
+
const ggml_tensor * scale = nullptr;
|
|
3613
|
+
if (op == GGML_OP_MUL_MAT) {
|
|
3614
|
+
scale = get_mul_mat_scale(scale_node, mm_node);
|
|
3615
|
+
} else {
|
|
3616
|
+
scale = get_mul_mat_id_scale(cgraph->nodes[i + 1], cgraph->nodes[i + 2], cgraph->nodes[i + 3], scale_node, mm_node);
|
|
3617
|
+
}
|
|
3618
|
+
if (!scale) {
|
|
3619
|
+
continue;
|
|
3620
|
+
}
|
|
3621
|
+
|
|
3622
|
+
const ggml_tensor * bias = with_bias ? get_bias_tensor(out_node, scale_node, bias_op) : nullptr;
|
|
3623
|
+
if (with_bias && !bias) {
|
|
3624
|
+
continue;
|
|
3625
|
+
}
|
|
3626
|
+
if (with_bias && bias_op == GGML_OP_ADD && !ggml_are_same_shape(out_node->src[0], out_node->src[1])) {
|
|
3627
|
+
continue;
|
|
3628
|
+
}
|
|
3629
|
+
if (with_bias && bias_op == GGML_OP_ADD_ID && out_node->src[2] != mm_node->src[2]) {
|
|
3630
|
+
continue;
|
|
3631
|
+
}
|
|
3632
|
+
|
|
3633
|
+
const ggml_tensor * src0 = mm_node->src[0];
|
|
3634
|
+
const ggml_tensor * src1 = mm_node->src[1];
|
|
3635
|
+
const ggml_tensor * ids = mm_node->src[2];
|
|
3636
|
+
|
|
3637
|
+
ggml_cuda_mm_fusion_args_host fusion_data{};
|
|
3638
|
+
fusion_data.x_bias = bias;
|
|
3639
|
+
fusion_data.x_scale = scale;
|
|
3640
|
+
|
|
3641
|
+
if (ggml_cuda_should_fuse_mul_mat_vec_q(mm_node)) {
|
|
3642
|
+
ggml_cuda_mul_mat_vec_q(*cuda_ctx, src0, src1, ids, out_node, &fusion_data);
|
|
3643
|
+
fused_mul_mat_vec = true;
|
|
3644
|
+
fused_node_count = n_ops;
|
|
3645
|
+
break;
|
|
3646
|
+
}
|
|
3647
|
+
}
|
|
3648
|
+
if (fused_mul_mat_vec) {
|
|
3649
|
+
break;
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
|
|
3653
|
+
if (fused_mul_mat_vec) {
|
|
3654
|
+
return fused_node_count - 1;
|
|
3655
|
+
}
|
|
3656
|
+
|
|
3657
|
+
// mul_mat + add
|
|
4178
3658
|
for (ggml_op op : { GGML_OP_MUL_MAT, GGML_OP_MUL_MAT_ID }) {
|
|
4179
3659
|
const ggml_op bias_op = op == GGML_OP_MUL_MAT ? GGML_OP_ADD : GGML_OP_ADD_ID;
|
|
4180
3660
|
|
|
@@ -4405,15 +3885,9 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
|
|
|
4405
3885
|
}
|
|
4406
3886
|
}
|
|
4407
3887
|
|
|
4408
|
-
#ifdef GGML_CUDA_DEBUG
|
|
4409
|
-
const int nodes_fused = i - prev_i - 1;
|
|
4410
|
-
if (nodes_fused > 0) {
|
|
4411
|
-
GGML_LOG_INFO("nodes_fused: %d\n", nodes_fused);
|
|
4412
|
-
}
|
|
4413
|
-
#endif
|
|
4414
3888
|
prev_i = i;
|
|
4415
3889
|
|
|
4416
|
-
if (
|
|
3890
|
+
if (ggml_cuda_is_view_or_noop(node)) {
|
|
4417
3891
|
continue;
|
|
4418
3892
|
}
|
|
4419
3893
|
|
|
@@ -4424,6 +3898,12 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
|
|
|
4424
3898
|
int nodes_to_skip = ggml_cuda_try_fuse(cuda_ctx, cgraph, i);
|
|
4425
3899
|
|
|
4426
3900
|
if (nodes_to_skip != 0) {
|
|
3901
|
+
#ifdef GGML_CUDA_DEBUG
|
|
3902
|
+
const int last_fused = i + nodes_to_skip;
|
|
3903
|
+
GGML_LOG_INFO("nodes_fused: %d, first: %s (%s), last: %s (%s)\n",
|
|
3904
|
+
nodes_to_skip + 1, ggml_op_name(node->op), node->name,
|
|
3905
|
+
ggml_op_name(cgraph->nodes[last_fused]->op), cgraph->nodes[last_fused]->name);
|
|
3906
|
+
#endif
|
|
4427
3907
|
i += nodes_to_skip;
|
|
4428
3908
|
continue;
|
|
4429
3909
|
}
|
|
@@ -4433,7 +3913,7 @@ static void ggml_cuda_graph_evaluate_and_capture(ggml_backend_cuda_context * cud
|
|
|
4433
3913
|
if (node->src[j] != nullptr) {
|
|
4434
3914
|
assert(node->src[j]->buffer);
|
|
4435
3915
|
assert(node->src[j]->buffer->buft == ggml_backend_cuda_buffer_type(cuda_ctx->device) ||
|
|
4436
|
-
|
|
3916
|
+
(integrated && ggml_backend_buft_is_cuda_host(node->src[j]->buffer->buft)));
|
|
4437
3917
|
}
|
|
4438
3918
|
}
|
|
4439
3919
|
#else
|
|
@@ -4916,6 +4396,14 @@ void ggml_backend_cuda_unregister_host_buffer(void * buffer) {
|
|
|
4916
4396
|
|
|
4917
4397
|
// backend device
|
|
4918
4398
|
|
|
4399
|
+
struct ggml_backend_cuda_device_context {
|
|
4400
|
+
int device;
|
|
4401
|
+
std::string name;
|
|
4402
|
+
std::string description;
|
|
4403
|
+
std::string pci_bus_id;
|
|
4404
|
+
int op_offload_min_batch_size;
|
|
4405
|
+
};
|
|
4406
|
+
|
|
4919
4407
|
static const char * ggml_backend_cuda_device_get_name(ggml_backend_dev_t dev) {
|
|
4920
4408
|
ggml_backend_cuda_device_context * ctx = (ggml_backend_cuda_device_context *)dev->context;
|
|
4921
4409
|
return ctx->name.c_str();
|
|
@@ -5004,11 +4492,6 @@ static bool ggml_backend_cuda_get_available_uma_memory(long * available_memory_k
|
|
|
5004
4492
|
|
|
5005
4493
|
static void ggml_backend_cuda_device_get_memory(ggml_backend_dev_t dev, size_t * free, size_t * total) {
|
|
5006
4494
|
ggml_backend_cuda_device_context * ctx = (ggml_backend_cuda_device_context *)dev->context;
|
|
5007
|
-
|
|
5008
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
5009
|
-
std::lock_guard<std::mutex> lock(ctx->device_mutex);
|
|
5010
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
5011
|
-
|
|
5012
4495
|
ggml_cuda_set_device(ctx->device);
|
|
5013
4496
|
CUDA_CHECK(cudaMemGetInfo(free, total));
|
|
5014
4497
|
|
|
@@ -5035,13 +4518,6 @@ static void ggml_backend_cuda_device_get_memory(ggml_backend_dev_t dev, size_t *
|
|
|
5035
4518
|
}
|
|
5036
4519
|
#endif // defined(__linux__)
|
|
5037
4520
|
|
|
5038
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
5039
|
-
// If no backends or buffers are active, the cudaMemGetInfo call above lazily created a CUDA
|
|
5040
|
-
// context that permanently consumes VRAM. Reset the device to free it.
|
|
5041
|
-
if (ctx->active_count == 0) {
|
|
5042
|
-
CUDA_CHECK(cudaDeviceReset());
|
|
5043
|
-
}
|
|
5044
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
5045
4521
|
}
|
|
5046
4522
|
|
|
5047
4523
|
static enum ggml_backend_dev_type ggml_backend_cuda_device_get_type(ggml_backend_dev_t dev) {
|
|
@@ -5099,15 +4575,6 @@ static ggml_backend_buffer_type_t ggml_backend_cuda_device_get_host_buffer_type(
|
|
|
5099
4575
|
static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const ggml_tensor * op) {
|
|
5100
4576
|
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) dev->context;
|
|
5101
4577
|
|
|
5102
|
-
// split buffers can only be used with GGML_OP_MUL_MAT
|
|
5103
|
-
if (op->op != GGML_OP_MUL_MAT) {
|
|
5104
|
-
for (int i = 0; i < GGML_MAX_SRC; i++) {
|
|
5105
|
-
if (op->src[i] && op->src[i]->buffer && ggml_backend_buft_is_cuda_split(op->src[i]->buffer->buft)) {
|
|
5106
|
-
return false;
|
|
5107
|
-
}
|
|
5108
|
-
}
|
|
5109
|
-
}
|
|
5110
|
-
|
|
5111
4578
|
// check if all the sources are allocated on this device
|
|
5112
4579
|
for (int i = 0; i < GGML_MAX_SRC; i++) {
|
|
5113
4580
|
if (op->src[i] && op->src[i]->buffer && ggml_backend_buft_is_cuda(op->src[i]->buffer->buft)) {
|
|
@@ -5168,19 +4635,8 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5168
4635
|
{
|
|
5169
4636
|
struct ggml_tensor * a = op->src[0];
|
|
5170
4637
|
struct ggml_tensor * b = op->src[1];
|
|
5171
|
-
if (a->
|
|
5172
|
-
|
|
5173
|
-
return false;
|
|
5174
|
-
}
|
|
5175
|
-
// for small weight matrices the active device can end up without any rows, don't use row split in those cases
|
|
5176
|
-
// this avoids some edge cases (and the performance would not be good anyways)
|
|
5177
|
-
ggml_backend_cuda_split_buffer_type_context * buft_ctx = (ggml_backend_cuda_split_buffer_type_context *) a->buffer->buft->context;
|
|
5178
|
-
int64_t row_low;
|
|
5179
|
-
int64_t row_high;
|
|
5180
|
-
get_row_split(&row_low, &row_high, a, buft_ctx->tensor_split, dev_ctx->device);
|
|
5181
|
-
if (row_low == row_high) {
|
|
5182
|
-
return false;
|
|
5183
|
-
}
|
|
4638
|
+
if (a->nb[0] != ggml_element_size(a) || b->nb[0] != ggml_element_size(b)) {
|
|
4639
|
+
return false; // TODO this could in principle be implemented though currently there is no use case.
|
|
5184
4640
|
}
|
|
5185
4641
|
if (b->type == GGML_TYPE_F16 && a->type != GGML_TYPE_F16) {
|
|
5186
4642
|
return false;
|
|
@@ -5256,10 +4712,16 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5256
4712
|
} break;
|
|
5257
4713
|
case GGML_OP_SET_ROWS:
|
|
5258
4714
|
{
|
|
5259
|
-
return (
|
|
5260
|
-
|
|
5261
|
-
|
|
5262
|
-
|
|
4715
|
+
return (
|
|
4716
|
+
(
|
|
4717
|
+
(op->type == GGML_TYPE_F32 || op->type == GGML_TYPE_F16 || op->type == GGML_TYPE_BF16 ||
|
|
4718
|
+
op->type == GGML_TYPE_Q4_0 || op->type == GGML_TYPE_Q4_1 || op->type == GGML_TYPE_Q5_0 ||
|
|
4719
|
+
op->type == GGML_TYPE_Q5_1 || op->type == GGML_TYPE_Q8_0 || op->type == GGML_TYPE_IQ4_NL) &&
|
|
4720
|
+
op->src[0]->type == GGML_TYPE_F32
|
|
4721
|
+
) || (
|
|
4722
|
+
op->type == GGML_TYPE_F16 && op->src[0]->type == GGML_TYPE_F16
|
|
4723
|
+
)
|
|
4724
|
+
) &&
|
|
5263
4725
|
(op->src[1]->type == GGML_TYPE_I64 || op->src[1]->type == GGML_TYPE_I32);
|
|
5264
4726
|
} break;
|
|
5265
4727
|
case GGML_OP_SET:
|
|
@@ -5337,8 +4799,9 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5337
4799
|
} break;
|
|
5338
4800
|
case GGML_OP_REPEAT:
|
|
5339
4801
|
{
|
|
4802
|
+
// the CUDA REPEAT path only implements F32/F16; other types assert at runtime
|
|
5340
4803
|
ggml_type src0_type = op->src[0]->type;
|
|
5341
|
-
return src0_type
|
|
4804
|
+
return src0_type == GGML_TYPE_F32 || src0_type == GGML_TYPE_F16;
|
|
5342
4805
|
} break;
|
|
5343
4806
|
case GGML_OP_REPEAT_BACK:
|
|
5344
4807
|
return op->type == GGML_TYPE_F32 && (op->src[0]->ne[2]*op->src[0]->ne[3]) <= (1 << 15);
|
|
@@ -5348,12 +4811,24 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5348
4811
|
ggml_type src1_type = op->src[1]->type;
|
|
5349
4812
|
return src0_type == src1_type &&
|
|
5350
4813
|
src0_type == op->type &&
|
|
5351
|
-
|
|
5352
|
-
|
|
5353
|
-
|
|
5354
|
-
|
|
5355
|
-
|
|
5356
|
-
|
|
4814
|
+
(
|
|
4815
|
+
(
|
|
4816
|
+
ggml_is_quantized(src0_type) &&
|
|
4817
|
+
ggml_is_contiguous(op->src[0]) &&
|
|
4818
|
+
ggml_is_contiguous(op->src[1]) &&
|
|
4819
|
+
op->src[0]->ne[0] % ggml_blck_size(src0_type) == 0 &&
|
|
4820
|
+
op->src[1]->ne[0] % ggml_blck_size(src0_type) == 0
|
|
4821
|
+
) || (
|
|
4822
|
+
!ggml_is_quantized(src0_type) &&
|
|
4823
|
+
ggml_blck_size(src0_type) == 1 &&
|
|
4824
|
+
(
|
|
4825
|
+
ggml_type_size(src0_type) == 1 ||
|
|
4826
|
+
ggml_type_size(src0_type) == 2 ||
|
|
4827
|
+
ggml_type_size(src0_type) == 4 ||
|
|
4828
|
+
ggml_type_size(src0_type) == 8
|
|
4829
|
+
)
|
|
4830
|
+
)
|
|
4831
|
+
);
|
|
5357
4832
|
} break;
|
|
5358
4833
|
case GGML_OP_CONV_TRANSPOSE_1D:
|
|
5359
4834
|
{
|
|
@@ -5364,13 +4839,21 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5364
4839
|
}
|
|
5365
4840
|
return false;
|
|
5366
4841
|
} break;
|
|
4842
|
+
case GGML_OP_COL2IM_1D:
|
|
4843
|
+
{
|
|
4844
|
+
ggml_type src0_type = op->src[0]->type;
|
|
4845
|
+
return (src0_type == GGML_TYPE_F32 || src0_type == GGML_TYPE_F16 || src0_type == GGML_TYPE_BF16) &&
|
|
4846
|
+
op->type == src0_type &&
|
|
4847
|
+
ggml_is_contiguous(op->src[0]) &&
|
|
4848
|
+
ggml_is_contiguous(op);
|
|
4849
|
+
} break;
|
|
5367
4850
|
case GGML_OP_SILU_BACK:
|
|
5368
4851
|
return ggml_is_contiguous(op->src[0]) && op->src[0]->type == GGML_TYPE_F32;
|
|
5369
4852
|
break;
|
|
5370
4853
|
case GGML_OP_NORM:
|
|
5371
4854
|
case GGML_OP_RMS_NORM:
|
|
5372
4855
|
case GGML_OP_L2_NORM:
|
|
5373
|
-
return
|
|
4856
|
+
return ggml_is_contiguous_rows(op->src[0]);
|
|
5374
4857
|
case GGML_OP_RMS_NORM_BACK:
|
|
5375
4858
|
return ggml_is_contiguous(op->src[0]);
|
|
5376
4859
|
break;
|
|
@@ -5434,7 +4917,9 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5434
4917
|
case GGML_OP_IM2COL:
|
|
5435
4918
|
case GGML_OP_IM2COL_3D:
|
|
5436
4919
|
case GGML_OP_CONV_2D:
|
|
4920
|
+
return true;
|
|
5437
4921
|
case GGML_OP_CONV_2D_DW:
|
|
4922
|
+
return op->src[0]->type == GGML_TYPE_F32;
|
|
5438
4923
|
case GGML_OP_CONV_TRANSPOSE_2D:
|
|
5439
4924
|
case GGML_OP_POOL_2D:
|
|
5440
4925
|
return true;
|
|
@@ -5494,7 +4979,7 @@ static bool ggml_backend_cuda_device_supports_op(ggml_backend_dev_t dev, const g
|
|
|
5494
4979
|
static bool ggml_backend_cuda_device_supports_buft(ggml_backend_dev_t dev, ggml_backend_buffer_type_t buft) {
|
|
5495
4980
|
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) dev->context;
|
|
5496
4981
|
const bool integrated = ggml_cuda_info().devices[dev_ctx->device].integrated;
|
|
5497
|
-
return (
|
|
4982
|
+
return (ggml_backend_buft_is_cuda(buft) && buft->device == dev) || (integrated && ggml_backend_buft_is_cuda_host(buft));
|
|
5498
4983
|
}
|
|
5499
4984
|
|
|
5500
4985
|
static int64_t get_op_batch_size(const ggml_tensor * op) {
|
|
@@ -5618,10 +5103,6 @@ static ggml_backend_feature * ggml_backend_cuda_get_features(ggml_backend_reg_t
|
|
|
5618
5103
|
features.push_back({ "USE_GRAPHS", "1" });
|
|
5619
5104
|
#endif
|
|
5620
5105
|
|
|
5621
|
-
#ifdef GGML_CUDA_PEER_MAX_BATCH_SIZE
|
|
5622
|
-
features.push_back({ "PEER_MAX_BATCH_SIZE", STRINGIFY(GGML_CUDA_PEER_MAX_BATCH_SIZE) });
|
|
5623
|
-
#endif
|
|
5624
|
-
|
|
5625
5106
|
#ifdef GGML_CUDA_FA_ALL_QUANTS
|
|
5626
5107
|
features.push_back({ "FA_ALL_QUANTS", "1" });
|
|
5627
5108
|
#endif
|
|
@@ -5660,9 +5141,6 @@ static void * ggml_backend_cuda_reg_get_proc_address(ggml_backend_reg_t reg, con
|
|
|
5660
5141
|
if (strcmp(name, "ggml_backend_comm_allreduce_tensor") == 0) {
|
|
5661
5142
|
return (void *)ggml_backend_cuda_comm_allreduce_tensor;
|
|
5662
5143
|
}
|
|
5663
|
-
if (strcmp(name, "ggml_backend_split_buffer_type") == 0) {
|
|
5664
|
-
return (void *)ggml_backend_cuda_split_buffer_type;
|
|
5665
|
-
}
|
|
5666
5144
|
if (strcmp(name, "ggml_backend_register_host_buffer") == 0) {
|
|
5667
5145
|
return (void *)ggml_backend_cuda_register_host_buffer;
|
|
5668
5146
|
}
|
|
@@ -5744,21 +5222,13 @@ ggml_backend_t ggml_backend_cuda_init(int device) {
|
|
|
5744
5222
|
return nullptr;
|
|
5745
5223
|
}
|
|
5746
5224
|
|
|
5747
|
-
ggml_backend_dev_t dev = ggml_backend_reg_dev_get(ggml_backend_cuda_reg(), device);
|
|
5748
|
-
|
|
5749
5225
|
ggml_backend_t cuda_backend = new ggml_backend {
|
|
5750
5226
|
/* .guid = */ ggml_backend_cuda_guid(),
|
|
5751
5227
|
/* .iface = */ ggml_backend_cuda_interface,
|
|
5752
|
-
/* .device = */
|
|
5228
|
+
/* .device = */ ggml_backend_reg_dev_get(ggml_backend_cuda_reg(), device),
|
|
5753
5229
|
/* .context = */ ctx,
|
|
5754
5230
|
};
|
|
5755
5231
|
|
|
5756
|
-
#if !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
5757
|
-
ggml_backend_cuda_device_context * dev_ctx = (ggml_backend_cuda_device_context *) dev->context;
|
|
5758
|
-
std::lock_guard<std::mutex> lock(dev_ctx->device_mutex);
|
|
5759
|
-
dev_ctx->active_count++;
|
|
5760
|
-
#endif // !defined(GGML_USE_HIP) && !defined(GGML_USE_MUSA)
|
|
5761
|
-
|
|
5762
5232
|
return cuda_backend;
|
|
5763
5233
|
}
|
|
5764
5234
|
|