@mlx-bun/inference 0.0.0-stage → 1.0.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.
- package/LICENSE +21 -0
- package/README.md +1475 -2
- package/THIRD_PARTY_NOTICES.md +3404 -0
- package/dist/native/libmlx_bun_ane.dylib +0 -0
- package/dist/native/libmlx_bun_expert_io.dylib +0 -0
- package/dist/native/mlx-bun-frame-extract +0 -0
- package/examples/fit-model.ts +25 -0
- package/examples/qwen3-forward.ts +42 -0
- package/examples/qwen3-generate.ts +28 -0
- package/examples/trellis-expand.ts +23 -0
- package/package.json +129 -4
- package/src/adapters/available.ts +110 -0
- package/src/adapters/index.ts +3 -0
- package/src/adapters/manager.ts +316 -0
- package/src/artifacts/auxiliary-files.ts +45 -0
- package/src/artifacts/config-dialects.ts +94 -0
- package/src/artifacts/config.ts +341 -0
- package/src/artifacts/draft-vocabulary.ts +30 -0
- package/src/artifacts/expert-offload-build.ts +75 -0
- package/src/artifacts/expert-offload.ts +89 -0
- package/src/artifacts/experts/index.ts +3 -0
- package/src/artifacts/experts/io.ts +386 -0
- package/src/artifacts/experts/residency.ts +1134 -0
- package/src/artifacts/experts/usage.ts +415 -0
- package/src/artifacts/fingerprint.ts +44 -0
- package/src/artifacts/glm52/container.ts +305 -0
- package/src/artifacts/glm52/expert-layout.ts +249 -0
- package/src/artifacts/glm52/index.ts +7 -0
- package/src/artifacts/glm52/kernel-layout.ts +124 -0
- package/src/artifacts/glm52/layout.ts +152 -0
- package/src/artifacts/glm52/memory.ts +500 -0
- package/src/artifacts/glm52/resident-weights.ts +135 -0
- package/src/artifacts/glm52/weights.ts +503 -0
- package/src/artifacts/glm52-config.ts +262 -0
- package/src/artifacts/identity.ts +94 -0
- package/src/artifacts/index.ts +15 -0
- package/src/artifacts/mmap.ts +90 -0
- package/src/artifacts/safetensors-writer.ts +249 -0
- package/src/artifacts/safetensors.ts +164 -0
- package/src/artifacts/turboquant-fold.ts +42 -0
- package/src/artifacts/weight-audit.ts +43 -0
- package/src/artifacts/weights.ts +255 -0
- package/src/contracts/index.ts +2 -0
- package/src/contracts/mlx/attention.ts +8 -0
- package/src/contracts/mlx/cache.ts +510 -0
- package/src/contracts/mlx/checkpoint.ts +10 -0
- package/src/contracts/mlx/draft-checkpoint.ts +14 -0
- package/src/contracts/mlx/draft-projection.ts +27 -0
- package/src/contracts/mlx/draft-target.ts +84 -0
- package/src/contracts/mlx/drafter.ts +176 -0
- package/src/contracts/mlx/forward-work.ts +23 -0
- package/src/contracts/mlx/glm52-weights.ts +25 -0
- package/src/contracts/mlx/graph.ts +309 -0
- package/src/contracts/mlx/head.ts +6 -0
- package/src/contracts/mlx/index.ts +15 -0
- package/src/contracts/mlx/kv-codec.ts +9 -0
- package/src/contracts/mlx/media.ts +113 -0
- package/src/contracts/mlx/positions.ts +16 -0
- package/src/contracts/mlx/row-table.ts +2 -0
- package/src/contracts/mlx/trainable.ts +103 -0
- package/src/contracts/mlx/whisper.ts +96 -0
- package/src/contracts/portable/composition.ts +106 -0
- package/src/contracts/portable/denoising.ts +17 -0
- package/src/contracts/portable/execution.ts +79 -0
- package/src/contracts/portable/generation.ts +103 -0
- package/src/contracts/portable/graph.ts +80 -0
- package/src/contracts/portable/index.ts +15 -0
- package/src/contracts/portable/memory-plan.ts +26 -0
- package/src/contracts/portable/object-cache.ts +8 -0
- package/src/contracts/portable/prefill.ts +63 -0
- package/src/contracts/portable/prefix-cache.ts +33 -0
- package/src/contracts/portable/prompt.ts +2 -0
- package/src/contracts/portable/resources.ts +25 -0
- package/src/contracts/portable/rollback.ts +7 -0
- package/src/contracts/portable/sampling.ts +44 -0
- package/src/contracts/portable/scheduling.ts +54 -0
- package/src/contracts/portable/token-delivery.ts +4 -0
- package/src/contracts/portable/tsconfig.json +14 -0
- package/src/embeddings/index.ts +1 -0
- package/src/embeddings/text.ts +85 -0
- package/src/execution/admission.ts +59 -0
- package/src/execution/batch-group.ts +1240 -0
- package/src/execution/batch-types.ts +225 -0
- package/src/execution/cancellation.ts +38 -0
- package/src/execution/continuation-request.ts +45 -0
- package/src/execution/continuation-types.ts +10 -0
- package/src/execution/coordinator.ts +70 -0
- package/src/execution/denoising-group.ts +180 -0
- package/src/execution/engine.ts +56 -0
- package/src/execution/fill-group.ts +505 -0
- package/src/execution/fit.ts +184 -0
- package/src/execution/gateway-binding.ts +178 -0
- package/src/execution/grammar-group.ts +224 -0
- package/src/execution/index.ts +18 -0
- package/src/execution/methods.ts +75 -0
- package/src/execution/mixed-iteration.ts +96 -0
- package/src/execution/plan.ts +65 -0
- package/src/execution/prefill-cohort.ts +100 -0
- package/src/execution/prefill-rows.ts +263 -0
- package/src/execution/request-policy.ts +19 -0
- package/src/execution/row-sampling.ts +49 -0
- package/src/execution/scheduler.ts +92 -0
- package/src/execution/session.ts +247 -0
- package/src/execution/speculative-group.ts +797 -0
- package/src/execution/tasks.ts +44 -0
- package/src/generation/autoregressive.ts +840 -0
- package/src/generation/bindings/autoregressive.ts +104 -0
- package/src/generation/bindings/denoising.ts +60 -0
- package/src/generation/bindings/prefill-policy.ts +36 -0
- package/src/generation/checkpoint-identity.ts +60 -0
- package/src/generation/denoising.ts +85 -0
- package/src/generation/diffusion.ts +583 -0
- package/src/generation/fill/echo-index.ts +188 -0
- package/src/generation/fill/index.ts +3 -0
- package/src/generation/fill/proposal.ts +69 -0
- package/src/generation/fill/schema-rows.ts +506 -0
- package/src/generation/fill/session.ts +464 -0
- package/src/generation/fill/tool-boundary.ts +103 -0
- package/src/generation/fill-append.ts +58 -0
- package/src/generation/generate.ts +44 -0
- package/src/generation/grammar-step.ts +39 -0
- package/src/generation/index.ts +14 -0
- package/src/generation/phase-dispatch.ts +115 -0
- package/src/generation/prefill.ts +33 -0
- package/src/generation/result.ts +49 -0
- package/src/generation/scopes.ts +157 -0
- package/src/generation/speculative/acceptance.ts +41 -0
- package/src/generation/speculative/adaptive-draft-gate.ts +166 -0
- package/src/generation/speculative/bindings/assistant-rows.ts +102 -0
- package/src/generation/speculative/bindings/autoregressive-rows.ts +124 -0
- package/src/generation/speculative/bindings/binding.ts +106 -0
- package/src/generation/speculative/bindings/deepspec-rows.ts +33 -0
- package/src/generation/speculative/bindings/draft-target.ts +10 -0
- package/src/generation/speculative/bindings/glm52-mtp-rows.ts +128 -0
- package/src/generation/speculative/bindings/projected-context-rows.ts +78 -0
- package/src/generation/speculative/bindings/projected-draft-rows.ts +95 -0
- package/src/generation/speculative/bindings/qwen-mtp-rows.ts +336 -0
- package/src/generation/speculative/bindings/two-model-rows.ts +63 -0
- package/src/generation/speculative/cache-identity.ts +16 -0
- package/src/generation/speculative/draft-kind.ts +149 -0
- package/src/generation/speculative/draft-policy.ts +41 -0
- package/src/generation/speculative/draft-registry.ts +118 -0
- package/src/generation/speculative/draft-vocab.ts +110 -0
- package/src/generation/speculative/index.ts +17 -0
- package/src/generation/speculative/output.ts +49 -0
- package/src/generation/speculative/round.ts +307 -0
- package/src/generation/speculative/source.ts +144 -0
- package/src/generation/speculative/sources/assistant-source.ts +64 -0
- package/src/generation/speculative/sources/deepspec-source.ts +70 -0
- package/src/generation/speculative/sources/dflash-source.ts +84 -0
- package/src/generation/speculative/sources/dflash2-source.ts +86 -0
- package/src/generation/speculative/sources/glm52-mtp-source.ts +66 -0
- package/src/generation/speculative/sources/ngram-source.ts +165 -0
- package/src/generation/speculative/sources/qwen-mtp-source.ts +154 -0
- package/src/generation/speculative/sources/two-model.ts +75 -0
- package/src/generation/types.ts +194 -0
- package/src/index.ts +20 -0
- package/src/input/audio/audiotoolbox.ts +112 -0
- package/src/input/audio/decode.ts +133 -0
- package/src/input/audio/features.ts +202 -0
- package/src/input/audio/index.ts +6 -0
- package/src/input/audio/transcode.ts +67 -0
- package/src/input/audio/whisper-mel.ts +185 -0
- package/src/input/audio/whisper-tokenizer.ts +238 -0
- package/src/input/chat-template.ts +389 -0
- package/src/input/index.ts +6 -0
- package/src/input/media-fetch.ts +439 -0
- package/src/input/packed-mixed.ts +43 -0
- package/src/input/special-tokens.ts +75 -0
- package/src/input/token-groups.ts +49 -0
- package/src/input/tokenizer.ts +336 -0
- package/src/input/tool-call.ts +689 -0
- package/src/input/vision/index.ts +3 -0
- package/src/input/vision/preprocess.ts +247 -0
- package/src/input/vision/prompt.ts +398 -0
- package/src/input/vision/qwen3vl-preprocess.ts +409 -0
- package/src/input/vision/qwen3vl-prompt.ts +237 -0
- package/src/input/vision/video-frames.ts +100 -0
- package/src/kernels/ane/fill.ts +101 -0
- package/src/kernels/ane/linear.ts +416 -0
- package/src/kernels/attention/flash.ts +694 -0
- package/src/kernels/attention/kvq4-decode.ts +155 -0
- package/src/kernels/attention/masks.ts +40 -0
- package/src/kernels/attention/multi-query.ts +193 -0
- package/src/kernels/attention/paged.ts +130 -0
- package/src/kernels/delta/gated.ts +306 -0
- package/src/kernels/delta/index.ts +3 -0
- package/src/kernels/delta/silu-rms-heads.ts +69 -0
- package/src/kernels/delta/state.ts +74 -0
- package/src/kernels/gated-rms-norm.ts +64 -0
- package/src/kernels/glm52/layout.ts +37 -0
- package/src/kernels/glm52/streamed-experts.ts +360 -0
- package/src/kernels/logits.ts +38 -0
- package/src/kernels/quantization/affine-row.ts +154 -0
- package/src/kernels/quantization/affine-rows.ts +36 -0
- package/src/kernels/quantization/affine-split-mma.ts +144 -0
- package/src/kernels/quantization/affine3-mma.ts +117 -0
- package/src/kernels/quantization/affine3-rows.ts +103 -0
- package/src/kernels/quantization/affine4-mma.ts +113 -0
- package/src/kernels/quantization/affine4-rows.ts +102 -0
- package/src/kernels/residual-rms-norm.ts +65 -0
- package/src/kernels/sampling/index.ts +2 -0
- package/src/kernels/sampling/normalized-argmax.ts +116 -0
- package/src/kernels/sampling/token-bitmask.ts +52 -0
- package/src/kernels/softcap.ts +35 -0
- package/src/kernels/trellis/codebook.ts +123 -0
- package/src/kernels/trellis/down-codebook.ts +184 -0
- package/src/kernels/trellis/down-factored.ts +180 -0
- package/src/kernels/trellis/down-k3-interleaved-factored.ts +146 -0
- package/src/kernels/trellis/down-mma-wide.ts +195 -0
- package/src/kernels/trellis/down-mma.ts +145 -0
- package/src/kernels/trellis/expand.ts +42 -0
- package/src/kernels/trellis/gate-up-codebook-mma.ts +141 -0
- package/src/kernels/trellis/gate-up-codebook.ts +137 -0
- package/src/kernels/trellis/gate-up-factored.ts +197 -0
- package/src/kernels/trellis/gate-up-mma-wide.ts +147 -0
- package/src/kernels/trellis/gate-up-mma.ts +148 -0
- package/src/kernels/trellis/gate-up.ts +248 -0
- package/src/kernels/trellis/geometry.ts +22 -0
- package/src/kernels/trellis/index.ts +103 -0
- package/src/kernels/trellis/launch.ts +12 -0
- package/src/kernels/trellis/mixed-gate-up-factored.ts +119 -0
- package/src/kernels/trellis/mixed-gate-up.ts +146 -0
- package/src/kernels/trellis/qualified.ts +34 -0
- package/src/kernels/trellis/reduce.ts +150 -0
- package/src/kernels/trellis/scatter.ts +407 -0
- package/src/kernels/trellis/splitk-prefill.ts +152 -0
- package/src/kernels/trellis/tiled-prefill.ts +131 -0
- package/src/kernels/trellis/vector-expand.ts +58 -0
- package/src/kernels/trellis/wide-prefill.ts +89 -0
- package/src/kernels/turboquant/decode.ts +82 -0
- package/src/kernels/turboquant/index.ts +5 -0
- package/src/kernels/turboquant/inverse.ts +122 -0
- package/src/kernels/turboquant/ops.ts +860 -0
- package/src/kernels/turboquant/signs.ts +130 -0
- package/src/kernels/turboquant/tables.ts +124 -0
- package/src/layers/affine-verify-linear.ts +75 -0
- package/src/layers/ane-prefill-split.ts +283 -0
- package/src/layers/compiled-normalization.ts +41 -0
- package/src/layers/delta-heads.ts +23 -0
- package/src/layers/dense-embedding.ts +29 -0
- package/src/layers/dense-linear.ts +32 -0
- package/src/layers/dequantized-linear.ts +72 -0
- package/src/layers/folded-attention.ts +42 -0
- package/src/layers/geglu.ts +130 -0
- package/src/layers/helpers.ts +7 -0
- package/src/layers/index.ts +36 -0
- package/src/layers/kv4-decode-attention.ts +15 -0
- package/src/layers/layer-norm.ts +24 -0
- package/src/layers/loading.ts +92 -0
- package/src/layers/lora.ts +150 -0
- package/src/layers/normalization.ts +9 -0
- package/src/layers/prefix-layout.ts +33 -0
- package/src/layers/quantized-append-attention.ts +32 -0
- package/src/layers/quantized-attention.ts +353 -0
- package/src/layers/quantized-embedding.ts +39 -0
- package/src/layers/quantized-linear.ts +137 -0
- package/src/layers/quantized-switch-linear.ts +37 -0
- package/src/layers/qwen-append.ts +12 -0
- package/src/layers/qwen-mrope.ts +238 -0
- package/src/layers/rope-2d.ts +110 -0
- package/src/layers/rope.ts +389 -0
- package/src/layers/swiglu.ts +23 -0
- package/src/layers/trellis-codebook-down.ts +52 -0
- package/src/layers/trellis-codebook-gate-up.ts +42 -0
- package/src/layers/trellis-down.ts +117 -0
- package/src/layers/trellis-gate-up.ts +71 -0
- package/src/layers/trellis-linear.ts +211 -0
- package/src/layers/trellis-prompt.ts +102 -0
- package/src/layers/trellis-reduce-gate-up.ts +73 -0
- package/src/layers/trellis-scatter-down.ts +98 -0
- package/src/models/ane-install.ts +74 -0
- package/src/models/audio/conformer.ts +656 -0
- package/src/models/cache-composition.ts +44 -0
- package/src/models/capabilities.ts +89 -0
- package/src/models/chat-template.ts +10 -0
- package/src/models/composition.ts +107 -0
- package/src/models/diffusion-gemma/experts.ts +59 -0
- package/src/models/diffusion-gemma/family.ts +21 -0
- package/src/models/diffusion-gemma/model.ts +900 -0
- package/src/models/diffusion-gemma/vision.ts +549 -0
- package/src/models/drafter-loaders.ts +49 -0
- package/src/models/drafters.ts +39 -0
- package/src/models/factory.ts +351 -0
- package/src/models/families.ts +70 -0
- package/src/models/family.ts +125 -0
- package/src/models/gemma4/assistant-target.ts +46 -0
- package/src/models/gemma4/assistant.ts +327 -0
- package/src/models/gemma4/blocks.ts +755 -0
- package/src/models/gemma4/compiled-decode.ts +452 -0
- package/src/models/gemma4/family.ts +39 -0
- package/src/models/gemma4/gemma4-12b.ts +677 -0
- package/src/models/gemma4/gemma4-26b.ts +544 -0
- package/src/models/gemma4/gemma4-e4b.ts +599 -0
- package/src/models/gemma4/graphs.ts +147 -0
- package/src/models/gemma4/media.ts +88 -0
- package/src/models/gemma4/model.ts +860 -0
- package/src/models/gemma4/serving-blocks.ts +72 -0
- package/src/models/gemma4/trainable.ts +186 -0
- package/src/models/gemma4/written-blocks.ts +232 -0
- package/src/models/gemma4/written-forward.ts +159 -0
- package/src/models/gemma4/written-input.ts +29 -0
- package/src/models/glm52/atlas.ts +507 -0
- package/src/models/glm52/coupling.ts +388 -0
- package/src/models/glm52/dsa.ts +601 -0
- package/src/models/glm52/family.ts +20 -0
- package/src/models/glm52/mla.ts +812 -0
- package/src/models/glm52/model.ts +1127 -0
- package/src/models/glm52/moe.ts +223 -0
- package/src/models/glm52/mtp.ts +60 -0
- package/src/models/glm52/pilot.ts +537 -0
- package/src/models/glm52/reference.ts +445 -0
- package/src/models/glm52/residency.ts +557 -0
- package/src/models/glm52/streamed-experts.ts +447 -0
- package/src/models/graph.ts +59 -0
- package/src/models/implementation.ts +230 -0
- package/src/models/index.ts +15 -0
- package/src/models/media-input.ts +15 -0
- package/src/models/memory-plan.ts +39 -0
- package/src/models/minicpm5/family.ts +29 -0
- package/src/models/minicpm5/model.ts +394 -0
- package/src/models/minicpm5/trainable.ts +90 -0
- package/src/models/profile.ts +337 -0
- package/src/models/qwen/blocks.ts +658 -0
- package/src/models/qwen/checkpoint.ts +190 -0
- package/src/models/qwen/families.ts +57 -0
- package/src/models/qwen/media-input.ts +161 -0
- package/src/models/qwen/mtp.ts +101 -0
- package/src/models/qwen/qwen3-moe.ts +355 -0
- package/src/models/qwen/qwen3.ts +323 -0
- package/src/models/qwen/qwen38-27b-trellis-m1max.ts +1532 -0
- package/src/models/qwen/qwen38-27b-trellis-m4pro.ts +1092 -0
- package/src/models/qwen/qwen3_5.ts +433 -0
- package/src/models/qwen/written-layers.ts +285 -0
- package/src/models/row-table.ts +1 -0
- package/src/models/runtime.ts +73 -0
- package/src/models/speculative/deepspec-artifact.ts +10 -0
- package/src/models/speculative/deepspec.ts +744 -0
- package/src/models/speculative/dflash.ts +553 -0
- package/src/models/speculative/dflash2-artifact.ts +9 -0
- package/src/models/speculative/dflash2-operations.ts +1 -0
- package/src/models/speculative/dflash2.ts +576 -0
- package/src/models/speculative/loader.ts +29 -0
- package/src/models/support.ts +79 -0
- package/src/models/universal/archs.ts +365 -0
- package/src/models/universal/blocks.ts +479 -0
- package/src/models/universal/dense.ts +255 -0
- package/src/models/universal/family.ts +17 -0
- package/src/models/vision/qwen3vl.ts +566 -0
- package/src/models/vision/siglip.ts +520 -0
- package/src/models/vision/unified.ts +176 -0
- package/src/models/whisper/family.ts +19 -0
- package/src/models/whisper/fast.ts +734 -0
- package/src/models/whisper/model.ts +430 -0
- package/src/runtime/compiled-trace.ts +16 -0
- package/src/runtime/config.ts +77 -0
- package/src/runtime/expert-trace.ts +71 -0
- package/src/runtime/graph-forward.ts +65 -0
- package/src/runtime/integers.ts +6 -0
- package/src/runtime/native.ts +16 -0
- package/src/runtime/resources.ts +53 -0
- package/src/runtime/row-operations.ts +42 -0
- package/src/runtime/trace.ts +161 -0
- package/src/sampling/curve.ts +122 -0
- package/src/sampling/draft.ts +55 -0
- package/src/sampling/extras.ts +45 -0
- package/src/sampling/filters.ts +134 -0
- package/src/sampling/grammar.ts +630 -0
- package/src/sampling/hlg.ts +290 -0
- package/src/sampling/index.ts +9 -0
- package/src/sampling/processors.ts +142 -0
- package/src/sampling/sampler.ts +120 -0
- package/src/sampling/step.ts +343 -0
- package/src/sampling/types.ts +161 -0
- package/src/sampling/window-filters.ts +46 -0
- package/src/scoring/decisions.ts +96 -0
- package/src/scoring/full-sequence.ts +103 -0
- package/src/scoring/index.ts +9 -0
- package/src/scoring/kl.ts +29 -0
- package/src/scoring/perplexity.ts +165 -0
- package/src/scoring/response-logps.ts +65 -0
- package/src/state/affine-attention.ts +180 -0
- package/src/state/attachment.ts +68 -0
- package/src/state/attention-read.ts +215 -0
- package/src/state/batched-kv.ts +294 -0
- package/src/state/batched-mask.ts +445 -0
- package/src/state/batched-quant.ts +389 -0
- package/src/state/batched-quantized-kv.ts +209 -0
- package/src/state/batched-rotating-quant.ts +457 -0
- package/src/state/batched-rotating-state.ts +149 -0
- package/src/state/batched-rotating.ts +430 -0
- package/src/state/batched-row-storage.ts +179 -0
- package/src/state/batched-ssm.ts +54 -0
- package/src/state/batched-turboquant-kv.ts +144 -0
- package/src/state/bf16-first-kv.ts +663 -0
- package/src/state/cache-service.ts +592 -0
- package/src/state/capabilities.ts +65 -0
- package/src/state/checkpoint.ts +46 -0
- package/src/state/continuation-persistence.ts +126 -0
- package/src/state/decode-step-inputs.ts +31 -0
- package/src/state/decoded-kv-donor.ts +12 -0
- package/src/state/delayed-quantized-kv.ts +141 -0
- package/src/state/delayed-rotating-quantized-kv.ts +178 -0
- package/src/state/delayed-turboquant-kv.ts +123 -0
- package/src/state/durability.ts +214 -0
- package/src/state/encoder-cache.ts +26 -0
- package/src/state/full-kv-row-append.ts +33 -0
- package/src/state/full-kv-row-donor.ts +54 -0
- package/src/state/full-prefill-padding.ts +56 -0
- package/src/state/full-prefill-row.ts +112 -0
- package/src/state/full-transitioning-kv-rows.ts +70 -0
- package/src/state/glm52-cache.ts +783 -0
- package/src/state/grouped-heads-kv4-cache.ts +26 -0
- package/src/state/index.ts +38 -0
- package/src/state/kv-attention-view.ts +77 -0
- package/src/state/kv-budget.ts +14 -0
- package/src/state/kv-scheme.ts +315 -0
- package/src/state/kv-storage.ts +57 -0
- package/src/state/kv-tensor-rows.ts +212 -0
- package/src/state/kv.ts +324 -0
- package/src/state/kv4-head256-cache.ts +46 -0
- package/src/state/latent-legos.ts +895 -0
- package/src/state/layout.ts +277 -0
- package/src/state/leases.ts +26 -0
- package/src/state/paged/cache.ts +689 -0
- package/src/state/paged/codec.ts +36 -0
- package/src/state/paged/rows.ts +223 -0
- package/src/state/persistence-types.ts +173 -0
- package/src/state/persistence-worker.ts +83 -0
- package/src/state/persistence.ts +1036 -0
- package/src/state/persistence.worker.d.ts +3 -0
- package/src/state/persistence.worker.js +264 -0
- package/src/state/prefix-cache.ts +685 -0
- package/src/state/quantized-kv.ts +369 -0
- package/src/state/quantized-tensor.ts +26 -0
- package/src/state/request-policy.ts +48 -0
- package/src/state/retention-policy.ts +37 -0
- package/src/state/rollback.ts +131 -0
- package/src/state/rotating-kv-donor.ts +35 -0
- package/src/state/rotating-kv-layout.ts +341 -0
- package/src/state/rotating-kv.ts +529 -0
- package/src/state/rotating-quantized-kv.ts +616 -0
- package/src/state/rotating-row-transaction.ts +35 -0
- package/src/state/rows.ts +104 -0
- package/src/state/softcap-attention.ts +118 -0
- package/src/state/speculative/glm52-mtp-state.ts +38 -0
- package/src/state/speculative/qwen-mtp-state.ts +34 -0
- package/src/state/speculative-rotating-kv.ts +113 -0
- package/src/state/ssd-cache.ts +434 -0
- package/src/state/ssm-prefill-padding.ts +39 -0
- package/src/state/ssm.ts +422 -0
- package/src/state/target-layout.ts +7 -0
- package/src/state/tiered-prefix-cache.ts +45 -0
- package/src/state/training-cache.ts +300 -0
- package/src/state/transitioning-kv-rows.ts +267 -0
- package/src/state/turboquant-attention.ts +97 -0
- package/src/state/turboquant-codec.ts +90 -0
- package/src/state/turboquant-kv.ts +442 -0
- package/src/state/views.ts +26 -0
- package/src/transcription/index.ts +3 -0
- package/src/transcription/silero-vad.ts +379 -0
- package/src/transcription/whisper/decode.ts +773 -0
- package/src/transcription/whisper/format.ts +74 -0
- package/src/transcription/whisper/index.ts +4 -0
- package/src/transcription/whisper/timing.ts +274 -0
- package/src/transcription/whisper/transcribe.ts +394 -0
- package/src/transcription/whisper/types.ts +22 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
import { Dtype } from "@mlx-bun/mlx/ffi";
|
|
3
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
4
|
+
import type { TrellisGeometry } from "./geometry";
|
|
5
|
+
import { HEADER, lutFor, decoderVariant } from "./codebook";
|
|
6
|
+
|
|
7
|
+
import { vectorTrellisExpand, vectorTrellisExpandEligible } from "./vector-expand";
|
|
8
|
+
|
|
9
|
+
const EXPAND_SOURCE = String.raw`
|
|
10
|
+
const uint c = thread_position_in_grid.x;
|
|
11
|
+
const uint r = thread_position_in_grid.y;
|
|
12
|
+
if (c >= (uint)C || r >= (uint)R) return;
|
|
13
|
+
const uint wpb = (uint)(BT * K / 32);
|
|
14
|
+
const uint blk = c / (uint)BT;
|
|
15
|
+
const uint t = c - blk * (uint)BT;
|
|
16
|
+
const device uint32_t* block = codes + (INTERLEAVE
|
|
17
|
+
? (ulong)(blk / 2) * R * 2 * wpb + (ulong)r * 2 * wpb + (blk % 2) * wpb
|
|
18
|
+
: (ulong)r * (C / BT) * wpb + blk * wpb);
|
|
19
|
+
const uint s = trellis_state(block, wpb, t, (uint)BT, (uint)K, (uint)L);
|
|
20
|
+
out[(ulong)r * (uint)C + c] = T(((VARIANT) >= 2 ? lut[s] : (VARIANT) == 1 ? trellis_val_rcp(s) : trellis_val(s)) * float(scales[r]));
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
let kernel: MetalKernel | undefined;
|
|
24
|
+
function expandKernel(): MetalKernel {
|
|
25
|
+
return kernel ??= new MetalKernel({ name: "mlx_bun_trellis_expand",
|
|
26
|
+
inputNames: ["codes", "scales", "lut"], outputNames: ["out"],
|
|
27
|
+
source: EXPAND_SOURCE, header: HEADER, ensureRowContiguous: true });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** Decode the stored matrix ([rows, cols], coded along cols) to `dtype`. */
|
|
31
|
+
export function expandTrellis(codes: MlxArray, scales: MlxArray, g: TrellisGeometry, dtype: Dtype, selected: number): MlxArray {
|
|
32
|
+
if (selected === 13 && vectorTrellisExpandEligible(g, dtype)) return vectorTrellisExpand(codes, scales, g);
|
|
33
|
+
const [out] = expandKernel().apply([codes, scales, lutFor(g.L)], {
|
|
34
|
+
outputs: [{ shape: [g.rows, g.cols], dtype }],
|
|
35
|
+
grid: [g.cols, g.rows, 1],
|
|
36
|
+
threadGroup: [Math.min(256, g.cols), 1, 1],
|
|
37
|
+
templateDtypes: { T: dtype },
|
|
38
|
+
templateInts: { R: g.rows, C: g.cols, BT: g.T, K: g.k, L: g.L,
|
|
39
|
+
VARIANT: decoderVariant(selected), INTERLEAVE: g.blockInterleave ?? 0 },
|
|
40
|
+
});
|
|
41
|
+
return out!;
|
|
42
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
import { Dtype } from "@mlx-bun/mlx/ffi";
|
|
3
|
+
import * as ops from "@mlx-bun/mlx/ops";
|
|
4
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
5
|
+
import type { TrellisWeights } from "./geometry";
|
|
6
|
+
import { HEADER } from "./codebook";
|
|
7
|
+
|
|
8
|
+
// Fused gate/up/SwiGLU for 1..8 activation rows on the simdgroup matrix unit,
|
|
9
|
+
// decoding through a threadgroup codebook (the M1 Max form, where the matrix
|
|
10
|
+
// products issue on the ordinary ALU pipes and the integer decode competes with
|
|
11
|
+
// them). gate-up-mma's fragments, K permutation and accumulation order, so each
|
|
12
|
+
// output is bit for bit gateUpMma's: a simdgroup owns an 8-output-row tile, A
|
|
13
|
+
// column i at step j is position base + 32·i + j, and every lane decodes two
|
|
14
|
+
// contiguous 32-position runs per projection from K+1 words. Each code value y
|
|
15
|
+
// is read from a half table of the 2^L values (every y in [-510, 510] is exact
|
|
16
|
+
// in half) that the threadgroup generates once, in place of the 1MAD
|
|
17
|
+
// arithmetic; the A fragments are half, B and the accumulators float. A
|
|
18
|
+
// window is one bit-field extract: one that straddles a word reads a virtual
|
|
19
|
+
// word (the high half of one word and the low half of the next). Each lane
|
|
20
|
+
// reads its two activation rows from device memory, 16 bytes at a time, with
|
|
21
|
+
// no threadgroup staging or barrier inside the K loop; rows past M repeat the
|
|
22
|
+
// last row and are not written. Measured on the M1 Max at the Qwen MLP shape
|
|
23
|
+
// (17408 x 5120, gate and up together, real weights), 3-bit: 8 rows 0.476 ms
|
|
24
|
+
// against gateUpMma's 1.17, 4 rows 0.465 against 0.795, 2 rows 0.458 against
|
|
25
|
+
// gateUpFactoredRows' 0.664.
|
|
26
|
+
const SG_TG = 4;
|
|
27
|
+
|
|
28
|
+
const RUN_HEADER = String.raw`
|
|
29
|
+
// Words W0 .. W0 + K of run 'run' of a row's codes (the last wraps to the block's first word).
|
|
30
|
+
template <int K, int BT_>
|
|
31
|
+
inline void codebook_mma_run(const device uint32_t* rowCodes, uint run, thread uint* w, thread uint* v) {
|
|
32
|
+
const uint wpb = (uint)(BT_ * K / 32);
|
|
33
|
+
const uint runsPerBlock = (uint)BT_ / 32u;
|
|
34
|
+
const uint blk = run / runsPerBlock;
|
|
35
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
36
|
+
const device uint32_t* bw = rowCodes + blk * wpb;
|
|
37
|
+
const uint w0 = ((uint)BT_ - 32u - t0) * (uint)K / 32u;
|
|
38
|
+
#pragma clang loop unroll(full)
|
|
39
|
+
for (uint i = 0; i < (uint)K; ++i) w[i] = bw[w0 + i];
|
|
40
|
+
w[K] = bw[t0 == 0u ? 0u : w0 + (uint)K];
|
|
41
|
+
// Virtual word i: bits [32i - 16, 32i + 16) of the run.
|
|
42
|
+
#pragma clang loop unroll(full)
|
|
43
|
+
for (uint i = 1; i <= (uint)K; ++i) v[i] = (w[i - 1] >> 16) | (w[i] << 16);
|
|
44
|
+
}
|
|
45
|
+
// The state of position j of a run (bits [(31 - j)·K, +L) of its words), one extract.
|
|
46
|
+
template <int K, int L_>
|
|
47
|
+
inline uint codebook_mma_state(thread const uint* w, thread const uint* v, uint j) {
|
|
48
|
+
const uint b = (31u - j) * (uint)K;
|
|
49
|
+
const uint off = b & 31u;
|
|
50
|
+
if (off + (uint)L_ <= 32u) return (w[b >> 5] >> off) & ((1u << (uint)L_) - 1u);
|
|
51
|
+
const uint vi = (b + 16u) >> 5;
|
|
52
|
+
return (v[vi] >> (b + 16u - 32u * vi)) & ((1u << (uint)L_) - 1u);
|
|
53
|
+
}
|
|
54
|
+
`;
|
|
55
|
+
|
|
56
|
+
const SOURCE = String.raw`
|
|
57
|
+
const uint M = (uint)x_shape[0];
|
|
58
|
+
const uint lane = thread_index_in_simdgroup;
|
|
59
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
60
|
+
threadgroup half codebook[1 << L];
|
|
61
|
+
for (uint i = sg * 32u + lane; i < (1u << (uint)L); i += 32u * (uint)SG_TG) codebook[i] = half(trellis_y_f32(i));
|
|
62
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
63
|
+
const uint n0 = (threadgroup_position_in_grid.y * (uint)SG_TG + sg) * 8u;
|
|
64
|
+
if (n0 >= (uint)R) return;
|
|
65
|
+
const uint fm = ((lane / 4u) & 4u) + ((lane / 2u) % 4u);
|
|
66
|
+
const uint fn = ((lane / 4u) & 2u) * 2u + (lane % 2u) * 2u;
|
|
67
|
+
const uint row = n0 + fm;
|
|
68
|
+
const device uint32_t* gRow = gcodes + (ulong)row * (ulong)((C / BT) * (BT * KG / 32));
|
|
69
|
+
const device uint32_t* uRow = ucodes + (ulong)row * (ulong)((C / BT) * (BT * KU / 32));
|
|
70
|
+
// Activation rows fn and fn + 1 from position 32·fm, 8 values per 16-byte load.
|
|
71
|
+
const device uint4* x0 = (const device uint4*)(x + (ulong)metal::min(fn, M - 1u) * (ulong)C + fm * 32u);
|
|
72
|
+
const device uint4* x1 = (const device uint4*)(x + (ulong)metal::min(fn + 1u, M - 1u) * (ulong)C + fm * 32u);
|
|
73
|
+
metal::simdgroup_float8x8 accG = metal::make_filled_simdgroup_matrix<float, 8, 8>(0.0f);
|
|
74
|
+
metal::simdgroup_float8x8 accU = metal::make_filled_simdgroup_matrix<float, 8, 8>(0.0f);
|
|
75
|
+
for (uint base = 0; base < (uint)C; base += 256u) {
|
|
76
|
+
const uint runA = base / 32u + fn;
|
|
77
|
+
uint ga[KG + 1], gav[KG + 1], gb[KG + 1], gbv[KG + 1];
|
|
78
|
+
uint ua[KU + 1], uav[KU + 1], ub[KU + 1], ubv[KU + 1];
|
|
79
|
+
codebook_mma_run<KG, BT>(gRow, runA, ga, gav);
|
|
80
|
+
codebook_mma_run<KG, BT>(gRow, runA + 1u, gb, gbv);
|
|
81
|
+
codebook_mma_run<KU, BT>(uRow, runA, ua, uav);
|
|
82
|
+
codebook_mma_run<KU, BT>(uRow, runA + 1u, ub, ubv);
|
|
83
|
+
#pragma clang loop unroll(full)
|
|
84
|
+
for (uint s8 = 0; s8 < 4u; ++s8) {
|
|
85
|
+
const uint4 xa = x0[base / 8u + s8], xb = x1[base / 8u + s8];
|
|
86
|
+
#pragma clang loop unroll(full)
|
|
87
|
+
for (uint q = 0; q < 8u; ++q) {
|
|
88
|
+
const uint j = s8 * 8u + q;
|
|
89
|
+
metal::simdgroup_half8x8 aG, aU;
|
|
90
|
+
aG.thread_elements()[0] = codebook[codebook_mma_state<KG, L>(ga, gav, j)];
|
|
91
|
+
aG.thread_elements()[1] = codebook[codebook_mma_state<KG, L>(gb, gbv, j)];
|
|
92
|
+
aU.thread_elements()[0] = codebook[codebook_mma_state<KU, L>(ua, uav, j)];
|
|
93
|
+
aU.thread_elements()[1] = codebook[codebook_mma_state<KU, L>(ub, ubv, j)];
|
|
94
|
+
metal::simdgroup_float8x8 b;
|
|
95
|
+
b.thread_elements()[0] = float(as_type<T>(ushort((q & 1u) ? xa[q / 2u] >> 16 : xa[q / 2u] & 0xFFFFu)));
|
|
96
|
+
b.thread_elements()[1] = float(as_type<T>(ushort((q & 1u) ? xb[q / 2u] >> 16 : xb[q / 2u] & 0xFFFFu)));
|
|
97
|
+
metal::simdgroup_multiply_accumulate(accG, aG, b, accG);
|
|
98
|
+
metal::simdgroup_multiply_accumulate(accU, aU, b, accU);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
const float gs = float(gscales[row]) * TRELLIS_RCP;
|
|
103
|
+
const float us = float(uscales[row]) * TRELLIS_RCP;
|
|
104
|
+
#pragma clang loop unroll(full)
|
|
105
|
+
for (uint j = 0; j < 2u; ++j) {
|
|
106
|
+
const uint m = fn + j;
|
|
107
|
+
if (m >= M) continue;
|
|
108
|
+
const T gateT = T(accG.thread_elements()[j] * gs);
|
|
109
|
+
const T upT = T(accU.thread_elements()[j] * us);
|
|
110
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
111
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
112
|
+
mid[(ulong)m * (ulong)R + row] = T(float(siluT) * float(upT));
|
|
113
|
+
}
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
let kernel: MetalKernel | undefined;
|
|
117
|
+
|
|
118
|
+
/** silu(gate(x))·up(x) for 1..8 bfloat16 or float16 activation rows, each output gateUpMma's bits. Gate and up
|
|
119
|
+
* share their axis-1 geometry (rows a multiple of 8, columns of 256, L at most 12); their bit widths may differ.
|
|
120
|
+
* Borrows x and the weights; returns owned lazy output with x's leading dimensions. */
|
|
121
|
+
export function gateUpCodebookMma(x: MlxArray, gate: TrellisWeights, up: TrellisWeights): MlxArray {
|
|
122
|
+
const g = gate.geometry, u = up.geometry;
|
|
123
|
+
const lead = x.shape.slice(0, -1), M = lead.reduce((a, b) => a * b, 1);
|
|
124
|
+
if (M < 1 || M > 8) throw new Error(`gateUpCodebookMma: M=${M} outside 1..8`);
|
|
125
|
+
if (x.dtype !== Dtype.bfloat16 && x.dtype !== Dtype.float16)
|
|
126
|
+
throw new Error("gateUpCodebookMma: needs bfloat16 or float16 activations");
|
|
127
|
+
if (g.axis !== 1 || u.axis !== 1 || g.rows !== u.rows || g.cols !== u.cols || g.T !== u.T || g.L !== u.L ||
|
|
128
|
+
g.rows % 8 !== 0 || g.cols % 256 !== 0 || g.T % 32 !== 0 || g.L > 12)
|
|
129
|
+
throw new Error("gateUpCodebookMma: unsupported gate/up geometry");
|
|
130
|
+
kernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_codebook_mma", inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales"],
|
|
131
|
+
outputNames: ["mid"], source: SOURCE, header: HEADER + RUN_HEADER, ensureRowContiguous: true });
|
|
132
|
+
using x2 = ops.reshape(x, [M, g.inFeatures]);
|
|
133
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales], {
|
|
134
|
+
outputs: [{ shape: [M, g.rows], dtype: x.dtype }],
|
|
135
|
+
grid: [32 * SG_TG, Math.ceil(g.rows / 8 / SG_TG), 1], threadGroup: [32 * SG_TG, 1, 1],
|
|
136
|
+
templateDtypes: { T: x.dtype },
|
|
137
|
+
templateInts: { R: g.rows, C: g.cols, BT: g.T, KG: g.k, KU: u.k, L: g.L, SG_TG },
|
|
138
|
+
});
|
|
139
|
+
using y = mid!;
|
|
140
|
+
return ops.reshape(y, [...lead, g.rows]);
|
|
141
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
import * as ops from "@mlx-bun/mlx/ops";
|
|
3
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
4
|
+
import type { TrellisWeights } from "./geometry";
|
|
5
|
+
import { CODEBOOK_WINDOW, HEADER } from "./codebook";
|
|
6
|
+
import { TRELLIS_CODEBOOK_ROW_THREADS, TRELLIS_CODEBOOK_ROW_SG_PER_TG } from "./launch";
|
|
7
|
+
import type { MixedGateUpTail } from "./mixed-gate-up";
|
|
8
|
+
|
|
9
|
+
// Fused gate/up/SwiGLU for one activation row over axis-1 Trellis codes whose
|
|
10
|
+
// gate and up widths may differ (KG, KU), decoding through a threadgroup
|
|
11
|
+
// codebook: every code value y·(1/147.8) of the 2^L states, generated once per
|
|
12
|
+
// threadgroup and shared by the rows its 32 SIMD groups take in turn (at most
|
|
13
|
+
// THREADGROUPS threadgroups, so each table serves several rows). Same
|
|
14
|
+
// lanes, runs, accumulation order and f32 code·scale weights as
|
|
15
|
+
// fusedGateUpSwiglu (same widths) and fusedGateUpSwigluMixed (different
|
|
16
|
+
// widths), bit for bit; TAIL selects the mixed kernel's SwiGLU arithmetic (1:
|
|
17
|
+
// MLX's compiled swiglu over the bf16 projections; 0: the float32 sigmoid of
|
|
18
|
+
// the same-width kernel).
|
|
19
|
+
//
|
|
20
|
+
// The threadgroup also stages the activation row, in 16-byte chunks ordered
|
|
21
|
+
// so the 32 lanes of one load read consecutive chunks; a lane reads each
|
|
22
|
+
// chunk of 8 positions just before it uses them (a threadgroup of 1024
|
|
23
|
+
// threads fits an M1 Max core only below 53 registers per thread). Each window
|
|
24
|
+
// is one bit-field extract (CODEBOOK_WINDOW, codebook.ts); code words are
|
|
25
|
+
// addressed by 32-bit offsets.
|
|
26
|
+
const SOURCE = String.raw`
|
|
27
|
+
threadgroup float codebook[1 << L];
|
|
28
|
+
threadgroup uint4 xs[C / 8];
|
|
29
|
+
constexpr uint N_RUNS = (uint)C / 32u;
|
|
30
|
+
for (uint i = thread_position_in_threadgroup.x; i < (1u << (uint)L); i += (uint)THREADS)
|
|
31
|
+
codebook[i] = trellis_unrefined_bits_y(trellis_y(i));
|
|
32
|
+
// Chunk q (positions 8q..8q+7) of run r at q·N_RUNS + r.
|
|
33
|
+
for (uint c = thread_position_in_threadgroup.x; c < (uint)C / 8u; c += (uint)THREADS)
|
|
34
|
+
xs[c] = ((const device uint4*)x)[(c % N_RUNS) * 4u + c / N_RUNS];
|
|
35
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
36
|
+
const threadgroup uchar* table = (const threadgroup uchar*)codebook;
|
|
37
|
+
const uint lane = thread_index_in_simdgroup;
|
|
38
|
+
const uint gWpb = (uint)(BT * KG / 32);
|
|
39
|
+
const uint uWpb = (uint)(BT * KU / 32);
|
|
40
|
+
const uint runsPerBlock = (uint)BT / 32u;
|
|
41
|
+
const uint rowStep = threadgroups_per_grid.y * (uint)ROWS_TG;
|
|
42
|
+
for (uint row = thread_position_in_grid.y * (uint)ROWS_TG + simdgroup_index_in_threadgroup; row < (uint)R; row += rowStep) {
|
|
43
|
+
const uint gRow = row * (uint)((C / BT) * gWpb);
|
|
44
|
+
const uint uRow = row * (uint)((C / BT) * uWpb);
|
|
45
|
+
const float gScale = float(gscales[row]);
|
|
46
|
+
const float uScale = float(uscales[row]);
|
|
47
|
+
float gAcc = 0.0f, gAcc2 = 0.0f, uAcc = 0.0f, uAcc2 = 0.0f;
|
|
48
|
+
for (uint run = lane; run < N_RUNS; run += 32u) {
|
|
49
|
+
const uint blk = run / runsPerBlock;
|
|
50
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
51
|
+
const uint gw = gRow + blk * gWpb, uw = uRow + blk * uWpb;
|
|
52
|
+
const uint gW0 = ((uint)BT - 32u - t0) * (uint)KG / 32u;
|
|
53
|
+
const uint uW0 = ((uint)BT - 32u - t0) * (uint)KU / 32u;
|
|
54
|
+
uint g[KG + 1], gv[KG + 1];
|
|
55
|
+
uint u[KU + 1], uv[KU + 1];
|
|
56
|
+
// Words W0 .. W0 + K - 1 stay in the block; the next word wraps to the block's first for its last run.
|
|
57
|
+
#pragma clang loop unroll(full)
|
|
58
|
+
for (uint i = 0; i < (uint)KG; ++i) g[i] = gcodes[gw + gW0 + i];
|
|
59
|
+
g[KG] = gcodes[gw + (t0 == 0u ? 0u : gW0 + (uint)KG)];
|
|
60
|
+
#pragma clang loop unroll(full)
|
|
61
|
+
for (uint i = 0; i < (uint)KU; ++i) u[i] = ucodes[uw + uW0 + i];
|
|
62
|
+
u[KU] = ucodes[uw + (t0 == 0u ? 0u : uW0 + (uint)KU)];
|
|
63
|
+
// Virtual words: bits [32i - 16, 32i + 16) of the run's words (only the ignored bits below word 0 are absent).
|
|
64
|
+
gv[0] = g[0] << 16;
|
|
65
|
+
uv[0] = u[0] << 16;
|
|
66
|
+
#pragma clang loop unroll(full)
|
|
67
|
+
for (uint i = 1; i <= (uint)KG; ++i) gv[i] = (g[i - 1] >> 16) | (g[i] << 16);
|
|
68
|
+
#pragma clang loop unroll(full)
|
|
69
|
+
for (uint i = 1; i <= (uint)KU; ++i) uv[i] = (u[i - 1] >> 16) | (u[i] << 16);
|
|
70
|
+
#pragma clang loop unroll(full)
|
|
71
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
72
|
+
const uint4 chunk = xs[q * N_RUNS + run];
|
|
73
|
+
#pragma clang loop unroll(full)
|
|
74
|
+
for (uint p = 0; p < 8u; ++p) {
|
|
75
|
+
const uint j = q * 8u + p;
|
|
76
|
+
// The bf16 in either half of a word, as the float of its bits.
|
|
77
|
+
const float xv = as_type<float>((p & 1u) ? chunk[p >> 1] & 0xFFFF0000u : chunk[p >> 1] << 16);
|
|
78
|
+
const float gWeight = trellis_codebook_window(table, g, gv, (31u - j) * (uint)KG, (uint)L) * gScale;
|
|
79
|
+
const float uWeight = trellis_codebook_window(table, u, uv, (31u - j) * (uint)KU, (uint)L) * uScale;
|
|
80
|
+
if (j & 1u) { gAcc2 = metal::fma(gWeight, xv, gAcc2); uAcc2 = metal::fma(uWeight, xv, uAcc2); }
|
|
81
|
+
else { gAcc = metal::fma(gWeight, xv, gAcc); uAcc = metal::fma(uWeight, xv, uAcc); }
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
const float gate = metal::simd_sum(gAcc + gAcc2);
|
|
86
|
+
const float up = metal::simd_sum(uAcc + uAcc2);
|
|
87
|
+
if (lane == 0u) {
|
|
88
|
+
const T gateT = T(gate);
|
|
89
|
+
const T upT = T(up);
|
|
90
|
+
if ((TAIL) == 1) {
|
|
91
|
+
const T sigY = 1 / (1 + metal::exp(metal::abs(gateT)));
|
|
92
|
+
const T sigmoidT = (gateT < 0) ? sigY : 1 - sigY;
|
|
93
|
+
const T siluT = gateT * sigmoidT;
|
|
94
|
+
mid[row] = siluT * upT;
|
|
95
|
+
} else {
|
|
96
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
97
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
98
|
+
mid[row] = T(float(siluT) * float(upT));
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
`;
|
|
103
|
+
|
|
104
|
+
/** Threadgroups at most: five per M1 Max GPU core, measured against 128 to 256 (the codebook generated 544 times per
|
|
105
|
+
* projection at the artifact's 17408 rows otherwise). */
|
|
106
|
+
const THREADGROUPS = 160;
|
|
107
|
+
|
|
108
|
+
let kernel: MetalKernel | undefined;
|
|
109
|
+
|
|
110
|
+
/** silu(gate(x))·up(x) for exactly one activation row over matching axis-1
|
|
111
|
+
* geometry (L at most 12, at most 8192 bf16 inputs; the bit widths may differ). `tail` applies where the
|
|
112
|
+
* widths differ; same widths take the float32 sigmoid. Borrows x and the
|
|
113
|
+
* weights; returns owned lazy output with x's leading dimensions. */
|
|
114
|
+
export function gateUpCodebookRow(x: MlxArray, gate: TrellisWeights, up: TrellisWeights, tail: MixedGateUpTail): MlxArray {
|
|
115
|
+
const g = gate.geometry, u = up.geometry;
|
|
116
|
+
if (g.axis !== 1 || u.axis !== 1 || g.rows !== u.rows || g.cols !== u.cols || g.T !== u.T || g.L !== u.L || g.L > 12)
|
|
117
|
+
throw new Error("gateUpCodebookRow: gate and up need matching axis-1 geometry with L <= 12");
|
|
118
|
+
if (x.size !== x.shape.at(-1)) throw new Error("gateUpCodebookRow: expects one activation row");
|
|
119
|
+
if ((4 << g.L) + 2 * g.cols > 32768) throw new Error("gateUpCodebookRow: the codebook and staged row exceed 32 KiB of threadgroup memory");
|
|
120
|
+
kernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_codebook_row",
|
|
121
|
+
inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales"], outputNames: ["mid"],
|
|
122
|
+
source: SOURCE, header: HEADER + CODEBOOK_WINDOW, ensureRowContiguous: true });
|
|
123
|
+
const lead = x.shape.slice(0, -1);
|
|
124
|
+
const x2 = ops.reshape(x, [1, g.inFeatures]);
|
|
125
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales], {
|
|
126
|
+
outputs: [{ shape: [1, g.rows], dtype: x.dtype }],
|
|
127
|
+
grid: [TRELLIS_CODEBOOK_ROW_THREADS, Math.min(THREADGROUPS, Math.ceil(g.rows / TRELLIS_CODEBOOK_ROW_SG_PER_TG)), 1],
|
|
128
|
+
threadGroup: [TRELLIS_CODEBOOK_ROW_THREADS, 1, 1],
|
|
129
|
+
templateDtypes: { T: x.dtype },
|
|
130
|
+
templateInts: { R: g.rows, C: g.cols, BT: g.T, KG: g.k, KU: u.k, L: g.L, ROWS_TG: TRELLIS_CODEBOOK_ROW_SG_PER_TG,
|
|
131
|
+
THREADS: TRELLIS_CODEBOOK_ROW_THREADS, TAIL: g.k !== u.k && tail === "split" ? 1 : 0 },
|
|
132
|
+
});
|
|
133
|
+
x2.dispose();
|
|
134
|
+
const out = ops.reshape(mid!, [...lead, g.rows]);
|
|
135
|
+
mid!.dispose();
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
import * as ops from "@mlx-bun/mlx/ops";
|
|
3
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
4
|
+
import type { TrellisWeights } from "./geometry";
|
|
5
|
+
import { HEADER } from "./codebook";
|
|
6
|
+
import { TRELLIS_THREADS, TRELLIS_SG_PER_TG } from "./launch";
|
|
7
|
+
|
|
8
|
+
// Fused gate/up/SwiGLU over same-width axis-1 Trellis codes with the row scale
|
|
9
|
+
// factored out: each weight contributes its code value y (trellis_y_f32), and
|
|
10
|
+
// scale·(1/147.8) multiplies each output once after the reduction. Same lanes
|
|
11
|
+
// and runs as fusedGateUpSwiglu; reassociated relative to its f32 code·scale
|
|
12
|
+
// weights (not bit-identical; gate by KL).
|
|
13
|
+
|
|
14
|
+
// One activation row; two accumulators per projection (even/odd positions).
|
|
15
|
+
const ROW_SOURCE = String.raw`
|
|
16
|
+
const uint lane = thread_index_in_simdgroup;
|
|
17
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
18
|
+
const uint row = thread_position_in_grid.y * (uint)ROWS_TG + sg;
|
|
19
|
+
if (row >= (uint)R) return;
|
|
20
|
+
const uint wpb = (uint)(BT * K / 32);
|
|
21
|
+
const uint runsPerBlock = (uint)BT / 32u;
|
|
22
|
+
const uint nRuns = (uint)C / 32u;
|
|
23
|
+
const ulong rowWords = (ulong)((C / BT) * wpb);
|
|
24
|
+
const device uint32_t* gRow = gcodes + (ulong)row * rowWords;
|
|
25
|
+
const device uint32_t* uRow = ucodes + (ulong)row * rowWords;
|
|
26
|
+
const float gScale = float(gscales[row]);
|
|
27
|
+
const float uScale = float(uscales[row]);
|
|
28
|
+
float gAcc = 0.0f, gAcc2 = 0.0f;
|
|
29
|
+
float uAcc = 0.0f, uAcc2 = 0.0f;
|
|
30
|
+
for (uint run = lane; run < nRuns; run += 32u) {
|
|
31
|
+
const uint blk = run / runsPerBlock;
|
|
32
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
33
|
+
const device uint32_t* gw = gRow + blk * wpb;
|
|
34
|
+
const device uint32_t* uw = uRow + blk * wpb;
|
|
35
|
+
const uint w0 = ((uint)BT - 32u - t0) * (uint)K / 32u;
|
|
36
|
+
uint g[K + 1];
|
|
37
|
+
uint u[K + 1];
|
|
38
|
+
#pragma clang loop unroll(full)
|
|
39
|
+
for (uint i = 0; i <= (uint)K; ++i) {
|
|
40
|
+
const uint wi = w0 + i;
|
|
41
|
+
const uint idx = wi >= wpb ? wi - wpb : wi;
|
|
42
|
+
g[i] = gw[idx];
|
|
43
|
+
u[i] = uw[idx];
|
|
44
|
+
}
|
|
45
|
+
const uint c0 = blk * (uint)BT + t0;
|
|
46
|
+
const device metal::vec<T, 4>* x4 = (const device metal::vec<T, 4>*)(x + c0);
|
|
47
|
+
#pragma clang loop unroll(full)
|
|
48
|
+
for (uint j4 = 0; j4 < 8u; ++j4) {
|
|
49
|
+
const float4 xv4 = float4(x4[j4]);
|
|
50
|
+
#pragma clang loop unroll(full)
|
|
51
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
52
|
+
const uint j = j4 * 4u + q;
|
|
53
|
+
const uint b = (31u - j) * (uint)K;
|
|
54
|
+
const uint wi = b >> 5;
|
|
55
|
+
const uint off = b & 31u;
|
|
56
|
+
uint gwin = g[wi] >> off;
|
|
57
|
+
uint uwin = u[wi] >> off;
|
|
58
|
+
if (off + (uint)L > 32u) { gwin |= g[wi + 1] << (32u - off); uwin |= u[wi + 1] << (32u - off); }
|
|
59
|
+
gwin &= (1u << (uint)L) - 1u;
|
|
60
|
+
uwin &= (1u << (uint)L) - 1u;
|
|
61
|
+
const float xv = xv4[q];
|
|
62
|
+
const float gv = trellis_y_f32(gwin);
|
|
63
|
+
const float uv = trellis_y_f32(uwin);
|
|
64
|
+
if (q & 1u) { gAcc2 = metal::fma(gv, xv, gAcc2); uAcc2 = metal::fma(uv, xv, uAcc2); }
|
|
65
|
+
else { gAcc = metal::fma(gv, xv, gAcc); uAcc = metal::fma(uv, xv, uAcc); }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
const float gate = metal::simd_sum(gAcc + gAcc2) * (gScale * TRELLIS_RCP);
|
|
70
|
+
const float up = metal::simd_sum(uAcc + uAcc2) * (uScale * TRELLIS_RCP);
|
|
71
|
+
if (lane == 0u) {
|
|
72
|
+
const T gateT = T(gate);
|
|
73
|
+
const T upT = T(up);
|
|
74
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
75
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
76
|
+
mid[row] = T(float(siluT) * float(upT));
|
|
77
|
+
}
|
|
78
|
+
`;
|
|
79
|
+
|
|
80
|
+
// M activation rows share each decoded weight; one accumulator per row and
|
|
81
|
+
// projection (the rows supply the independent FMA chains).
|
|
82
|
+
const ROWS_SOURCE = String.raw`
|
|
83
|
+
const uint lane = thread_index_in_simdgroup;
|
|
84
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
85
|
+
const uint row = thread_position_in_grid.y * (uint)ROWS_TG + sg;
|
|
86
|
+
if (row >= (uint)R) return;
|
|
87
|
+
const uint wpb = (uint)(BT * K / 32);
|
|
88
|
+
const uint runsPerBlock = (uint)BT / 32u;
|
|
89
|
+
const uint nRuns = (uint)C / 32u;
|
|
90
|
+
const ulong rowWords = (ulong)((C / BT) * wpb);
|
|
91
|
+
const device uint32_t* gRow = gcodes + (ulong)row * rowWords;
|
|
92
|
+
const device uint32_t* uRow = ucodes + (ulong)row * rowWords;
|
|
93
|
+
const float gScale = float(gscales[row]);
|
|
94
|
+
const float uScale = float(uscales[row]);
|
|
95
|
+
float gAcc[M], uAcc[M];
|
|
96
|
+
#pragma clang loop unroll(full)
|
|
97
|
+
for (uint m = 0; m < (uint)M; ++m) { gAcc[m] = 0.0f; uAcc[m] = 0.0f; }
|
|
98
|
+
for (uint run = lane; run < nRuns; run += 32u) {
|
|
99
|
+
const uint blk = run / runsPerBlock;
|
|
100
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
101
|
+
const device uint32_t* gw = gRow + blk * wpb;
|
|
102
|
+
const device uint32_t* uw = uRow + blk * wpb;
|
|
103
|
+
const uint w0 = ((uint)BT - 32u - t0) * (uint)K / 32u;
|
|
104
|
+
uint g[K + 1];
|
|
105
|
+
uint u[K + 1];
|
|
106
|
+
#pragma clang loop unroll(full)
|
|
107
|
+
for (uint i = 0; i <= (uint)K; ++i) {
|
|
108
|
+
const uint wi = w0 + i;
|
|
109
|
+
const uint idx = wi >= wpb ? wi - wpb : wi;
|
|
110
|
+
g[i] = gw[idx];
|
|
111
|
+
u[i] = uw[idx];
|
|
112
|
+
}
|
|
113
|
+
const uint c0 = blk * (uint)BT + t0;
|
|
114
|
+
#pragma clang loop unroll(full)
|
|
115
|
+
for (uint j4 = 0; j4 < 8u; ++j4) {
|
|
116
|
+
float4 xv4[M];
|
|
117
|
+
#pragma clang loop unroll(full)
|
|
118
|
+
for (uint m = 0; m < (uint)M; ++m)
|
|
119
|
+
xv4[m] = float4(((const device metal::vec<T, 4>*)(x + (ulong)m * (ulong)C + c0))[j4]);
|
|
120
|
+
#pragma clang loop unroll(full)
|
|
121
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
122
|
+
const uint j = j4 * 4u + q;
|
|
123
|
+
const uint b = (31u - j) * (uint)K;
|
|
124
|
+
const uint wi = b >> 5;
|
|
125
|
+
const uint off = b & 31u;
|
|
126
|
+
uint gwin = g[wi] >> off;
|
|
127
|
+
uint uwin = u[wi] >> off;
|
|
128
|
+
if (off + (uint)L > 32u) { gwin |= g[wi + 1] << (32u - off); uwin |= u[wi + 1] << (32u - off); }
|
|
129
|
+
gwin &= (1u << (uint)L) - 1u;
|
|
130
|
+
uwin &= (1u << (uint)L) - 1u;
|
|
131
|
+
const float gv = trellis_y_f32(gwin);
|
|
132
|
+
const float uv = trellis_y_f32(uwin);
|
|
133
|
+
#pragma clang loop unroll(full)
|
|
134
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
135
|
+
const float xv = xv4[m][q];
|
|
136
|
+
gAcc[m] = metal::fma(gv, xv, gAcc[m]); uAcc[m] = metal::fma(uv, xv, uAcc[m]);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
#pragma clang loop unroll(full)
|
|
142
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
143
|
+
const float gate = metal::simd_sum(gAcc[m]) * (gScale * TRELLIS_RCP);
|
|
144
|
+
const float up = metal::simd_sum(uAcc[m]) * (uScale * TRELLIS_RCP);
|
|
145
|
+
if (lane == 0u) {
|
|
146
|
+
const T gateT = T(gate);
|
|
147
|
+
const T upT = T(up);
|
|
148
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
149
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
150
|
+
mid[(ulong)m * (ulong)R + row] = T(float(siluT) * float(upT));
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
`;
|
|
154
|
+
|
|
155
|
+
const INPUTS = ["x", "gcodes", "gscales", "ucodes", "uscales"];
|
|
156
|
+
let rowKernel: MetalKernel | undefined, rowsKernel: MetalKernel | undefined;
|
|
157
|
+
|
|
158
|
+
function check(name: string, gate: TrellisWeights, up: TrellisWeights): void {
|
|
159
|
+
const a = gate.geometry, b = up.geometry;
|
|
160
|
+
if (a.axis !== 1 || b.axis !== 1 || a.k !== b.k || a.rows !== b.rows || a.cols !== b.cols || a.T !== b.T || a.L !== b.L)
|
|
161
|
+
throw new Error(`${name}: gate and up need the same axis-1 geometry`);
|
|
162
|
+
}
|
|
163
|
+
function launch(kernel: MetalKernel, x: MlxArray, gate: TrellisWeights, up: TrellisWeights, M: number): MlxArray {
|
|
164
|
+
const g = gate.geometry, lead = x.shape.slice(0, -1);
|
|
165
|
+
const x2 = ops.reshape(x, [M, g.inFeatures]);
|
|
166
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales], {
|
|
167
|
+
outputs: [{ shape: [M, g.rows], dtype: x.dtype }],
|
|
168
|
+
grid: [TRELLIS_THREADS, Math.ceil(g.rows / TRELLIS_SG_PER_TG), 1],
|
|
169
|
+
threadGroup: [TRELLIS_THREADS, 1, 1],
|
|
170
|
+
templateDtypes: { T: x.dtype },
|
|
171
|
+
templateInts: { M, R: g.rows, C: g.cols, BT: g.T, K: g.k, L: g.L, ROWS_TG: TRELLIS_SG_PER_TG },
|
|
172
|
+
});
|
|
173
|
+
x2.dispose();
|
|
174
|
+
const out = ops.reshape(mid!, [...lead, g.rows]);
|
|
175
|
+
mid!.dispose();
|
|
176
|
+
return out;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** silu(gate(x))·up(x) for exactly one activation row. Borrows x and the
|
|
180
|
+
* weights; returns owned lazy output with x's leading dimensions. */
|
|
181
|
+
export function gateUpFactoredRow(x: MlxArray, gate: TrellisWeights, up: TrellisWeights): MlxArray {
|
|
182
|
+
check("gateUpFactoredRow", gate, up);
|
|
183
|
+
if (x.size !== x.shape.at(-1)) throw new Error("gateUpFactoredRow: expects one activation row");
|
|
184
|
+
rowKernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_factored_row", inputNames: INPUTS,
|
|
185
|
+
outputNames: ["mid"], source: ROW_SOURCE, header: HEADER, ensureRowContiguous: true });
|
|
186
|
+
return launch(rowKernel, x, gate, up, 1);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** silu(gate(x))·up(x) for 2..4 activation rows sharing each decoded weight. */
|
|
190
|
+
export function gateUpFactoredRows(x: MlxArray, gate: TrellisWeights, up: TrellisWeights): MlxArray {
|
|
191
|
+
check("gateUpFactoredRows", gate, up);
|
|
192
|
+
const M = x.size / x.shape.at(-1)!;
|
|
193
|
+
if (M < 2 || M > 4) throw new Error(`gateUpFactoredRows: M=${M} outside 2..4`);
|
|
194
|
+
rowsKernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_factored_rows", inputNames: INPUTS,
|
|
195
|
+
outputNames: ["mid"], source: ROWS_SOURCE, header: HEADER, ensureRowContiguous: true });
|
|
196
|
+
return launch(rowsKernel, x, gate, up, M);
|
|
197
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
import * as ops from "@mlx-bun/mlx/ops";
|
|
3
|
+
import { MetalKernel } from "@mlx-bun/mlx/metal-kernel";
|
|
4
|
+
import type { TrellisWeights } from "./geometry";
|
|
5
|
+
import { HEADER } from "./codebook";
|
|
6
|
+
|
|
7
|
+
// Fused gate/up/SwiGLU on the simdgroup matrix unit for any number of
|
|
8
|
+
// activation rows: gate-up-mma's fragments, decode and accumulation (each
|
|
9
|
+
// output row bit for bit the same), with every decoded weight fragment feeding
|
|
10
|
+
// an MMA for MT blocks of 8 rows. A threadgroup of SG_TG simdgroups (8 output
|
|
11
|
+
// rows each) generates the 2^L code values y once into a threadgroup codebook
|
|
12
|
+
// (half: every y in [-510, 510] is exact) and stages the activations of its
|
|
13
|
+
// 8·MT rows over each 256-position K step in threadgroup memory, where every
|
|
14
|
+
// simdgroup reads its B fragments; grid z walks chunks of 8·MT rows. The row
|
|
15
|
+
// count is read at run time (one pipeline per geometry and MT). Measured on
|
|
16
|
+
// the M1 Max at the Qwen MLP shape (17408 x 5120, 3-bit): 9 rows 1.01 ms, 16
|
|
17
|
+
// 0.98, 24 1.52, 32 1.87, 64 3.68, 128 7.22 for gate and up together,
|
|
18
|
+
// against 11.3, 10.9, 10.9, 9.5 (the prefill tiles), 5.3 and 8.1 (weight
|
|
19
|
+
// expansion and GEMM).
|
|
20
|
+
const SG_TG = 8;
|
|
21
|
+
|
|
22
|
+
const RUN_HEADER = String.raw`
|
|
23
|
+
template <int K, int BT_>
|
|
24
|
+
inline void load_run(const device uint32_t* rowCodes, uint run, thread uint* w) {
|
|
25
|
+
const uint wpb = (uint)(BT_ * K / 32);
|
|
26
|
+
const uint runsPerBlock = (uint)BT_ / 32u;
|
|
27
|
+
const uint blk = run / runsPerBlock;
|
|
28
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
29
|
+
const device uint32_t* bw = rowCodes + blk * wpb;
|
|
30
|
+
const uint w0 = ((uint)BT_ - 32u - t0) * (uint)K / 32u;
|
|
31
|
+
#pragma clang loop unroll(full)
|
|
32
|
+
for (uint i = 0; i <= (uint)K; ++i) {
|
|
33
|
+
const uint wi = w0 + i;
|
|
34
|
+
w[i] = bw[wi >= wpb ? wi - wpb : wi];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
template <int K, int L_>
|
|
38
|
+
inline uint run_state(thread const uint* w, uint j) {
|
|
39
|
+
const uint b = (31u - j) * (uint)K;
|
|
40
|
+
const uint wi = b >> 5;
|
|
41
|
+
const uint off = b & 31u;
|
|
42
|
+
uint win = w[wi] >> off;
|
|
43
|
+
if (off + (uint)L_ > 32u) win |= w[wi + 1] << (32u - off);
|
|
44
|
+
return win & ((1u << (uint)L_) - 1u);
|
|
45
|
+
}
|
|
46
|
+
`;
|
|
47
|
+
|
|
48
|
+
const SOURCE = String.raw`
|
|
49
|
+
const uint M = (uint)x_shape[0];
|
|
50
|
+
const uint lane = thread_index_in_simdgroup;
|
|
51
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
52
|
+
const uint tid = sg * 32u + lane;
|
|
53
|
+
threadgroup half codebook[1 << L];
|
|
54
|
+
threadgroup T xs[8 * MT][256];
|
|
55
|
+
for (uint i = tid; i < (1u << (uint)L); i += 32u * (uint)SG_TG) codebook[i] = half(trellis_y_f32(i));
|
|
56
|
+
const uint n0 = (threadgroup_position_in_grid.y * (uint)SG_TG + sg) * 8u;
|
|
57
|
+
const uint fm = ((lane / 4u) & 4u) + ((lane / 2u) % 4u);
|
|
58
|
+
const uint fn = ((lane / 4u) & 2u) * 2u + (lane % 2u) * 2u;
|
|
59
|
+
// A simdgroup past the last output row still stages its share and meets every barrier; it writes nothing.
|
|
60
|
+
const uint row = metal::min(n0 + fm, (uint)R - 1u);
|
|
61
|
+
const device uint32_t* gRow = gcodes + (ulong)row * (ulong)((C / BT) * (BT * KG / 32));
|
|
62
|
+
const device uint32_t* uRow = ucodes + (ulong)row * (ulong)((C / BT) * (BT * KU / 32));
|
|
63
|
+
const uint mBase = threadgroup_position_in_grid.z * 8u * (uint)MT;
|
|
64
|
+
metal::simdgroup_float8x8 accG[MT], accU[MT];
|
|
65
|
+
#pragma clang loop unroll(full)
|
|
66
|
+
for (uint bk = 0; bk < (uint)MT; ++bk) {
|
|
67
|
+
accG[bk] = metal::make_filled_simdgroup_matrix<float, 8, 8>(0.0f);
|
|
68
|
+
accU[bk] = metal::make_filled_simdgroup_matrix<float, 8, 8>(0.0f);
|
|
69
|
+
}
|
|
70
|
+
for (uint base = 0; base < (uint)C; base += 256u) {
|
|
71
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
72
|
+
for (uint e = tid; e < 8u * (uint)MT * 64u; e += 32u * (uint)SG_TG) {
|
|
73
|
+
const uint r = e / 64u, c4 = e % 64u, m = mBase + r;
|
|
74
|
+
const metal::vec<T, 4> v = m < M ? ((const device metal::vec<T, 4>*)(x + (ulong)m * (ulong)C + base))[c4]
|
|
75
|
+
: metal::vec<T, 4>(0);
|
|
76
|
+
*((threadgroup metal::vec<T, 4>*)(&xs[r][c4 * 4u])) = v;
|
|
77
|
+
}
|
|
78
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
79
|
+
const uint runA = base / 32u + fn;
|
|
80
|
+
uint ga[KG + 1], gb[KG + 1], ua[KU + 1], ub[KU + 1];
|
|
81
|
+
load_run<KG, BT>(gRow, runA, ga);
|
|
82
|
+
load_run<KG, BT>(gRow, runA + 1u, gb);
|
|
83
|
+
load_run<KU, BT>(uRow, runA, ua);
|
|
84
|
+
load_run<KU, BT>(uRow, runA + 1u, ub);
|
|
85
|
+
#pragma clang loop unroll(full)
|
|
86
|
+
for (uint j = 0; j < 32u; ++j) {
|
|
87
|
+
metal::simdgroup_float8x8 aG, aU;
|
|
88
|
+
aG.thread_elements()[0] = float(codebook[run_state<KG, L>(ga, j)]);
|
|
89
|
+
aG.thread_elements()[1] = float(codebook[run_state<KG, L>(gb, j)]);
|
|
90
|
+
aU.thread_elements()[0] = float(codebook[run_state<KU, L>(ua, j)]);
|
|
91
|
+
aU.thread_elements()[1] = float(codebook[run_state<KU, L>(ub, j)]);
|
|
92
|
+
#pragma clang loop unroll(full)
|
|
93
|
+
for (uint bk = 0; bk < (uint)MT; ++bk) {
|
|
94
|
+
metal::simdgroup_float8x8 b;
|
|
95
|
+
b.thread_elements()[0] = float(xs[8u * bk + fn][fm * 32u + j]);
|
|
96
|
+
b.thread_elements()[1] = float(xs[8u * bk + fn + 1u][fm * 32u + j]);
|
|
97
|
+
metal::simdgroup_multiply_accumulate(accG[bk], aG, b, accG[bk]);
|
|
98
|
+
metal::simdgroup_multiply_accumulate(accU[bk], aU, b, accU[bk]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (n0 >= (uint)R) return;
|
|
103
|
+
const float gs = float(gscales[row]) * TRELLIS_RCP;
|
|
104
|
+
const float us = float(uscales[row]) * TRELLIS_RCP;
|
|
105
|
+
#pragma clang loop unroll(full)
|
|
106
|
+
for (uint bk = 0; bk < (uint)MT; ++bk)
|
|
107
|
+
#pragma clang loop unroll(full)
|
|
108
|
+
for (uint j = 0; j < 2u; ++j) {
|
|
109
|
+
const uint m = mBase + 8u * bk + fn + j;
|
|
110
|
+
if (m >= M) continue;
|
|
111
|
+
const T gateT = T(accG[bk].thread_elements()[j] * gs);
|
|
112
|
+
const T upT = T(accU[bk].thread_elements()[j] * us);
|
|
113
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
114
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
115
|
+
mid[(ulong)m * (ulong)R + row] = T(float(siluT) * float(upT));
|
|
116
|
+
}
|
|
117
|
+
`;
|
|
118
|
+
|
|
119
|
+
let kernel: MetalKernel | undefined;
|
|
120
|
+
|
|
121
|
+
/** Row blocks per pass for M rows: two (16 rows), or three where three blocks of 8 cover them (17..24 rows: 1.52
|
|
122
|
+
* against 1.64 ms for three passes of one block and 1.86 for two of two). */
|
|
123
|
+
function rowBlocks(M: number): number { return Math.ceil(M / 8) === 3 ? 3 : 2; }
|
|
124
|
+
|
|
125
|
+
/** silu(gate(x))·up(x) for any number of activation rows. Gate and up share their axis-1 geometry (rows a multiple
|
|
126
|
+
* of 8, columns of 256, L at most 12); their bit widths may differ. Borrows x and the weights; returns owned lazy
|
|
127
|
+
* output with x's leading dimensions. */
|
|
128
|
+
export function gateUpMmaWide(x: MlxArray, gate: TrellisWeights, up: TrellisWeights): MlxArray {
|
|
129
|
+
const g = gate.geometry, u = up.geometry;
|
|
130
|
+
const lead = x.shape.slice(0, -1), M = lead.reduce((a, b) => a * b, 1);
|
|
131
|
+
if (M < 1) throw new Error("gateUpMmaWide: no rows");
|
|
132
|
+
if (g.axis !== 1 || u.axis !== 1 || g.rows !== u.rows || g.cols !== u.cols || g.T !== u.T || g.L !== u.L ||
|
|
133
|
+
g.rows % 8 !== 0 || g.cols % 256 !== 0 || g.T % 32 !== 0 || g.L > 12)
|
|
134
|
+
throw new Error("gateUpMmaWide: unsupported gate/up geometry");
|
|
135
|
+
kernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_mma_wide", inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales"],
|
|
136
|
+
outputNames: ["mid"], source: SOURCE, header: HEADER + RUN_HEADER, ensureRowContiguous: true });
|
|
137
|
+
const MT = rowBlocks(M);
|
|
138
|
+
using x2 = ops.reshape(x, [M, g.inFeatures]);
|
|
139
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales], {
|
|
140
|
+
outputs: [{ shape: [M, g.rows], dtype: x.dtype }],
|
|
141
|
+
grid: [32 * SG_TG, Math.ceil(g.rows / 8 / SG_TG), Math.ceil(M / (8 * MT))], threadGroup: [32 * SG_TG, 1, 1],
|
|
142
|
+
templateDtypes: { T: x.dtype },
|
|
143
|
+
templateInts: { R: g.rows, C: g.cols, BT: g.T, KG: g.k, KU: u.k, L: g.L, SG_TG, MT },
|
|
144
|
+
});
|
|
145
|
+
using y = mid!;
|
|
146
|
+
return ops.reshape(y, [...lead, g.rows]);
|
|
147
|
+
}
|