cohere-transcribe 0.1.0
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 +7 -0
- data/CHANGELOG.md +21 -0
- data/LICENSE.txt +201 -0
- data/NOTICE +5 -0
- data/README.md +265 -0
- data/THIRD_PARTY_NOTICES.md +67 -0
- data/exe/cohere-transcribe +8 -0
- data/exe/cohere-transcribe-doctor +8 -0
- data/ext/cohere_transcribe_native/CMakeLists.txt +262 -0
- data/ext/cohere_transcribe_native/README.md +26 -0
- data/ext/cohere_transcribe_native/audio_abi.cpp +1416 -0
- data/ext/cohere_transcribe_native/audio_exports.macos +5 -0
- data/ext/cohere_transcribe_native/audio_exports.map +10 -0
- data/ext/cohere_transcribe_native/cohere_abi.cpp +1209 -0
- data/ext/cohere_transcribe_native/exports.macos +40 -0
- data/ext/cohere_transcribe_native/exports.map +45 -0
- data/ext/cohere_transcribe_native/extconf.rb +89 -0
- data/ext/cohere_transcribe_native/test/abi_smoke.rb +232 -0
- data/ext/cohere_transcribe_native/test/audio_matrix_smoke.cpp +121 -0
- data/ext/cohere_transcribe_native/test/audio_reliability_smoke.cpp +198 -0
- data/ext/cohere_transcribe_native/test/native_abi_reliability_smoke.cpp +186 -0
- data/ext/cohere_transcribe_native/test/native_batch_projection_probe.rb +81 -0
- data/ext/cohere_transcribe_native/test/native_cancellation_smoke.cpp +194 -0
- data/lib/cohere/transcribe/alignment/ATTRIBUTION.md +23 -0
- data/lib/cohere/transcribe/alignment/LICENSE.ctc-forced-aligner +407 -0
- data/lib/cohere/transcribe/alignment/LICENSE.torchaudio +25 -0
- data/lib/cohere/transcribe/alignment/LICENSE.uroman +26 -0
- data/lib/cohere/transcribe/alignment/aligner.rb +476 -0
- data/lib/cohere/transcribe/alignment/ctc.rb +224 -0
- data/lib/cohere/transcribe/alignment/text.rb +237 -0
- data/lib/cohere/transcribe/alignment/uroman_data.rb +4950 -0
- data/lib/cohere/transcribe/api.rb +173 -0
- data/lib/cohere/transcribe/asr/batching.rb +472 -0
- data/lib/cohere/transcribe/asr/failure_policy.rb +112 -0
- data/lib/cohere/transcribe/asr/native.rb +676 -0
- data/lib/cohere/transcribe/audio/ATTRIBUTION.md +8 -0
- data/lib/cohere/transcribe/audio/LICENSE.auditok +21 -0
- data/lib/cohere/transcribe/audio/decoder.rb +315 -0
- data/lib/cohere/transcribe/audio/ffmpeg_native.rb +248 -0
- data/lib/cohere/transcribe/audio/segmentation.rb +260 -0
- data/lib/cohere/transcribe/cli.rb +727 -0
- data/lib/cohere/transcribe/configuration.rb +282 -0
- data/lib/cohere/transcribe/constants.rb +14 -0
- data/lib/cohere/transcribe/dense_converter.rb +548 -0
- data/lib/cohere/transcribe/doctor.rb +576 -0
- data/lib/cohere/transcribe/errors.rb +57 -0
- data/lib/cohere/transcribe/gguf_writer.rb +268 -0
- data/lib/cohere/transcribe/hub.rb +436 -0
- data/lib/cohere/transcribe/input.rb +110 -0
- data/lib/cohere/transcribe/licenses/crispasr.txt +21 -0
- data/lib/cohere/transcribe/loader.rb +128 -0
- data/lib/cohere/transcribe/model_identity.rb +440 -0
- data/lib/cohere/transcribe/output/publication.rb +1118 -0
- data/lib/cohere/transcribe/output/rendering.rb +105 -0
- data/lib/cohere/transcribe/output/timing.rb +86 -0
- data/lib/cohere/transcribe/python_text.rb +70 -0
- data/lib/cohere/transcribe/pytorch_checkpoint.rb +1180 -0
- data/lib/cohere/transcribe/runtime/engine.rb +1676 -0
- data/lib/cohere/transcribe/runtime/model_provider.rb +390 -0
- data/lib/cohere/transcribe/runtime/precision.rb +57 -0
- data/lib/cohere/transcribe/runtime/preparation.rb +215 -0
- data/lib/cohere/transcribe/runtime/resources.rb +165 -0
- data/lib/cohere/transcribe/runtime/word_pipeline.rb +364 -0
- data/lib/cohere/transcribe/safetensors.rb +579 -0
- data/lib/cohere/transcribe/state/checkpoint.rb +224 -0
- data/lib/cohere/transcribe/state/contracts.rb +141 -0
- data/lib/cohere/transcribe/state/io.rb +727 -0
- data/lib/cohere/transcribe/state/locking.rb +211 -0
- data/lib/cohere/transcribe/state/manifest.rb +155 -0
- data/lib/cohere/transcribe/state.rb +7 -0
- data/lib/cohere/transcribe/types.rb +535 -0
- data/lib/cohere/transcribe/vad/ATTRIBUTION.md +14 -0
- data/lib/cohere/transcribe/vad/LICENSE.faster-whisper +21 -0
- data/lib/cohere/transcribe/vad/LICENSE.silero-vad +21 -0
- data/lib/cohere/transcribe/vad/silero.rb +344 -0
- data/lib/cohere/transcribe/vad/silero_vad_v6.onnx +0 -0
- data/lib/cohere/transcribe/vad/timestamps.rb +219 -0
- data/lib/cohere/transcribe/version.rb +7 -0
- data/lib/cohere/transcribe.rb +26 -0
- data/sig/cohere/transcribe.rbs +250 -0
- data/vendor/crispasr/AUTHORS +510 -0
- data/vendor/crispasr/LICENSE +21 -0
- data/vendor/crispasr/UPSTREAM.md +9 -0
- data/vendor/crispasr/VERSION +1 -0
- data/vendor/crispasr/ggml/AUTHORS +335 -0
- data/vendor/crispasr/ggml/CMakeLists.txt +512 -0
- data/vendor/crispasr/ggml/LICENSE +21 -0
- data/vendor/crispasr/ggml/README.md +49 -0
- data/vendor/crispasr/ggml/cmake/FindNCCL.cmake +36 -0
- data/vendor/crispasr/ggml/cmake/GitVars.cmake +22 -0
- data/vendor/crispasr/ggml/cmake/common.cmake +50 -0
- data/vendor/crispasr/ggml/cmake/ggml-config.cmake.in +191 -0
- data/vendor/crispasr/ggml/ggml.pc.in +10 -0
- data/vendor/crispasr/ggml/include/ggml-alloc.h +85 -0
- data/vendor/crispasr/ggml/include/ggml-backend.h +431 -0
- data/vendor/crispasr/ggml/include/ggml-blas.h +25 -0
- data/vendor/crispasr/ggml/include/ggml-cann.h +123 -0
- data/vendor/crispasr/ggml/include/ggml-cpp.h +39 -0
- data/vendor/crispasr/ggml/include/ggml-cpu.h +151 -0
- data/vendor/crispasr/ggml/include/ggml-cuda.h +50 -0
- data/vendor/crispasr/ggml/include/ggml-hexagon.h +19 -0
- data/vendor/crispasr/ggml/include/ggml-metal.h +61 -0
- data/vendor/crispasr/ggml/include/ggml-opencl.h +26 -0
- data/vendor/crispasr/ggml/include/ggml-openvino.h +37 -0
- data/vendor/crispasr/ggml/include/ggml-opt.h +256 -0
- data/vendor/crispasr/ggml/include/ggml-rpc.h +35 -0
- data/vendor/crispasr/ggml/include/ggml-sycl.h +49 -0
- data/vendor/crispasr/ggml/include/ggml-virtgpu.h +14 -0
- data/vendor/crispasr/ggml/include/ggml-vulkan.h +29 -0
- data/vendor/crispasr/ggml/include/ggml-webgpu.h +19 -0
- data/vendor/crispasr/ggml/include/ggml-zdnn.h +17 -0
- data/vendor/crispasr/ggml/include/ggml-zendnn.h +22 -0
- data/vendor/crispasr/ggml/include/ggml.h +2887 -0
- data/vendor/crispasr/ggml/include/gguf.h +204 -0
- data/vendor/crispasr/ggml/src/CMakeLists.txt +493 -0
- data/vendor/crispasr/ggml/src/ggml-alloc.c +1323 -0
- data/vendor/crispasr/ggml/src/ggml-backend-dl.cpp +48 -0
- data/vendor/crispasr/ggml/src/ggml-backend-dl.h +44 -0
- data/vendor/crispasr/ggml/src/ggml-backend-impl.h +275 -0
- data/vendor/crispasr/ggml/src/ggml-backend-meta.cpp +2145 -0
- data/vendor/crispasr/ggml/src/ggml-backend-reg.cpp +586 -0
- data/vendor/crispasr/ggml/src/ggml-backend.cpp +2437 -0
- data/vendor/crispasr/ggml/src/ggml-common.h +1900 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/CMakeLists.txt +718 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/amx/amx.cpp +249 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/amx/amx.h +8 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/amx/common.h +115 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/amx/mmq.cpp +2512 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/amx/mmq.h +10 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/arm/cpu-feats.cpp +98 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/arm/quants.c +4244 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/arm/repack.cpp +5156 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/loongarch/quants.c +2158 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/powerpc/cpu-feats.cpp +82 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/powerpc/quants.c +2304 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/riscv/cpu-feats.cpp +38 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/riscv/quants.c +4455 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/riscv/repack.cpp +1703 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/s390/cpu-feats.cpp +50 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/s390/quants.c +1465 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/wasm/quants.c +1220 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/x86/cpu-feats.cpp +327 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/x86/quants.c +3970 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch/x86/repack.cpp +6407 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/arch-fallback.h +349 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/binary-ops.cpp +154 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/binary-ops.h +16 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/cmake/FindSIMD.cmake +100 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/common.h +95 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/ggml-cpu-impl.h +539 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/ggml-cpu.c +3791 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/ggml-cpu.cpp +703 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/hbm.cpp +55 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/hbm.h +8 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kernels.cpp +939 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kernels.h +90 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kleidiai.cpp +1513 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/kleidiai/kleidiai.h +17 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/llamafile/sgemm.cpp +4051 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/llamafile/sgemm.h +25 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/ops.cpp +11662 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/ops.h +121 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/quants.c +1288 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/quants.h +103 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/repack.cpp +4836 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/repack.h +245 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/simd-gemm.h +226 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/simd-mappings.h +1329 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime.cpp +1025 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime.h +13 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime1_kernels.cpp +3196 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/spacemit/ime_kernels.h +26 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/traits.cpp +36 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/traits.h +38 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/unary-ops.cpp +336 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/unary-ops.h +35 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/vec.cpp +681 -0
- data/vendor/crispasr/ggml/src/ggml-cpu/vec.h +1606 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/CMakeLists.txt +272 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/acc.cu +61 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/acc.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/add-id.cu +58 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/add-id.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/arange.cu +34 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/arange.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/argmax.cu +91 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/argmax.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/argsort.cu +265 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/argsort.cuh +19 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/binbcast.cu +534 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/binbcast.cuh +12 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/clamp.cu +45 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/clamp.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/col2im-1d.cu +81 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/col2im-1d.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/common.cuh +1489 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/concat.cu +204 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/concat.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv-transpose-1d.cu +97 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv-transpose-1d.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-dw.cu +161 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-dw.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-transpose.cu +115 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv2d-transpose.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv2d.cu +166 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/conv2d.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/convert.cu +892 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/convert.cuh +66 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/count-equal.cu +64 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/count-equal.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cp-async.cuh +57 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cpy-utils.cuh +217 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cpy.cu +581 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cpy.cuh +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cross-entropy-loss.cu +177 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cross-entropy-loss.cuh +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cumsum.cu +307 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/cumsum.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/dequantize.cuh +99 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/diag.cu +77 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/diag.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/diagmask.cu +40 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/diagmask.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-common.cuh +1212 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-mma-f16.cuh +1860 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-tile.cu +57 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-tile.cuh +1309 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-vec.cuh +600 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-wmma-f16.cu +696 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn-wmma-f16.cuh +51 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn.cu +620 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fattn.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fill.cu +37 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/fill.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/gated_delta_net.cu +273 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/gated_delta_net.cuh +4 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/getrows.cu +332 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/getrows.cuh +15 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/ggml-cuda.cu +5580 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/gla.cu +93 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/gla.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/im2col.cu +274 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/im2col.cuh +6 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mean.cu +75 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mean.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mma.cuh +1333 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmf.cu +191 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmf.cuh +908 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmid.cu +164 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmid.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmq.cu +372 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmq.cuh +4175 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmvf.cu +862 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmvf.cuh +14 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmvq.cu +1161 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/mmvq.cuh +16 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/norm.cu +756 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/norm.cuh +20 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-adamw.cu +78 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-adamw.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-sgd.cu +49 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/opt-step-sgd.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/out-prod.cu +68 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/out-prod.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/pad.cu +106 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/pad.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/pad_reflect_1d.cu +91 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/pad_reflect_1d.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/pool2d.cu +94 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/pool2d.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/quantize.cu +443 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/quantize.cuh +41 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/reduce_rows.cuh +39 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/roll.cu +67 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/roll.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/rope.cu +665 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/rope.cuh +9 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/scale.cu +34 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/scale.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/set-rows.cu +330 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/set-rows.cuh +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/set.cu +39 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/set.cuh +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/softcap.cu +34 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/softcap.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/softmax.cu +472 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/softmax.cuh +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/solve_tri.cu +275 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/solve_tri.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/ssm-conv.cu +197 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/ssm-conv.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/ssm-scan.cu +342 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/ssm-scan.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/sum.cu +41 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/sum.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/sumrows.cu +43 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/sumrows.cuh +4 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_16.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_32.cu +6 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_1-ncols2_8.cu +11 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_1.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_2.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_16-ncols2_4.cu +12 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_16.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_32.cu +6 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_4.cu +12 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_2-ncols2_8.cu +11 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_1.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_32-ncols2_2.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_16.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_2.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_4.cu +12 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_4-ncols2_8.cu +11 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_64-ncols2_1.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_1.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_2.cu +10 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_4.cu +12 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-mma-f16-instance-ncols1_8-ncols2_8.cu +11 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq112-dv112.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq128-dv128.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq256-dv256.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq320-dv256.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq40-dv40.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq512-dv512.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq576-dv512.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq64-dv64.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq72-dv72.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq80-dv80.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-tile-instance-dkq96-dv96.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-bf16-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-f16-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_0-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q4_1-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_0-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q5_1-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-bf16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-f16.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q4_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q4_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q5_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q5_1.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/fattn-vec-instance-q8_0-q8_0.cu +7 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_1.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_10.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_11.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_12.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_13.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_14.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_15.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_16.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_2.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_3.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_4.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_5.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_6.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_7.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_8.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmf-instance-ncols_9.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq1_s.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_s.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xs.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq2_xxs.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_s.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq3_xxs.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_nl.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-iq4_xs.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-mxfp4.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-nvfp4.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q1_0.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q2_k.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q3_k.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_0.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_1.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q4_k.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_0.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_1.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q5_k.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q6_k.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/template-instances/mmq-instance-q8_0.cu +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/top-k.cu +95 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/top-k.cuh +3 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/topk-moe.cu +415 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/topk-moe.cuh +27 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/tri.cu +136 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/tri.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/tsembd.cu +47 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/tsembd.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/unary.cu +644 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/unary.cuh +116 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/upscale.cu +293 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/upscale.cuh +5 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/vecdotq.cuh +1317 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/vendors/cuda.h +28 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/vendors/hip.h +306 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/vendors/musa.h +148 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/wkv.cu +199 -0
- data/vendor/crispasr/ggml/src/ggml-cuda/wkv.cuh +7 -0
- data/vendor/crispasr/ggml/src/ggml-impl.h +783 -0
- data/vendor/crispasr/ggml/src/ggml-metal/CMakeLists.txt +124 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-common.cpp +457 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-common.h +52 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-context.h +41 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-context.m +778 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-device.cpp +2117 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-device.h +299 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-device.m +2093 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-impl.h +1267 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-ops.cpp +5023 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal-ops.h +111 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal.cpp +954 -0
- data/vendor/crispasr/ggml/src/ggml-metal/ggml-metal.metal +11756 -0
- data/vendor/crispasr/ggml/src/ggml-opt.cpp +1094 -0
- data/vendor/crispasr/ggml/src/ggml-quants.c +5491 -0
- data/vendor/crispasr/ggml/src/ggml-quants.h +112 -0
- data/vendor/crispasr/ggml/src/ggml-threading.cpp +12 -0
- data/vendor/crispasr/ggml/src/ggml-threading.h +14 -0
- data/vendor/crispasr/ggml/src/ggml.c +7925 -0
- data/vendor/crispasr/ggml/src/ggml.cpp +26 -0
- data/vendor/crispasr/ggml/src/gguf.cpp +1556 -0
- data/vendor/crispasr/src/cohere-arch.h +137 -0
- data/vendor/crispasr/src/cohere.cpp +5642 -0
- data/vendor/crispasr/src/cohere.h +327 -0
- data/vendor/crispasr/src/cohere_batch_planner.h +82 -0
- data/vendor/crispasr/src/cohere_chunking.h +64 -0
- data/vendor/crispasr/src/cohere_decoder_batch_layout.h +60 -0
- data/vendor/crispasr/src/cohere_encoder_padded_layout.h +27 -0
- data/vendor/crispasr/src/cohere_frontend.cpp +189 -0
- data/vendor/crispasr/src/cohere_frontend.h +31 -0
- data/vendor/crispasr/src/cohere_ragged_controller.h +149 -0
- data/vendor/crispasr/src/cohere_token_renderer.h +181 -0
- data/vendor/crispasr/src/core/attention.h +924 -0
- data/vendor/crispasr/src/core/audio_chunking.h +97 -0
- data/vendor/crispasr/src/core/beam_decode.h +486 -0
- data/vendor/crispasr/src/core/cpu_ops.h +135 -0
- data/vendor/crispasr/src/core/gguf_loader.cpp +1021 -0
- data/vendor/crispasr/src/core/gguf_loader.h +216 -0
- data/vendor/crispasr/src/core/gpu_backend_pref.h +119 -0
- data/vendor/crispasr/src/core/mel.cpp +519 -0
- data/vendor/crispasr/src/core/mel.h +265 -0
- data/vendor/crispasr/src/core/ngram_loop_fix.h +173 -0
- data/vendor/crispasr/src/core/repetition_loop_guard.h +54 -0
- data/vendor/crispasr/src/crispasr_imatrix.cpp +255 -0
- data/vendor/crispasr/src/crispasr_imatrix.h +38 -0
- metadata +596 -0
|
@@ -0,0 +1,1021 @@
|
|
|
1
|
+
// src/core/gguf_loader.cpp — implementation of core_gguf:: helpers.
|
|
2
|
+
// See gguf_loader.h for the interface contract.
|
|
3
|
+
|
|
4
|
+
#include "gguf_loader.h"
|
|
5
|
+
|
|
6
|
+
#include "ggml-backend-impl.h"
|
|
7
|
+
#include "ggml-cpu.h"
|
|
8
|
+
#ifdef GGML_USE_METAL
|
|
9
|
+
#include "ggml-metal.h"
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#include <cerrno>
|
|
13
|
+
#include <cstdarg>
|
|
14
|
+
#include <cstdio>
|
|
15
|
+
#include <cstdlib>
|
|
16
|
+
#include <cstring>
|
|
17
|
+
#include <map>
|
|
18
|
+
#include <mutex>
|
|
19
|
+
|
|
20
|
+
#if defined(_WIN32)
|
|
21
|
+
#include <io.h>
|
|
22
|
+
#ifndef NOMINMAX
|
|
23
|
+
#define NOMINMAX
|
|
24
|
+
#endif
|
|
25
|
+
#include <windows.h>
|
|
26
|
+
#else
|
|
27
|
+
#include <fcntl.h>
|
|
28
|
+
#include <sys/mman.h>
|
|
29
|
+
#include <sys/stat.h>
|
|
30
|
+
#include <unistd.h>
|
|
31
|
+
#endif
|
|
32
|
+
|
|
33
|
+
namespace core_gguf {
|
|
34
|
+
|
|
35
|
+
// ---------------------------------------------------------------------------
|
|
36
|
+
// Pass 1: metadata
|
|
37
|
+
// ---------------------------------------------------------------------------
|
|
38
|
+
|
|
39
|
+
gguf_context* open_metadata(const char* path) {
|
|
40
|
+
gguf_init_params gp = {/*.no_alloc=*/true, /*.ctx=*/nullptr};
|
|
41
|
+
gguf_context* g = gguf_init_from_file(path, gp);
|
|
42
|
+
if (!g) {
|
|
43
|
+
fprintf(stderr, "core_gguf: failed to open '%s' for metadata read\n", path);
|
|
44
|
+
}
|
|
45
|
+
return g;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void free_metadata(gguf_context* gctx) {
|
|
49
|
+
if (gctx)
|
|
50
|
+
gguf_free(gctx);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Type-checked scalar readers. The GGUF format stores types explicitly so
|
|
54
|
+
// we can validate; if the file has a mismatched type the reader silently
|
|
55
|
+
// returns the default rather than crashing, matching the existing inline
|
|
56
|
+
// helpers in each model.
|
|
57
|
+
|
|
58
|
+
uint32_t kv_u32(gguf_context* gctx, const char* key, uint32_t default_val) {
|
|
59
|
+
const int k = gguf_find_key(gctx, key);
|
|
60
|
+
if (k < 0)
|
|
61
|
+
return default_val;
|
|
62
|
+
const gguf_type t = gguf_get_kv_type(gctx, k);
|
|
63
|
+
switch (t) {
|
|
64
|
+
case GGUF_TYPE_UINT32:
|
|
65
|
+
return gguf_get_val_u32(gctx, k);
|
|
66
|
+
case GGUF_TYPE_INT32:
|
|
67
|
+
return (uint32_t)gguf_get_val_i32(gctx, k);
|
|
68
|
+
case GGUF_TYPE_UINT64:
|
|
69
|
+
return (uint32_t)gguf_get_val_u64(gctx, k);
|
|
70
|
+
case GGUF_TYPE_INT64:
|
|
71
|
+
return (uint32_t)gguf_get_val_i64(gctx, k);
|
|
72
|
+
case GGUF_TYPE_UINT16:
|
|
73
|
+
return gguf_get_val_u16(gctx, k);
|
|
74
|
+
case GGUF_TYPE_INT16:
|
|
75
|
+
return (uint32_t)gguf_get_val_i16(gctx, k);
|
|
76
|
+
case GGUF_TYPE_UINT8:
|
|
77
|
+
return gguf_get_val_u8(gctx, k);
|
|
78
|
+
case GGUF_TYPE_INT8:
|
|
79
|
+
return (uint32_t)gguf_get_val_i8(gctx, k);
|
|
80
|
+
default:
|
|
81
|
+
return default_val;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
int32_t kv_i32(gguf_context* gctx, const char* key, int32_t default_val) {
|
|
86
|
+
const int k = gguf_find_key(gctx, key);
|
|
87
|
+
if (k < 0)
|
|
88
|
+
return default_val;
|
|
89
|
+
const gguf_type t = gguf_get_kv_type(gctx, k);
|
|
90
|
+
switch (t) {
|
|
91
|
+
case GGUF_TYPE_INT32:
|
|
92
|
+
return gguf_get_val_i32(gctx, k);
|
|
93
|
+
case GGUF_TYPE_UINT32:
|
|
94
|
+
return (int32_t)gguf_get_val_u32(gctx, k);
|
|
95
|
+
case GGUF_TYPE_INT64:
|
|
96
|
+
return (int32_t)gguf_get_val_i64(gctx, k);
|
|
97
|
+
case GGUF_TYPE_UINT64:
|
|
98
|
+
return (int32_t)gguf_get_val_u64(gctx, k);
|
|
99
|
+
default:
|
|
100
|
+
return default_val;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
float kv_f32(gguf_context* gctx, const char* key, float default_val) {
|
|
105
|
+
const int k = gguf_find_key(gctx, key);
|
|
106
|
+
if (k < 0)
|
|
107
|
+
return default_val;
|
|
108
|
+
const gguf_type t = gguf_get_kv_type(gctx, k);
|
|
109
|
+
if (t == GGUF_TYPE_FLOAT32)
|
|
110
|
+
return gguf_get_val_f32(gctx, k);
|
|
111
|
+
if (t == GGUF_TYPE_FLOAT64)
|
|
112
|
+
return (float)gguf_get_val_f64(gctx, k);
|
|
113
|
+
return default_val;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
bool kv_bool(gguf_context* gctx, const char* key, bool default_val) {
|
|
117
|
+
const int k = gguf_find_key(gctx, key);
|
|
118
|
+
if (k < 0)
|
|
119
|
+
return default_val;
|
|
120
|
+
if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_BOOL)
|
|
121
|
+
return default_val;
|
|
122
|
+
return gguf_get_val_bool(gctx, k);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
std::string kv_str(gguf_context* gctx, const char* key, const char* default_val) {
|
|
126
|
+
const int k = gguf_find_key(gctx, key);
|
|
127
|
+
if (k < 0)
|
|
128
|
+
return default_val ? default_val : "";
|
|
129
|
+
if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_STRING)
|
|
130
|
+
return default_val ? default_val : "";
|
|
131
|
+
const char* s = gguf_get_val_str(gctx, k);
|
|
132
|
+
return s ? std::string(s) : std::string(default_val ? default_val : "");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
std::vector<std::string> kv_str_array(gguf_context* gctx, const char* key) {
|
|
136
|
+
std::vector<std::string> out;
|
|
137
|
+
const int k = gguf_find_key(gctx, key);
|
|
138
|
+
if (k < 0)
|
|
139
|
+
return out;
|
|
140
|
+
if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_ARRAY)
|
|
141
|
+
return out;
|
|
142
|
+
if (gguf_get_arr_type(gctx, k) != GGUF_TYPE_STRING)
|
|
143
|
+
return out;
|
|
144
|
+
const int n = gguf_get_arr_n(gctx, k);
|
|
145
|
+
out.reserve((size_t)n);
|
|
146
|
+
for (int i = 0; i < n; i++) {
|
|
147
|
+
out.emplace_back(gguf_get_arr_str(gctx, k, i));
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
std::vector<float> kv_f32_array(gguf_context* gctx, const char* key) {
|
|
153
|
+
std::vector<float> out;
|
|
154
|
+
const int k = gguf_find_key(gctx, key);
|
|
155
|
+
if (k < 0)
|
|
156
|
+
return out;
|
|
157
|
+
if (gguf_get_kv_type(gctx, k) != GGUF_TYPE_ARRAY)
|
|
158
|
+
return out;
|
|
159
|
+
if (gguf_get_arr_type(gctx, k) != GGUF_TYPE_FLOAT32)
|
|
160
|
+
return out;
|
|
161
|
+
const size_t n = gguf_get_arr_n(gctx, k);
|
|
162
|
+
const float* data = (const float*)gguf_get_arr_data(gctx, k);
|
|
163
|
+
out.assign(data, data + n);
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
// Pass 2: tensor allocation + weight data copy.
|
|
169
|
+
// ---------------------------------------------------------------------------
|
|
170
|
+
|
|
171
|
+
namespace {
|
|
172
|
+
|
|
173
|
+
// Read a file slice into a backend tensor. Uses mmap on POSIX; falls back
|
|
174
|
+
// to pread/lseek+read when mmap is unavailable (rare in practice).
|
|
175
|
+
//
|
|
176
|
+
// On POSIX the mmap lives for the duration of one load call — we copy via
|
|
177
|
+
// ggml_backend_tensor_set then unmap. No mmap persists past load_weights().
|
|
178
|
+
struct MappedFile {
|
|
179
|
+
int fd = -1;
|
|
180
|
+
void* base = nullptr;
|
|
181
|
+
size_t size = 0;
|
|
182
|
+
bool ok = false;
|
|
183
|
+
|
|
184
|
+
// When `writable` is true, the mapping is created with copy-on-write
|
|
185
|
+
// semantics (POSIX MAP_PRIVATE + PROT_READ|PROT_WRITE / Win32
|
|
186
|
+
// FILE_MAP_COPY). Reads share the file's page cache; writes get a
|
|
187
|
+
// private anonymous duplicate of the touched page. This lets backends
|
|
188
|
+
// that mutate weights post-load (e.g. parakeet's BN-into-conv fold) run
|
|
189
|
+
// unchanged on the zero-copy path without modifying the underlying file.
|
|
190
|
+
explicit MappedFile(const char* path, bool writable = false) {
|
|
191
|
+
#if defined(_WIN32)
|
|
192
|
+
const DWORD page_protect = writable ? PAGE_WRITECOPY : PAGE_READONLY;
|
|
193
|
+
const DWORD view_access = writable ? FILE_MAP_COPY : FILE_MAP_READ;
|
|
194
|
+
HANDLE hFile = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr);
|
|
195
|
+
if (hFile == INVALID_HANDLE_VALUE)
|
|
196
|
+
return;
|
|
197
|
+
LARGE_INTEGER fsize;
|
|
198
|
+
if (!GetFileSizeEx(hFile, &fsize)) {
|
|
199
|
+
CloseHandle(hFile);
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
size = (size_t)fsize.QuadPart;
|
|
203
|
+
HANDLE hMap = CreateFileMappingA(hFile, nullptr, page_protect, 0, 0, nullptr);
|
|
204
|
+
CloseHandle(hFile);
|
|
205
|
+
if (!hMap)
|
|
206
|
+
return;
|
|
207
|
+
base = MapViewOfFile(hMap, view_access, 0, 0, 0);
|
|
208
|
+
CloseHandle(hMap);
|
|
209
|
+
if (!base)
|
|
210
|
+
return;
|
|
211
|
+
ok = true;
|
|
212
|
+
#else
|
|
213
|
+
fd = ::open(path, O_RDONLY);
|
|
214
|
+
if (fd < 0)
|
|
215
|
+
return;
|
|
216
|
+
struct stat st;
|
|
217
|
+
if (fstat(fd, &st) != 0) {
|
|
218
|
+
::close(fd);
|
|
219
|
+
fd = -1;
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
size = (size_t)st.st_size;
|
|
223
|
+
const int prot = writable ? (PROT_READ | PROT_WRITE) : PROT_READ;
|
|
224
|
+
const int flags = writable ? MAP_PRIVATE : MAP_SHARED;
|
|
225
|
+
base = ::mmap(nullptr, size, prot, flags, fd, 0);
|
|
226
|
+
::close(fd);
|
|
227
|
+
fd = -1;
|
|
228
|
+
if (base == MAP_FAILED) {
|
|
229
|
+
base = nullptr;
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
ok = true;
|
|
233
|
+
#endif
|
|
234
|
+
}
|
|
235
|
+
~MappedFile() {
|
|
236
|
+
#if defined(_WIN32)
|
|
237
|
+
if (base)
|
|
238
|
+
UnmapViewOfFile(base);
|
|
239
|
+
#else
|
|
240
|
+
if (base)
|
|
241
|
+
::munmap(base, size);
|
|
242
|
+
#endif
|
|
243
|
+
}
|
|
244
|
+
MappedFile(const MappedFile&) = delete;
|
|
245
|
+
MappedFile& operator=(const MappedFile&) = delete;
|
|
246
|
+
|
|
247
|
+
// Transfer ownership of the mmap region out of the RAII handle so it
|
|
248
|
+
// outlives the destructor. Used by the CRISPASR_GGUF_MMAP=1 path to
|
|
249
|
+
// hand the mapping to a backend buffer that owns it for the model's
|
|
250
|
+
// lifetime.
|
|
251
|
+
void release() {
|
|
252
|
+
base = nullptr;
|
|
253
|
+
size = 0;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
|
|
257
|
+
// PLAN #51a: a CPU backend buffer whose backing memory is an mmap'd file
|
|
258
|
+
// region. On free_buffer the mapping is unmapped — that's the entire
|
|
259
|
+
// reason this buffer type exists. Tensors must be bound with
|
|
260
|
+
// ggml_backend_tensor_alloc(); we do not provide an init_tensor path.
|
|
261
|
+
//
|
|
262
|
+
// We reuse ggml_backend_cpu_buffer_type() so ggml_backend_buffer_is_host()
|
|
263
|
+
// returns true on this buffer (some scheduler paths key off that).
|
|
264
|
+
struct mmap_buffer_ctx {
|
|
265
|
+
void* mmap_base = nullptr; // page-aligned start of the mmap
|
|
266
|
+
size_t mmap_size = 0; // length of the mmap
|
|
267
|
+
void* tensor_base = nullptr; // mmap_base + data_off, 32-byte aligned
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
static void* mmap_buffer_get_base(ggml_backend_buffer_t buffer) {
|
|
271
|
+
GGML_ASSERT(buffer);
|
|
272
|
+
return ((mmap_buffer_ctx*)buffer->context)->tensor_base;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
static void mmap_buffer_free(ggml_backend_buffer_t buffer) {
|
|
276
|
+
GGML_ASSERT(buffer);
|
|
277
|
+
auto* mctx = (mmap_buffer_ctx*)buffer->context;
|
|
278
|
+
if (mctx->mmap_base) {
|
|
279
|
+
#if defined(_WIN32)
|
|
280
|
+
UnmapViewOfFile(mctx->mmap_base);
|
|
281
|
+
#else
|
|
282
|
+
::munmap(mctx->mmap_base, mctx->mmap_size);
|
|
283
|
+
#endif
|
|
284
|
+
}
|
|
285
|
+
delete mctx;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
static void mmap_buffer_memset_tensor(ggml_backend_buffer_t buffer, ggml_tensor* tensor, uint8_t value, size_t offset,
|
|
289
|
+
size_t size) {
|
|
290
|
+
GGML_ASSERT(tensor);
|
|
291
|
+
memset((char*)tensor->data + offset, value, size);
|
|
292
|
+
GGML_UNUSED(buffer);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
static void mmap_buffer_set_tensor(ggml_backend_buffer_t buffer, ggml_tensor* tensor, const void* data, size_t offset,
|
|
296
|
+
size_t size) {
|
|
297
|
+
GGML_ASSERT(tensor);
|
|
298
|
+
memcpy((char*)tensor->data + offset, data, size);
|
|
299
|
+
GGML_UNUSED(buffer);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
static void mmap_buffer_get_tensor(ggml_backend_buffer_t buffer, const ggml_tensor* tensor, void* data, size_t offset,
|
|
303
|
+
size_t size) {
|
|
304
|
+
GGML_ASSERT(tensor);
|
|
305
|
+
memcpy(data, (const char*)tensor->data + offset, size);
|
|
306
|
+
GGML_UNUSED(buffer);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
static bool mmap_buffer_cpy_tensor(ggml_backend_buffer_t buffer, const ggml_tensor* src, ggml_tensor* dst) {
|
|
310
|
+
GGML_ASSERT(src);
|
|
311
|
+
if (ggml_backend_buffer_is_host(src->buffer)) {
|
|
312
|
+
memcpy(dst->data, src->data, ggml_nbytes(src));
|
|
313
|
+
return true;
|
|
314
|
+
}
|
|
315
|
+
return false;
|
|
316
|
+
GGML_UNUSED(buffer);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
static void mmap_buffer_clear(ggml_backend_buffer_t buffer, uint8_t value) {
|
|
320
|
+
auto* mctx = (mmap_buffer_ctx*)buffer->context;
|
|
321
|
+
memset(mctx->tensor_base, value, buffer->size);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
static const ggml_backend_buffer_i mmap_buffer_iface = {
|
|
325
|
+
/* .free_buffer = */ mmap_buffer_free,
|
|
326
|
+
/* .get_base = */ mmap_buffer_get_base,
|
|
327
|
+
/* .init_tensor = */ nullptr,
|
|
328
|
+
/* .memset_tensor = */ mmap_buffer_memset_tensor,
|
|
329
|
+
/* .set_tensor = */ mmap_buffer_set_tensor,
|
|
330
|
+
/* .get_tensor = */ mmap_buffer_get_tensor,
|
|
331
|
+
/* .set_tensor_2d = */ nullptr,
|
|
332
|
+
/* .get_tensor_2d = */ nullptr,
|
|
333
|
+
/* .cpy_tensor = */ mmap_buffer_cpy_tensor,
|
|
334
|
+
/* .clear = */ mmap_buffer_clear,
|
|
335
|
+
/* .reset = */ nullptr,
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// PLAN #51a (Metal variant): non-CPU backends use `buffer_from_host_ptr`
|
|
339
|
+
// to wrap our mmap region directly into a backend buffer (e.g. an
|
|
340
|
+
// MTLResourceStorageModeShared MTLBuffer on Apple-Silicon Metal). We
|
|
341
|
+
// CANNOT wrap that inner buffer with our own iface to attach a munmap
|
|
342
|
+
// callback: ggml-metal pierces the iface abstraction and casts
|
|
343
|
+
// `buffer->context` straight to its private `ggml_metal_buffer_t` (see
|
|
344
|
+
// `ggml_metal_get_buffer_id` in ggml-metal-context.m), so any wrapper
|
|
345
|
+
// makes Metal read garbage and emit "tensor 'X' buffer is nil" for
|
|
346
|
+
// every weight — the kokoro Metal gibberish-audio regression.
|
|
347
|
+
//
|
|
348
|
+
// Instead we hand the inner buffer back as-is and track the mmap region
|
|
349
|
+
// in this static side-map. When the buffer is freed elsewhere (model
|
|
350
|
+
// shutdown) the inner backend's free callback releases its device-side
|
|
351
|
+
// reference, but the host mmap stays mapped — Metal's
|
|
352
|
+
// `newBufferWithBytesNoCopy:options:deallocator:nil` doesn't own the
|
|
353
|
+
// host pages, so there's no MTLBuffer-side teardown that could munmap.
|
|
354
|
+
// We deliberately leak the mmap; on macOS the kernel can still evict
|
|
355
|
+
// file-backed pages under pressure (they're not anonymous), and process
|
|
356
|
+
// exit reclaims everything. Address-space-wise this costs nothing past
|
|
357
|
+
// the model's working set, which we'd be holding anyway.
|
|
358
|
+
struct gpu_mmap_handle {
|
|
359
|
+
void* base = nullptr;
|
|
360
|
+
size_t size = 0;
|
|
361
|
+
};
|
|
362
|
+
static std::mutex g_gpu_mmap_mu;
|
|
363
|
+
static std::map<ggml_backend_buffer_t, gpu_mmap_handle> g_gpu_mmap;
|
|
364
|
+
|
|
365
|
+
static void register_gpu_mmap(ggml_backend_buffer_t buf, void* base, size_t size) {
|
|
366
|
+
std::lock_guard<std::mutex> lk(g_gpu_mmap_mu);
|
|
367
|
+
g_gpu_mmap[buf] = {base, size};
|
|
368
|
+
}
|
|
369
|
+
static gpu_mmap_handle lookup_gpu_mmap(ggml_backend_buffer_t buf) {
|
|
370
|
+
std::lock_guard<std::mutex> lk(g_gpu_mmap_mu);
|
|
371
|
+
auto it = g_gpu_mmap.find(buf);
|
|
372
|
+
return it != g_gpu_mmap.end() ? it->second : gpu_mmap_handle{};
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// Issue #94 (chatterbox-turbo segfault during init on macOS / Apple
|
|
376
|
+
// Silicon): the legacy alloc+copy load path takes 30-60 s for the
|
|
377
|
+
// chatterbox-turbo T3 (658 MB Q8_0) on slow disks and reproducibly
|
|
378
|
+
// fails for some users. The zero-copy mmap path completes the same
|
|
379
|
+
// load in ~5-10 s and uses half the peak RSS. The CPU mmap path has
|
|
380
|
+
// been validated for every backend that goes through this loader
|
|
381
|
+
// (mimo-asr, voxtral, voxtral4b, chatterbox base + turbo, kokoro,
|
|
382
|
+
// qwen3-tts, vibevoice, parakeet, granite, …) since the PLAN #51a
|
|
383
|
+
// rollout in late April; flipping the default after a month of opt-in
|
|
384
|
+
// testing matches llama.cpp's behaviour and resolves the slow-load
|
|
385
|
+
// reports.
|
|
386
|
+
//
|
|
387
|
+
// Opt out with `CRISPASR_GGUF_MMAP=0` for users whose model files live
|
|
388
|
+
// on volumes that may disappear mid-run (network mounts, removable
|
|
389
|
+
// disks); mmap-backed weights SIGBUS if the underlying file vanishes.
|
|
390
|
+
static bool mmap_loader_enabled() {
|
|
391
|
+
const char* v = std::getenv("CRISPASR_GGUF_MMAP");
|
|
392
|
+
if (!v || !*v)
|
|
393
|
+
return true;
|
|
394
|
+
return *v != '0';
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
// PLAN #60c: opt-in preload — page-walk the entire mmap region so every
|
|
398
|
+
// page is resident before we return. Trades cold-start *load* time for
|
|
399
|
+
// cold-start *prefill* time; useful for benchmarking and for users with
|
|
400
|
+
// enough RAM to keep the working set resident. POSIX path uses a 1-byte
|
|
401
|
+
// volatile read per page; Linux MADV_POPULATE_READ would be a cleaner
|
|
402
|
+
// single-syscall version when available.
|
|
403
|
+
static bool preload_enabled() {
|
|
404
|
+
const char* v = std::getenv("CRISPASR_GGUF_PRELOAD");
|
|
405
|
+
return v && *v && *v != '0';
|
|
406
|
+
}
|
|
407
|
+
static void preload_pages(void* base, size_t size) {
|
|
408
|
+
#if !defined(_WIN32)
|
|
409
|
+
const long pg = sysconf(_SC_PAGESIZE);
|
|
410
|
+
if (pg <= 0)
|
|
411
|
+
return;
|
|
412
|
+
volatile const unsigned char* p = (const unsigned char*)base;
|
|
413
|
+
size_t touched = 0;
|
|
414
|
+
for (size_t off = 0; off < size; off += (size_t)pg) {
|
|
415
|
+
(void)p[off];
|
|
416
|
+
touched++;
|
|
417
|
+
}
|
|
418
|
+
(void)touched;
|
|
419
|
+
#else
|
|
420
|
+
(void)base;
|
|
421
|
+
(void)size;
|
|
422
|
+
#endif
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
// PLAN #60f: opt-in mlock — pin the mmap region in physical RAM so the
|
|
426
|
+
// kernel can't evict pages under memory pressure. Risky on RAM-tight
|
|
427
|
+
// hosts (a 16 GB model on a 16 GB box would starve the rest of the
|
|
428
|
+
// system). Useful as opt-in for users with comfortable headroom (32+
|
|
429
|
+
// GB). Failure (typically RLIMIT_MEMLOCK exceeded) prints a warning
|
|
430
|
+
// and continues — mmap'd weights still work, just without the pin.
|
|
431
|
+
static bool mlock_enabled() {
|
|
432
|
+
const char* v = std::getenv("CRISPASR_MLOCK");
|
|
433
|
+
return v && *v && *v != '0';
|
|
434
|
+
}
|
|
435
|
+
static void try_mlock(const char* tag, void* base, size_t size) {
|
|
436
|
+
#if !defined(_WIN32)
|
|
437
|
+
if (::mlock(base, size) != 0) {
|
|
438
|
+
fprintf(stderr,
|
|
439
|
+
"%s: mlock(%zu MiB) failed (errno=%d) — pages may still be evicted under "
|
|
440
|
+
"memory pressure. Raise RLIMIT_MEMLOCK (`ulimit -l unlimited`) if you want "
|
|
441
|
+
"the pin to take effect.\n",
|
|
442
|
+
tag, size / (1024 * 1024), errno);
|
|
443
|
+
}
|
|
444
|
+
#else
|
|
445
|
+
(void)tag;
|
|
446
|
+
(void)base;
|
|
447
|
+
(void)size;
|
|
448
|
+
#endif
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
} // namespace
|
|
452
|
+
|
|
453
|
+
bool load_weights(const char* path, ggml_backend_t backend, const char* model_tag, WeightLoad& out) {
|
|
454
|
+
const char* tag = model_tag ? model_tag : "core_gguf";
|
|
455
|
+
|
|
456
|
+
gguf_init_params gp = {/*.no_alloc=*/true, /*.ctx=*/&out.ctx};
|
|
457
|
+
gguf_context* gctx = gguf_init_from_file(path, gp);
|
|
458
|
+
if (!gctx || !out.ctx) {
|
|
459
|
+
fprintf(stderr, "%s: failed to load tensor metadata from '%s'\n", tag, path);
|
|
460
|
+
if (gctx)
|
|
461
|
+
gguf_free(gctx);
|
|
462
|
+
return false;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// PLAN #51a: zero-copy CPU path. Skip ggml_backend_alloc_ctx_tensors
|
|
466
|
+
// (which would allocate a fresh backend-side buffer) and instead bind
|
|
467
|
+
// each tensor directly into the mmap'd file. Saves one full copy of
|
|
468
|
+
// the weights — the difference between a 14.9 GB F16 GGUF loading on
|
|
469
|
+
// a 16 GB Mac and thrashing swap. Default-on as of issue #94 (slow /
|
|
470
|
+
// failing chatterbox-turbo load on macOS); opt out with
|
|
471
|
+
// `CRISPASR_GGUF_MMAP=0`.
|
|
472
|
+
if (mmap_loader_enabled() && ggml_backend_is_cpu(backend)) {
|
|
473
|
+
MappedFile mf(path, /*writable=*/true);
|
|
474
|
+
if (mf.ok) {
|
|
475
|
+
const size_t data_off = gguf_get_data_offset(gctx);
|
|
476
|
+
const size_t mmap_size = mf.size;
|
|
477
|
+
char* tensor_base = (char*)mf.base + data_off;
|
|
478
|
+
const size_t buf_size = mmap_size > data_off ? (mmap_size - data_off) : 0;
|
|
479
|
+
|
|
480
|
+
auto* mctx = new mmap_buffer_ctx{};
|
|
481
|
+
mctx->mmap_base = mf.base;
|
|
482
|
+
mctx->mmap_size = mmap_size;
|
|
483
|
+
mctx->tensor_base = tensor_base;
|
|
484
|
+
mf.release();
|
|
485
|
+
// Hint kernel to start async readahead of the entire weight
|
|
486
|
+
// region. Without this we hit a synchronous page fault on every
|
|
487
|
+
// first access during prefill (~5-10 ms each on the 99%-full
|
|
488
|
+
// external disk we hit during PLAN #51c F16 testing). Mirrors
|
|
489
|
+
// llama.cpp's `llama_mmap` populate path.
|
|
490
|
+
#if !defined(_WIN32)
|
|
491
|
+
::posix_madvise(mctx->mmap_base, mctx->mmap_size, POSIX_MADV_WILLNEED);
|
|
492
|
+
#endif
|
|
493
|
+
// PLAN #60c / #60f: optional preload + mlock, opt-in via env.
|
|
494
|
+
if (preload_enabled())
|
|
495
|
+
preload_pages(mctx->mmap_base, mctx->mmap_size);
|
|
496
|
+
if (mlock_enabled())
|
|
497
|
+
try_mlock(tag, mctx->mmap_base, mctx->mmap_size);
|
|
498
|
+
|
|
499
|
+
out.buf = ggml_backend_buffer_init(ggml_backend_cpu_buffer_type(), mmap_buffer_iface, mctx, buf_size);
|
|
500
|
+
if (!out.buf) {
|
|
501
|
+
fprintf(stderr, "%s: failed to wrap mmap in backend buffer\n", tag);
|
|
502
|
+
#if defined(_WIN32)
|
|
503
|
+
UnmapViewOfFile(mctx->mmap_base);
|
|
504
|
+
#else
|
|
505
|
+
::munmap(mctx->mmap_base, mctx->mmap_size);
|
|
506
|
+
#endif
|
|
507
|
+
delete mctx;
|
|
508
|
+
gguf_free(gctx);
|
|
509
|
+
ggml_free(out.ctx);
|
|
510
|
+
out.ctx = nullptr;
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
// Pre-validate tensor bounds before calling ggml_backend_tensor_alloc,
|
|
515
|
+
// which fires a hard GGML_ASSERT when any tensor's range exceeds
|
|
516
|
+
// buf_size. Seen on macOS 26.x Tahoe (issue #94) — likely a
|
|
517
|
+
// mismatched or truncated GGUF file. Detect it here and fall back
|
|
518
|
+
// gracefully to the legacy alloc+copy path instead of crashing.
|
|
519
|
+
bool bounds_ok = true;
|
|
520
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
521
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
522
|
+
if (tid < 0)
|
|
523
|
+
continue;
|
|
524
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
525
|
+
if (off + ggml_nbytes(t) > buf_size) {
|
|
526
|
+
fprintf(stderr,
|
|
527
|
+
"%s: mmap bounds check failed for tensor '%s' "
|
|
528
|
+
"(off=%zu + nbytes=%zu > buf_size=%zu) — "
|
|
529
|
+
"falling back to legacy loader\n",
|
|
530
|
+
tag, ggml_get_name(t), off, ggml_nbytes(t), buf_size);
|
|
531
|
+
bounds_ok = false;
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
if (bounds_ok) {
|
|
536
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
537
|
+
out.tensors[ggml_get_name(t)] = t;
|
|
538
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
539
|
+
if (tid < 0)
|
|
540
|
+
continue;
|
|
541
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
542
|
+
ggml_backend_tensor_alloc(out.buf, t, tensor_base + off);
|
|
543
|
+
}
|
|
544
|
+
gguf_free(gctx);
|
|
545
|
+
return true;
|
|
546
|
+
}
|
|
547
|
+
// Bounds check failed — release the mmap buffer and fall through to
|
|
548
|
+
// the legacy alloc+copy path below.
|
|
549
|
+
ggml_backend_buffer_free(out.buf);
|
|
550
|
+
out.buf = nullptr;
|
|
551
|
+
}
|
|
552
|
+
// mmap failed or bounds check failed — fall through to the legacy
|
|
553
|
+
// alloc + copy path. Functionally equivalent, just with more RSS.
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
// PLAN #51a (Metal variant): zero-copy GPU path via the device's
|
|
557
|
+
// `buffer_from_host_ptr` capability. On Apple-Silicon Metal this maps
|
|
558
|
+
// to `[MTLDevice newBufferWithBytesNoCopy:length:options:deallocator:]`
|
|
559
|
+
// wrapping our mmap region in an MTLResourceStorageModeShared buffer
|
|
560
|
+
// — same physical pages the CPU sees thanks to unified memory, no
|
|
561
|
+
// device-side allocation, no copy. On discrete-Metal hosts (Intel +
|
|
562
|
+
// eGPU) this lets the GPU page-fault from the file directly. The
|
|
563
|
+
// device-cap probe means we silently fall through on backends that
|
|
564
|
+
// don't advertise host-pointer support (CUDA without managed memory,
|
|
565
|
+
// Vulkan, etc.).
|
|
566
|
+
//
|
|
567
|
+
// The inner buffer is returned as `out.buf` UNWRAPPED. We used to
|
|
568
|
+
// wrap it to attach a munmap callback to free_buffer, but ggml-metal
|
|
569
|
+
// pierces the iface abstraction and casts `buffer->context` straight
|
|
570
|
+
// to its `ggml_metal_buffer_t` — wrapping made Metal read garbage
|
|
571
|
+
// and emit "tensor 'X' buffer is nil" for every weight (kokoro
|
|
572
|
+
// gibberish-audio regression). The mmap region is registered in
|
|
573
|
+
// g_gpu_mmap and deliberately leaked when the buffer is freed: Metal
|
|
574
|
+
// doesn't own the pages (deallocator=nil), and on macOS file-backed
|
|
575
|
+
// pages can still be evicted under pressure. Process exit cleans up.
|
|
576
|
+
if (mmap_loader_enabled() && !ggml_backend_is_cpu(backend)) {
|
|
577
|
+
ggml_backend_dev_t dev = ggml_backend_get_device(backend);
|
|
578
|
+
ggml_backend_dev_props props{};
|
|
579
|
+
ggml_backend_dev_get_props(dev, &props);
|
|
580
|
+
if (props.caps.buffer_from_host_ptr) {
|
|
581
|
+
MappedFile mf(path, /*writable=*/true);
|
|
582
|
+
if (mf.ok) {
|
|
583
|
+
const size_t data_off = gguf_get_data_offset(gctx);
|
|
584
|
+
char* tensor_base = (char*)mf.base + data_off;
|
|
585
|
+
|
|
586
|
+
// Hand the entire mmap region (including GGUF header) to
|
|
587
|
+
// the device. The backend's `buffer_from_host_ptr` uses
|
|
588
|
+
// the size for its internal MTLBuffer view; tensor binds
|
|
589
|
+
// below offset into this base.
|
|
590
|
+
ggml_backend_buffer_t inner = ggml_backend_dev_buffer_from_host_ptr(dev, mf.base, mf.size,
|
|
591
|
+
/*max_tensor_size=*/0);
|
|
592
|
+
if (inner) {
|
|
593
|
+
void* leaked_base = mf.base;
|
|
594
|
+
size_t leaked_size = mf.size;
|
|
595
|
+
mf.release();
|
|
596
|
+
// Hint kernel async readahead — same rationale as the
|
|
597
|
+
// CPU branch above. On Apple Silicon the unified-memory
|
|
598
|
+
// shared-storage MTLBuffer reads the same physical
|
|
599
|
+
// pages, so this readahead benefits both CPU and GPU
|
|
600
|
+
// accesses with one call.
|
|
601
|
+
#if !defined(_WIN32)
|
|
602
|
+
::posix_madvise(leaked_base, leaked_size, POSIX_MADV_WILLNEED);
|
|
603
|
+
#endif
|
|
604
|
+
// PLAN #60c / #60f: optional preload + mlock, opt-in
|
|
605
|
+
// via env. mlock is particularly meaningful here —
|
|
606
|
+
// pinning prevents Metal's shared-storage reads from
|
|
607
|
+
// racing CPU page faults under memory pressure.
|
|
608
|
+
if (preload_enabled())
|
|
609
|
+
preload_pages(leaked_base, leaked_size);
|
|
610
|
+
if (mlock_enabled())
|
|
611
|
+
try_mlock(tag, leaked_base, leaked_size);
|
|
612
|
+
|
|
613
|
+
register_gpu_mmap(inner, leaked_base, leaked_size);
|
|
614
|
+
out.buf = inner;
|
|
615
|
+
|
|
616
|
+
// Pre-validate bounds (same rationale as CPU mmap path).
|
|
617
|
+
bool bounds_ok = true;
|
|
618
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
619
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
620
|
+
if (tid < 0)
|
|
621
|
+
continue;
|
|
622
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
623
|
+
if (data_off + off + ggml_nbytes(t) > leaked_size) {
|
|
624
|
+
fprintf(stderr,
|
|
625
|
+
"%s: GPU mmap bounds check failed for tensor '%s' "
|
|
626
|
+
"(data_off=%zu + off=%zu + nbytes=%zu > file_size=%zu) — "
|
|
627
|
+
"falling back to legacy loader\n",
|
|
628
|
+
tag, ggml_get_name(t), data_off, off, ggml_nbytes(t), leaked_size);
|
|
629
|
+
bounds_ok = false;
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
if (!bounds_ok) {
|
|
634
|
+
out.buf = nullptr;
|
|
635
|
+
// inner is registered in g_gpu_mmap and deliberately
|
|
636
|
+
// leaked (same as the normal teardown path).
|
|
637
|
+
// Fall through to legacy path.
|
|
638
|
+
} else {
|
|
639
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
640
|
+
out.tensors[ggml_get_name(t)] = t;
|
|
641
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
642
|
+
if (tid < 0)
|
|
643
|
+
continue;
|
|
644
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
645
|
+
ggml_backend_tensor_alloc(out.buf, t, tensor_base + off);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
gguf_free(gctx);
|
|
649
|
+
return true;
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
// buffer_from_host_ptr returned null — release mmap and fall
|
|
653
|
+
// through to the legacy path. No warning; same rationale as
|
|
654
|
+
// the CPU mmap branch.
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
out.buf = ggml_backend_alloc_ctx_tensors(out.ctx, backend);
|
|
660
|
+
if (!out.buf) {
|
|
661
|
+
fprintf(stderr, "%s: failed to allocate backend buffer\n", tag);
|
|
662
|
+
gguf_free(gctx);
|
|
663
|
+
ggml_free(out.ctx);
|
|
664
|
+
out.ctx = nullptr;
|
|
665
|
+
return false;
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
MappedFile mf(path);
|
|
669
|
+
if (mf.ok) {
|
|
670
|
+
// Issue #94: the legacy alloc+copy path took 30-60 s for the
|
|
671
|
+
// 658 MB chatterbox-turbo T3 GGUF on slow disks, because each
|
|
672
|
+
// ggml_backend_tensor_set hit a synchronous page fault on
|
|
673
|
+
// its first access to the mmap source region. The zero-copy
|
|
674
|
+
// mmap path already hints WILLNEED (line 526) for the same
|
|
675
|
+
// reason; doing it here brings the legacy path's load time
|
|
676
|
+
// back in line for users who opt out of the zero-copy path
|
|
677
|
+
// with CRISPASR_GGUF_MMAP=0 (e.g. model files on network
|
|
678
|
+
// mounts where mmap would SIGBUS on disconnect).
|
|
679
|
+
#if !defined(_WIN32)
|
|
680
|
+
::posix_madvise(mf.base, mf.size, POSIX_MADV_WILLNEED);
|
|
681
|
+
#endif
|
|
682
|
+
}
|
|
683
|
+
if (!mf.ok) {
|
|
684
|
+
// Fallback: read via FILE* pread/fseek. This is the rare path —
|
|
685
|
+
// most systems have working mmap. We implement it inline here so
|
|
686
|
+
// models don't have to.
|
|
687
|
+
FILE* fp = fopen(path, "rb");
|
|
688
|
+
if (!fp) {
|
|
689
|
+
fprintf(stderr, "%s: cannot open '%s' for fread fallback\n", tag, path);
|
|
690
|
+
gguf_free(gctx);
|
|
691
|
+
return false;
|
|
692
|
+
}
|
|
693
|
+
const size_t data_off = gguf_get_data_offset(gctx);
|
|
694
|
+
std::vector<uint8_t> tbuf;
|
|
695
|
+
bool load_ok = true;
|
|
696
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
697
|
+
out.tensors[ggml_get_name(t)] = t;
|
|
698
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
699
|
+
if (tid < 0)
|
|
700
|
+
continue;
|
|
701
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
702
|
+
const size_t nbytes = ggml_nbytes(t);
|
|
703
|
+
if (tbuf.size() < nbytes)
|
|
704
|
+
tbuf.resize(nbytes);
|
|
705
|
+
#if defined(_WIN32)
|
|
706
|
+
if (_fseeki64(fp, (int64_t)(data_off + off), SEEK_SET) != 0) {
|
|
707
|
+
fprintf(stderr, "%s: fseek failed for tensor '%s' — file truncated?\n", tag, ggml_get_name(t));
|
|
708
|
+
load_ok = false;
|
|
709
|
+
break;
|
|
710
|
+
}
|
|
711
|
+
#else
|
|
712
|
+
if (fseeko(fp, (off_t)(data_off + off), SEEK_SET) != 0) {
|
|
713
|
+
fprintf(stderr, "%s: fseek failed for tensor '%s' — file truncated?\n", tag, ggml_get_name(t));
|
|
714
|
+
load_ok = false;
|
|
715
|
+
break;
|
|
716
|
+
}
|
|
717
|
+
#endif
|
|
718
|
+
if (fread(tbuf.data(), 1, nbytes, fp) != nbytes) {
|
|
719
|
+
fprintf(stderr, "%s: short read for tensor '%s' (%zu bytes expected) — file truncated?\n", tag,
|
|
720
|
+
ggml_get_name(t), nbytes);
|
|
721
|
+
load_ok = false;
|
|
722
|
+
break;
|
|
723
|
+
}
|
|
724
|
+
ggml_backend_tensor_set(t, tbuf.data(), 0, nbytes);
|
|
725
|
+
}
|
|
726
|
+
fclose(fp);
|
|
727
|
+
if (!load_ok) {
|
|
728
|
+
fprintf(stderr, "%s: legacy loader failed — model file may be truncated or corrupt\n", tag);
|
|
729
|
+
gguf_free(gctx);
|
|
730
|
+
ggml_backend_buffer_free(out.buf);
|
|
731
|
+
out.buf = nullptr;
|
|
732
|
+
ggml_free(out.ctx);
|
|
733
|
+
out.ctx = nullptr;
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
} else {
|
|
737
|
+
const size_t data_off = gguf_get_data_offset(gctx);
|
|
738
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
739
|
+
out.tensors[ggml_get_name(t)] = t;
|
|
740
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
741
|
+
if (tid < 0)
|
|
742
|
+
continue;
|
|
743
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
744
|
+
const size_t nbytes = ggml_nbytes(t);
|
|
745
|
+
// Bounds check: prevent segfault on truncated GGUF files
|
|
746
|
+
if (data_off + off + nbytes > mf.size) {
|
|
747
|
+
fprintf(stderr,
|
|
748
|
+
"%s: mmap legacy path: tensor '%s' exceeds file bounds "
|
|
749
|
+
"(off=%zu + nbytes=%zu > file_size=%zu) — file truncated?\n",
|
|
750
|
+
tag, ggml_get_name(t), data_off + off, nbytes, mf.size);
|
|
751
|
+
gguf_free(gctx);
|
|
752
|
+
ggml_backend_buffer_free(out.buf);
|
|
753
|
+
out.buf = nullptr;
|
|
754
|
+
ggml_free(out.ctx);
|
|
755
|
+
out.ctx = nullptr;
|
|
756
|
+
return false;
|
|
757
|
+
}
|
|
758
|
+
ggml_backend_tensor_set(t, (const char*)mf.base + data_off + off, 0, nbytes);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
gguf_free(gctx);
|
|
763
|
+
return true;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
void free_weights(WeightLoad& wl) {
|
|
767
|
+
if (wl.buf) {
|
|
768
|
+
ggml_backend_buffer_free(wl.buf);
|
|
769
|
+
wl.buf = nullptr;
|
|
770
|
+
}
|
|
771
|
+
if (wl.buf_cpu) {
|
|
772
|
+
ggml_backend_buffer_free(wl.buf_cpu);
|
|
773
|
+
wl.buf_cpu = nullptr;
|
|
774
|
+
}
|
|
775
|
+
if (wl.ctx) {
|
|
776
|
+
ggml_free(wl.ctx);
|
|
777
|
+
wl.ctx = nullptr;
|
|
778
|
+
}
|
|
779
|
+
wl.tensors.clear();
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
int blk_layer_of_with_prefix(const char* tensor_name, const char* prefix) {
|
|
783
|
+
if (!tensor_name || !prefix)
|
|
784
|
+
return -1;
|
|
785
|
+
const size_t plen = std::strlen(prefix);
|
|
786
|
+
if (std::strncmp(tensor_name, prefix, plen) != 0)
|
|
787
|
+
return -1;
|
|
788
|
+
char* end = nullptr;
|
|
789
|
+
long il = std::strtol(tensor_name + plen, &end, 10);
|
|
790
|
+
if (!end || *end != '.' || il < 0)
|
|
791
|
+
return -1;
|
|
792
|
+
return (int)il;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
int blk_layer_of(const char* tensor_name) {
|
|
796
|
+
return blk_layer_of_with_prefix(tensor_name, "blk.");
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
bool is_gpu_tensor_with_prefix(const char* tensor_name, void* user) {
|
|
800
|
+
const auto* cfg = static_cast<const LayerSplitConfig*>(user);
|
|
801
|
+
const int il = blk_layer_of_with_prefix(tensor_name, cfg->prefix);
|
|
802
|
+
if (il < 0)
|
|
803
|
+
return true; // non-layered tensors stay on GPU
|
|
804
|
+
return il < cfg->threshold;
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
bool is_gpu_tensor_blk(const char* tensor_name, void* user) {
|
|
808
|
+
const int threshold = *static_cast<const int*>(user);
|
|
809
|
+
const int il = blk_layer_of(tensor_name);
|
|
810
|
+
if (il < 0)
|
|
811
|
+
return true;
|
|
812
|
+
return il < threshold;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
bool load_weights_split(const char* path, ggml_backend_t gpu_backend, ggml_backend_t cpu_backend, IsGpuTensor is_gpu,
|
|
816
|
+
void* user, const char* model_tag, WeightLoad& out) {
|
|
817
|
+
const char* tag = model_tag ? model_tag : "core_gguf";
|
|
818
|
+
|
|
819
|
+
if (!gpu_backend || !cpu_backend) {
|
|
820
|
+
fprintf(stderr, "%s: load_weights_split requires both gpu and cpu backends\n", tag);
|
|
821
|
+
return false;
|
|
822
|
+
}
|
|
823
|
+
if (!is_gpu) {
|
|
824
|
+
fprintf(stderr, "%s: load_weights_split requires a non-null is_gpu predicate\n", tag);
|
|
825
|
+
return false;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// Open metadata + create ggml_context with all tensor metadata (no_alloc).
|
|
829
|
+
gguf_init_params gp = {/*.no_alloc=*/true, /*.ctx=*/&out.ctx};
|
|
830
|
+
gguf_context* gctx = gguf_init_from_file(path, gp);
|
|
831
|
+
if (!gctx || !out.ctx) {
|
|
832
|
+
fprintf(stderr, "%s: failed to load tensor metadata from '%s'\n", tag, path);
|
|
833
|
+
if (gctx)
|
|
834
|
+
gguf_free(gctx);
|
|
835
|
+
return false;
|
|
836
|
+
}
|
|
837
|
+
|
|
838
|
+
// Pass 1: partition tensors by predicate, sum sizes per partition.
|
|
839
|
+
std::vector<ggml_tensor*> gpu_tensors, cpu_tensors;
|
|
840
|
+
size_t gpu_size = 0, cpu_size = 0;
|
|
841
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
842
|
+
const char* tname = ggml_get_name(t);
|
|
843
|
+
const bool to_gpu = is_gpu(tname, user);
|
|
844
|
+
if (to_gpu) {
|
|
845
|
+
gpu_tensors.push_back(t);
|
|
846
|
+
gpu_size += ggml_nbytes(t);
|
|
847
|
+
} else {
|
|
848
|
+
cpu_tensors.push_back(t);
|
|
849
|
+
cpu_size += ggml_nbytes(t);
|
|
850
|
+
}
|
|
851
|
+
out.tensors[tname] = t;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
// Allocate per-partition backend buffers. Tensor alignment within the
|
|
855
|
+
// buffer follows the backend buffer-type's alignment requirement;
|
|
856
|
+
// pad each per-tensor offset up to that alignment.
|
|
857
|
+
auto round_up = [](size_t n, size_t a) { return (n + a - 1) & ~(a - 1); };
|
|
858
|
+
auto bind_partition = [&](ggml_backend_t be, const std::vector<ggml_tensor*>& tensors, size_t total,
|
|
859
|
+
ggml_backend_buffer_t* out_buf) -> bool {
|
|
860
|
+
if (tensors.empty())
|
|
861
|
+
return true;
|
|
862
|
+
const size_t align = ggml_backend_get_alignment(be);
|
|
863
|
+
// Compute final size with per-tensor alignment slack.
|
|
864
|
+
size_t aligned_total = 0;
|
|
865
|
+
for (ggml_tensor* t : tensors)
|
|
866
|
+
aligned_total = round_up(aligned_total, align) + ggml_nbytes(t);
|
|
867
|
+
(void)total;
|
|
868
|
+
ggml_backend_buffer_t buf = ggml_backend_alloc_buffer(be, aligned_total);
|
|
869
|
+
if (!buf) {
|
|
870
|
+
fprintf(stderr, "%s: failed to allocate %zu MiB backend buffer\n", tag, aligned_total / 1048576);
|
|
871
|
+
return false;
|
|
872
|
+
}
|
|
873
|
+
char* base = (char*)ggml_backend_buffer_get_base(buf);
|
|
874
|
+
size_t cursor = 0;
|
|
875
|
+
for (ggml_tensor* t : tensors) {
|
|
876
|
+
cursor = round_up(cursor, align);
|
|
877
|
+
ggml_backend_tensor_alloc(buf, t, base + cursor);
|
|
878
|
+
cursor += ggml_nbytes(t);
|
|
879
|
+
}
|
|
880
|
+
*out_buf = buf;
|
|
881
|
+
return true;
|
|
882
|
+
};
|
|
883
|
+
|
|
884
|
+
if (!bind_partition(gpu_backend, gpu_tensors, gpu_size, &out.buf)) {
|
|
885
|
+
gguf_free(gctx);
|
|
886
|
+
ggml_free(out.ctx);
|
|
887
|
+
out.ctx = nullptr;
|
|
888
|
+
return false;
|
|
889
|
+
}
|
|
890
|
+
if (!bind_partition(cpu_backend, cpu_tensors, cpu_size, &out.buf_cpu)) {
|
|
891
|
+
if (out.buf) {
|
|
892
|
+
ggml_backend_buffer_free(out.buf);
|
|
893
|
+
out.buf = nullptr;
|
|
894
|
+
}
|
|
895
|
+
gguf_free(gctx);
|
|
896
|
+
ggml_free(out.ctx);
|
|
897
|
+
out.ctx = nullptr;
|
|
898
|
+
return false;
|
|
899
|
+
}
|
|
900
|
+
|
|
901
|
+
// Copy tensor data from the file. Use mmap when available for zero-
|
|
902
|
+
// copy where the kernel will demand-page; fall back to pread.
|
|
903
|
+
MappedFile mf(path);
|
|
904
|
+
if (!mf.ok) {
|
|
905
|
+
FILE* fp = fopen(path, "rb");
|
|
906
|
+
if (!fp) {
|
|
907
|
+
fprintf(stderr, "%s: cannot open '%s' for fread fallback\n", tag, path);
|
|
908
|
+
free_weights(out);
|
|
909
|
+
gguf_free(gctx);
|
|
910
|
+
return false;
|
|
911
|
+
}
|
|
912
|
+
const size_t data_off = gguf_get_data_offset(gctx);
|
|
913
|
+
std::vector<uint8_t> tbuf;
|
|
914
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
915
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
916
|
+
if (tid < 0)
|
|
917
|
+
continue;
|
|
918
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
919
|
+
const size_t nbytes = ggml_nbytes(t);
|
|
920
|
+
if (tbuf.size() < nbytes)
|
|
921
|
+
tbuf.resize(nbytes);
|
|
922
|
+
#if defined(_WIN32)
|
|
923
|
+
if (_fseeki64(fp, (int64_t)(data_off + off), SEEK_SET) != 0)
|
|
924
|
+
break;
|
|
925
|
+
#else
|
|
926
|
+
if (fseeko(fp, (off_t)(data_off + off), SEEK_SET) != 0)
|
|
927
|
+
break;
|
|
928
|
+
#endif
|
|
929
|
+
if (fread(tbuf.data(), 1, nbytes, fp) != nbytes)
|
|
930
|
+
break;
|
|
931
|
+
ggml_backend_tensor_set(t, tbuf.data(), 0, nbytes);
|
|
932
|
+
}
|
|
933
|
+
fclose(fp);
|
|
934
|
+
} else {
|
|
935
|
+
const size_t data_off = gguf_get_data_offset(gctx);
|
|
936
|
+
for (ggml_tensor* t = ggml_get_first_tensor(out.ctx); t; t = ggml_get_next_tensor(out.ctx, t)) {
|
|
937
|
+
const int64_t tid = gguf_find_tensor(gctx, ggml_get_name(t));
|
|
938
|
+
if (tid < 0)
|
|
939
|
+
continue;
|
|
940
|
+
const size_t off = gguf_get_tensor_offset(gctx, tid);
|
|
941
|
+
const size_t nbytes = ggml_nbytes(t);
|
|
942
|
+
ggml_backend_tensor_set(t, (const char*)mf.base + data_off + off, 0, nbytes);
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
fprintf(stderr, "%s: weight residency: gpu=%zu MiB (%zu tensors), cpu=%zu MiB (%zu tensors)\n", tag,
|
|
947
|
+
gpu_size / 1048576, gpu_tensors.size(), cpu_size / 1048576, cpu_tensors.size());
|
|
948
|
+
|
|
949
|
+
gguf_free(gctx);
|
|
950
|
+
return true;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
// PLAN #60g: switch a previously-WILLNEED-hinted region to MADV_RANDOM.
|
|
954
|
+
// Used by callers (e.g., mimo-asr's transcribe loop) to tell the kernel
|
|
955
|
+
// "I'm done with sequential prefill access; my next reads will be
|
|
956
|
+
// random-order layer revisits during decode — please stop wasting IO
|
|
957
|
+
// on speculative readahead."
|
|
958
|
+
//
|
|
959
|
+
// We dispatch on the buffer's iface fields to detect which of our two
|
|
960
|
+
// mmap paths the buffer came from, since the buffer types themselves
|
|
961
|
+
// aren't exposed publicly. No-op if the buffer wasn't allocated through
|
|
962
|
+
// either path (incl. the legacy alloc+copy fallback when MMAP=0 or
|
|
963
|
+
// mmap failed).
|
|
964
|
+
void mmap_advise_random(ggml_backend_buffer_t buf) {
|
|
965
|
+
#if !defined(_WIN32)
|
|
966
|
+
if (!buf)
|
|
967
|
+
return;
|
|
968
|
+
void* base = nullptr;
|
|
969
|
+
size_t size = 0;
|
|
970
|
+
if (buf->iface.free_buffer == mmap_buffer_free) {
|
|
971
|
+
// CPU mmap path — context is mmap_buffer_ctx (our own iface).
|
|
972
|
+
auto* mctx = (mmap_buffer_ctx*)buf->context;
|
|
973
|
+
base = mctx->mmap_base;
|
|
974
|
+
size = mctx->mmap_size;
|
|
975
|
+
} else {
|
|
976
|
+
// Non-CPU (Metal) mmap path — buffer is the inner backend buffer,
|
|
977
|
+
// its context belongs to that backend; look the mmap region up
|
|
978
|
+
// in our side-map instead.
|
|
979
|
+
gpu_mmap_handle h = lookup_gpu_mmap(buf);
|
|
980
|
+
base = h.base;
|
|
981
|
+
size = h.size;
|
|
982
|
+
}
|
|
983
|
+
if (base && size > 0)
|
|
984
|
+
::posix_madvise(base, size, POSIX_MADV_RANDOM);
|
|
985
|
+
#else
|
|
986
|
+
(void)buf;
|
|
987
|
+
#endif
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
// ---------------------------------------------------------------------------
|
|
991
|
+
// Tensor lookup helpers
|
|
992
|
+
// ---------------------------------------------------------------------------
|
|
993
|
+
|
|
994
|
+
// Signatures use `core_gguf::tensor_map` (see gguf_loader.h cross-repo contract).
|
|
995
|
+
ggml_tensor* try_get(const tensor_map& tensors, const char* name) {
|
|
996
|
+
auto it = tensors.find(name);
|
|
997
|
+
return it != tensors.end() ? it->second : nullptr;
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
ggml_tensor* require(const tensor_map& tensors, const char* name, const char* model_tag) {
|
|
1001
|
+
auto it = tensors.find(name);
|
|
1002
|
+
if (it == tensors.end()) {
|
|
1003
|
+
fprintf(stderr, "%s: required tensor '%s' not found in GGUF\n", model_tag ? model_tag : "core_gguf", name);
|
|
1004
|
+
return nullptr;
|
|
1005
|
+
}
|
|
1006
|
+
return it->second;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
std::string format_layer_name(const char* fmt, int i) {
|
|
1010
|
+
char buf[256];
|
|
1011
|
+
snprintf(buf, sizeof(buf), fmt, i);
|
|
1012
|
+
return std::string(buf);
|
|
1013
|
+
}
|
|
1014
|
+
|
|
1015
|
+
std::string format_layer_name(const char* fmt, int i, int j) {
|
|
1016
|
+
char buf[256];
|
|
1017
|
+
snprintf(buf, sizeof(buf), fmt, i, j);
|
|
1018
|
+
return std::string(buf);
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
} // namespace core_gguf
|