@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,148 @@
|
|
|
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
|
+
// Verify-width fused gate/up/SwiGLU on the simdgroup matrix unit: one
|
|
8
|
+
// simdgroup owns an 8-output-row tile for up to 8 activation rows. The K index
|
|
9
|
+
// inside each 8x8 step is permuted so that A column i at step s is position
|
|
10
|
+
// base + 32·i + s: every lane decodes two contiguous 32-position runs per
|
|
11
|
+
// projection from K+1 words (the matvec's word window, unrolled) straight into
|
|
12
|
+
// its A fragment and reads its two activation rows contiguously, so per-weight
|
|
13
|
+
// decode work matches the one-row matvec. Raw code values y accumulate in f32;
|
|
14
|
+
// scale·(1/147.8) applies once per output. Gate and up may differ in bit width.
|
|
15
|
+
// Not bit-identical to the per-lane matvec reduction (different summation
|
|
16
|
+
// order); gate it by KL. Fragment coordinates follow MLX steel's Metal layout.
|
|
17
|
+
const SG_TG = 4, MT = 1;
|
|
18
|
+
|
|
19
|
+
const RUN3_HEADER = String.raw`
|
|
20
|
+
template <int K, int BT_>
|
|
21
|
+
inline void load_run(const device uint32_t* rowCodes, uint run, thread uint* w) {
|
|
22
|
+
const uint wpb = (uint)(BT_ * K / 32);
|
|
23
|
+
const uint runsPerBlock = (uint)BT_ / 32u;
|
|
24
|
+
const uint blk = run / runsPerBlock;
|
|
25
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
26
|
+
const device uint32_t* bw = rowCodes + blk * wpb;
|
|
27
|
+
const uint w0 = ((uint)BT_ - 32u - t0) * (uint)K / 32u;
|
|
28
|
+
#pragma clang loop unroll(full)
|
|
29
|
+
for (uint i = 0; i <= (uint)K; ++i) {
|
|
30
|
+
const uint wi = w0 + i;
|
|
31
|
+
w[i] = bw[wi >= wpb ? wi - wpb : wi];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
template <int K, int L_>
|
|
35
|
+
inline uint run_state(thread const uint* w, uint j) {
|
|
36
|
+
const uint b = (31u - j) * (uint)K;
|
|
37
|
+
const uint wi = b >> 5;
|
|
38
|
+
const uint off = b & 31u;
|
|
39
|
+
uint win = w[wi] >> off;
|
|
40
|
+
if (off + (uint)L_ > 32u) win |= w[wi + 1] << (32u - off);
|
|
41
|
+
return win & ((1u << (uint)L_) - 1u);
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
const SOURCE_V3 = String.raw`
|
|
45
|
+
const uint lane = thread_index_in_simdgroup;
|
|
46
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
47
|
+
const uint n0 = (threadgroup_position_in_grid.y * (uint)SG_TG + sg) * 8u;
|
|
48
|
+
if (n0 >= (uint)R) return;
|
|
49
|
+
const uint fm = ((lane / 4u) & 4u) + ((lane / 2u) % 4u);
|
|
50
|
+
const uint fn = ((lane / 4u) & 2u) * 2u + (lane % 2u) * 2u;
|
|
51
|
+
const uint row = n0 + fm;
|
|
52
|
+
const device uint32_t* gRow = gcodes + (ulong)row * (ulong)((C / BT) * (BT * KG / 32));
|
|
53
|
+
const device uint32_t* uRow = ucodes + (ulong)row * (ulong)((C / BT) * (BT * KU / 32));
|
|
54
|
+
// MT activation blocks of 8 rows; grid z walks chunks of 8·MT rows.
|
|
55
|
+
const uint mBase = threadgroup_position_in_grid.z * 8u * (uint)MT;
|
|
56
|
+
bool m0[MT], m1[MT];
|
|
57
|
+
const device T* x0[MT];
|
|
58
|
+
const device T* x1[MT];
|
|
59
|
+
#pragma clang loop unroll(full)
|
|
60
|
+
for (uint bk = 0; bk < (uint)MT; ++bk) {
|
|
61
|
+
const uint r0 = mBase + 8u * bk + fn;
|
|
62
|
+
m0[bk] = r0 < (uint)M; m1[bk] = r0 + 1u < (uint)M;
|
|
63
|
+
x0[bk] = x + (ulong)(m0[bk] ? r0 : 0u) * (ulong)C + fm * 32u;
|
|
64
|
+
x1[bk] = x + (ulong)(m1[bk] ? r0 + 1u : 0u) * (ulong)C + fm * 32u;
|
|
65
|
+
}
|
|
66
|
+
metal::simdgroup_float8x8 accG[MT], accU[MT];
|
|
67
|
+
#pragma clang loop unroll(full)
|
|
68
|
+
for (uint bk = 0; bk < (uint)MT; ++bk) {
|
|
69
|
+
accG[bk] = metal::make_filled_simdgroup_matrix<float, 8, 8>(0.0f);
|
|
70
|
+
accU[bk] = metal::make_filled_simdgroup_matrix<float, 8, 8>(0.0f);
|
|
71
|
+
}
|
|
72
|
+
for (uint base = 0; base < (uint)C; base += 256u) {
|
|
73
|
+
const uint runA = base / 32u + fn;
|
|
74
|
+
uint ga[KG + 1], gb[KG + 1], ua[KU + 1], ub[KU + 1];
|
|
75
|
+
load_run<KG, BT>(gRow, runA, ga);
|
|
76
|
+
load_run<KG, BT>(gRow, runA + 1u, gb);
|
|
77
|
+
load_run<KU, BT>(uRow, runA, ua);
|
|
78
|
+
load_run<KU, BT>(uRow, runA + 1u, ub);
|
|
79
|
+
#pragma clang loop unroll(full)
|
|
80
|
+
for (uint s4 = 0; s4 < 8u; ++s4) {
|
|
81
|
+
float4 va[MT], vb[MT];
|
|
82
|
+
#pragma clang loop unroll(full)
|
|
83
|
+
for (uint bk = 0; bk < (uint)MT; ++bk) {
|
|
84
|
+
va[bk] = m0[bk] ? float4(((const device metal::vec<T, 4>*)(x0[bk] + base))[s4]) : float4(0.0f);
|
|
85
|
+
vb[bk] = m1[bk] ? float4(((const device metal::vec<T, 4>*)(x1[bk] + base))[s4]) : float4(0.0f);
|
|
86
|
+
}
|
|
87
|
+
#pragma clang loop unroll(full)
|
|
88
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
89
|
+
const uint j = s4 * 4u + q;
|
|
90
|
+
metal::simdgroup_float8x8 aG, aU;
|
|
91
|
+
aG.thread_elements()[0] = trellis_y_f32((run_state<KG, L>(ga, j)));
|
|
92
|
+
aG.thread_elements()[1] = trellis_y_f32((run_state<KG, L>(gb, j)));
|
|
93
|
+
aU.thread_elements()[0] = trellis_y_f32((run_state<KU, L>(ua, j)));
|
|
94
|
+
aU.thread_elements()[1] = trellis_y_f32((run_state<KU, L>(ub, j)));
|
|
95
|
+
#pragma clang loop unroll(full)
|
|
96
|
+
for (uint bk = 0; bk < (uint)MT; ++bk) {
|
|
97
|
+
metal::simdgroup_float8x8 b;
|
|
98
|
+
b.thread_elements()[0] = va[bk][q];
|
|
99
|
+
b.thread_elements()[1] = vb[bk][q];
|
|
100
|
+
metal::simdgroup_multiply_accumulate(accG[bk], aG, b, accG[bk]);
|
|
101
|
+
metal::simdgroup_multiply_accumulate(accU[bk], aU, b, accU[bk]);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
const float gs = float(gscales[row]) * TRELLIS_RCP;
|
|
107
|
+
const float us = float(uscales[row]) * TRELLIS_RCP;
|
|
108
|
+
#pragma clang loop unroll(full)
|
|
109
|
+
for (uint bk = 0; bk < (uint)MT; ++bk)
|
|
110
|
+
#pragma clang loop unroll(full)
|
|
111
|
+
for (uint j = 0; j < 2u; ++j) {
|
|
112
|
+
const uint m = mBase + 8u * bk + fn + j;
|
|
113
|
+
if (m >= (uint)M) continue;
|
|
114
|
+
const T gateT = T(accG[bk].thread_elements()[j] * gs);
|
|
115
|
+
const T upT = T(accU[bk].thread_elements()[j] * us);
|
|
116
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
117
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
118
|
+
mid[(ulong)m * (ulong)R + row] = T(float(siluT) * float(upT));
|
|
119
|
+
}
|
|
120
|
+
`;
|
|
121
|
+
|
|
122
|
+
let kernel: MetalKernel | undefined;
|
|
123
|
+
|
|
124
|
+
/** silu(gate(x))·up(x) for 1..8 activation rows. Gate and up share their
|
|
125
|
+
* axis-1 geometry (rows a multiple of 8, columns of 256); their bit widths may
|
|
126
|
+
* differ. Borrows x and the weights; returns owned lazy output with x's
|
|
127
|
+
* leading dimensions. */
|
|
128
|
+
export function gateUpMma(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 || M > 8) throw new Error(`gateUpMma: M=${M} outside 1..8`);
|
|
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)
|
|
134
|
+
throw new Error("gateUpMma: unsupported gate/up geometry");
|
|
135
|
+
kernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_mma", inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales"],
|
|
136
|
+
outputNames: ["mid"], source: SOURCE_V3, header: HEADER + RUN3_HEADER, ensureRowContiguous: true });
|
|
137
|
+
const x2 = ops.reshape(x, [M, g.inFeatures]);
|
|
138
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales], {
|
|
139
|
+
outputs: [{ shape: [M, g.rows], dtype: x.dtype }],
|
|
140
|
+
grid: [32 * SG_TG, Math.ceil(g.rows / 8 / SG_TG), 1], threadGroup: [32 * SG_TG, 1, 1],
|
|
141
|
+
templateDtypes: { T: x.dtype },
|
|
142
|
+
templateInts: { M, R: g.rows, C: g.cols, BT: g.T, KG: g.k, KU: u.k, L: g.L, SG_TG, MT },
|
|
143
|
+
});
|
|
144
|
+
x2.dispose();
|
|
145
|
+
const out = ops.reshape(mid!, [...lead, g.rows]);
|
|
146
|
+
mid!.dispose();
|
|
147
|
+
return out;
|
|
148
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
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 { Dtype } from "@mlx-bun/mlx/ffi";
|
|
5
|
+
import type { TrellisGeometry, TrellisWeights } from "./geometry";
|
|
6
|
+
import { HEADER, lutFor, decoderVariant } from "./codebook";
|
|
7
|
+
import { TRELLIS_THREADS, TRELLIS_SG_PER_TG, TRELLIS_CODEBOOK_THREADS, TRELLIS_CODEBOOK_SG_PER_TG } from "./launch";
|
|
8
|
+
import { qualifiedRepresentations } from "./qualified";
|
|
9
|
+
|
|
10
|
+
import { TRELLIS_MATVEC_MAX_M as MATVEC_MAX_M } from "./reduce";
|
|
11
|
+
|
|
12
|
+
const GATEUP_SOURCE = String.raw`
|
|
13
|
+
threadgroup float lutTG[4096];
|
|
14
|
+
if ((VARIANT) == 2 || CODEBOOK) {
|
|
15
|
+
for (uint i = thread_position_in_threadgroup.x; i < 4096u; i += (uint)THREADS)
|
|
16
|
+
lutTG[i] = CODEBOOK ? trellis_unrefined_y(trellis_y(i)) : lut[i];
|
|
17
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
18
|
+
}
|
|
19
|
+
const uint lane = thread_index_in_simdgroup;
|
|
20
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
21
|
+
const uint row = thread_position_in_grid.y * (uint)ROWS_TG + sg;
|
|
22
|
+
const uint sample = thread_position_in_grid.z;
|
|
23
|
+
if (row >= (uint)R || sample >= (uint)M) return;
|
|
24
|
+
const uint wpb = (uint)(BT * K / 32);
|
|
25
|
+
const uint runsPerBlock = (uint)BT / 32u;
|
|
26
|
+
const uint nRuns = (uint)C / 32u;
|
|
27
|
+
const ulong rowWords = (ulong)((C / BT) * wpb);
|
|
28
|
+
const device uint32_t* gRow = gcodes + (ulong)row * rowWords;
|
|
29
|
+
const device uint32_t* uRow = ucodes + (ulong)row * rowWords;
|
|
30
|
+
const device T* xs = x + (ulong)sample * (ulong)C;
|
|
31
|
+
const float gScale = float(gscales[row]);
|
|
32
|
+
const float uScale = float(uscales[row]);
|
|
33
|
+
float gAcc = 0.0f, gAcc2 = 0.0f;
|
|
34
|
+
float uAcc = 0.0f, uAcc2 = 0.0f;
|
|
35
|
+
for (uint run = lane; run < nRuns; run += 32u) {
|
|
36
|
+
const uint blk = run / runsPerBlock;
|
|
37
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
38
|
+
const device uint32_t* gw = gRow + blk * wpb;
|
|
39
|
+
const device uint32_t* uw = uRow + blk * wpb;
|
|
40
|
+
const uint w0 = ((uint)BT - 32u - t0) * (uint)K / 32u;
|
|
41
|
+
uint g[K + 1];
|
|
42
|
+
uint u[K + 1];
|
|
43
|
+
#pragma clang loop unroll(full)
|
|
44
|
+
for (uint i = 0; i <= (uint)K; ++i) {
|
|
45
|
+
const uint wi = w0 + i;
|
|
46
|
+
const uint idx = wi >= wpb ? wi - wpb : wi;
|
|
47
|
+
g[i] = gw[idx];
|
|
48
|
+
u[i] = uw[idx];
|
|
49
|
+
}
|
|
50
|
+
const uint c0 = blk * (uint)BT + t0;
|
|
51
|
+
const device metal::vec<T, 4>* x4 = (const device metal::vec<T, 4>*)(xs + c0);
|
|
52
|
+
#pragma clang loop unroll(full)
|
|
53
|
+
for (uint j4 = 0; j4 < 8u; ++j4) {
|
|
54
|
+
const float4 xv4 = float4(x4[j4]);
|
|
55
|
+
#pragma clang loop unroll(full)
|
|
56
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
57
|
+
const uint j = j4 * 4u + q;
|
|
58
|
+
const uint b = (31u - j) * (uint)K;
|
|
59
|
+
const uint wi = b >> 5;
|
|
60
|
+
const uint off = b & 31u;
|
|
61
|
+
uint gwin = g[wi] >> off;
|
|
62
|
+
uint uwin = u[wi] >> off;
|
|
63
|
+
if (off + (uint)L > 32u) { gwin |= g[wi + 1] << (32u - off); uwin |= u[wi + 1] << (32u - off); }
|
|
64
|
+
gwin &= (1u << (uint)L) - 1u;
|
|
65
|
+
uwin &= (1u << (uint)L) - 1u;
|
|
66
|
+
const float xv = xv4[q];
|
|
67
|
+
const float gv = TRELLIS_ROUND((CODEBOOK ? lutTG[gwin] : TRELLIS_DECODE(gwin, lutTG, lut)) * gScale);
|
|
68
|
+
const float uv = TRELLIS_ROUND((CODEBOOK ? lutTG[uwin] : TRELLIS_DECODE(uwin, lutTG, lut)) * uScale);
|
|
69
|
+
if (q & 1u) { gAcc2 = metal::fma(gv, xv, gAcc2); uAcc2 = metal::fma(uv, xv, uAcc2); }
|
|
70
|
+
else { gAcc = metal::fma(gv, xv, gAcc); uAcc = metal::fma(uv, xv, uAcc); }
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
const float gate = metal::simd_sum(gAcc + gAcc2);
|
|
75
|
+
const float up = metal::simd_sum(uAcc + uAcc2);
|
|
76
|
+
if (lane == 0u) {
|
|
77
|
+
const T gateT = T(gate);
|
|
78
|
+
const T upT = T(up);
|
|
79
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
80
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
81
|
+
mid[(ulong)sample * (ulong)R + row] = T(float(siluT) * float(upT));
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
const GATEUP_SHARED_M_SOURCE = String.raw`
|
|
86
|
+
threadgroup float lutTG[4096];
|
|
87
|
+
if ((VARIANT) == 2) {
|
|
88
|
+
for (uint i = thread_position_in_threadgroup.x; i < 4096u; i += ${TRELLIS_THREADS}u) lutTG[i] = lut[i];
|
|
89
|
+
threadgroup_barrier(metal::mem_flags::mem_threadgroup);
|
|
90
|
+
}
|
|
91
|
+
const uint lane = thread_index_in_simdgroup;
|
|
92
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
93
|
+
const uint row = thread_position_in_grid.y * (uint)ROWS_TG + sg;
|
|
94
|
+
const uint sample = 0u;
|
|
95
|
+
if (row >= (uint)R || sample >= (uint)M) return;
|
|
96
|
+
const uint wpb = (uint)(BT * K / 32);
|
|
97
|
+
const uint runsPerBlock = (uint)BT / 32u;
|
|
98
|
+
const uint nRuns = (uint)C / 32u;
|
|
99
|
+
const ulong rowWords = (ulong)((C / BT) * wpb);
|
|
100
|
+
const device uint32_t* gRow = gcodes + (ulong)row * rowWords;
|
|
101
|
+
const device uint32_t* uRow = ucodes + (ulong)row * rowWords;
|
|
102
|
+
const float gScale = float(gscales[row]);
|
|
103
|
+
const float uScale = float(uscales[row]);
|
|
104
|
+
float gAcc[M], gAcc2[M], uAcc[M], uAcc2[M];
|
|
105
|
+
#pragma clang loop unroll(full)
|
|
106
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
107
|
+
gAcc[m] = 0.0f; gAcc2[m] = 0.0f; uAcc[m] = 0.0f; uAcc2[m] = 0.0f;
|
|
108
|
+
}
|
|
109
|
+
for (uint run = lane; run < nRuns; run += 32u) {
|
|
110
|
+
const uint blk = run / runsPerBlock;
|
|
111
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
112
|
+
const device uint32_t* gw = gRow + blk * wpb;
|
|
113
|
+
const device uint32_t* uw = uRow + blk * wpb;
|
|
114
|
+
const uint w0 = ((uint)BT - 32u - t0) * (uint)K / 32u;
|
|
115
|
+
uint g[K + 1];
|
|
116
|
+
uint u[K + 1];
|
|
117
|
+
#pragma clang loop unroll(full)
|
|
118
|
+
for (uint i = 0; i <= (uint)K; ++i) {
|
|
119
|
+
const uint wi = w0 + i;
|
|
120
|
+
const uint idx = wi >= wpb ? wi - wpb : wi;
|
|
121
|
+
g[i] = gw[idx];
|
|
122
|
+
u[i] = uw[idx];
|
|
123
|
+
}
|
|
124
|
+
const uint c0 = blk * (uint)BT + t0;
|
|
125
|
+
#pragma clang loop unroll(full)
|
|
126
|
+
for (uint j4 = 0; j4 < 8u; ++j4) {
|
|
127
|
+
float4 xv4[M];
|
|
128
|
+
#pragma clang loop unroll(full)
|
|
129
|
+
for (uint m = 0; m < (uint)M; ++m)
|
|
130
|
+
xv4[m] = float4(((const device metal::vec<T, 4>*)(x + (ulong)m * (ulong)C + c0))[j4]);
|
|
131
|
+
#pragma clang loop unroll(full)
|
|
132
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
133
|
+
const uint j = j4 * 4u + q;
|
|
134
|
+
const uint b = (31u - j) * (uint)K;
|
|
135
|
+
const uint wi = b >> 5;
|
|
136
|
+
const uint off = b & 31u;
|
|
137
|
+
uint gwin = g[wi] >> off;
|
|
138
|
+
uint uwin = u[wi] >> off;
|
|
139
|
+
if (off + (uint)L > 32u) { gwin |= g[wi + 1] << (32u - off); uwin |= u[wi + 1] << (32u - off); }
|
|
140
|
+
gwin &= (1u << (uint)L) - 1u;
|
|
141
|
+
uwin &= (1u << (uint)L) - 1u;
|
|
142
|
+
const float gv = TRELLIS_ROUND(TRELLIS_DECODE(gwin, lutTG, lut) * gScale);
|
|
143
|
+
const float uv = TRELLIS_ROUND(TRELLIS_DECODE(uwin, lutTG, lut) * uScale);
|
|
144
|
+
#pragma clang loop unroll(full)
|
|
145
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
146
|
+
const float xv = xv4[m][q];
|
|
147
|
+
if (q & 1u) { gAcc2[m] = metal::fma(gv, xv, gAcc2[m]); uAcc2[m] = metal::fma(uv, xv, uAcc2[m]); }
|
|
148
|
+
else { gAcc[m] = metal::fma(gv, xv, gAcc[m]); uAcc[m] = metal::fma(uv, xv, uAcc[m]); }
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
#pragma clang loop unroll(full)
|
|
154
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
155
|
+
const float gate = metal::simd_sum(gAcc[m] + gAcc2[m]);
|
|
156
|
+
const float up = metal::simd_sum(uAcc[m] + uAcc2[m]);
|
|
157
|
+
if (lane == 0u) {
|
|
158
|
+
const T gateT = T(gate);
|
|
159
|
+
const T upT = T(up);
|
|
160
|
+
const T sigmoidT = T(1.0f / (1.0f + metal::precise::exp(-float(gateT))));
|
|
161
|
+
const T siluT = T(float(gateT) * float(sigmoidT));
|
|
162
|
+
mid[(ulong)m * (ulong)R + row] = T(float(siluT) * float(upT));
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
`;
|
|
166
|
+
|
|
167
|
+
let base: MetalKernel | undefined, shared: MetalKernel | undefined;
|
|
168
|
+
function gateUpKernel(): MetalKernel {
|
|
169
|
+
return base ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_swiglu",
|
|
170
|
+
inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales", "lut"], outputNames: ["mid"],
|
|
171
|
+
source: GATEUP_SOURCE, header: HEADER, ensureRowContiguous: true });
|
|
172
|
+
}
|
|
173
|
+
function sharedGateUpKernel(): MetalKernel {
|
|
174
|
+
return shared ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_shared_m",
|
|
175
|
+
inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales", "lut"], outputNames: ["mid"],
|
|
176
|
+
source: GATEUP_SHARED_M_SOURCE, header: HEADER, ensureRowContiguous: true });
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** The measured artifact geometry, row count, dtype and numerical variant of the codebook decode. */
|
|
180
|
+
function codebookShape(g: TrellisGeometry, m: number, dtype: Dtype, selected: number): boolean {
|
|
181
|
+
return selected === 13 && m === 1 && dtype === Dtype.bfloat16 &&
|
|
182
|
+
g.axis === 1 && g.T === 256 && g.L === 12 && [2, 3, 4].includes(g.k) &&
|
|
183
|
+
g.inFeatures === 5120 && g.outFeatures === 17408 && g.cols === 5120 && g.rows === 17408 && !g.blockInterleave;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/** Qualification is deliberately limited to the measured artifact geometry and
|
|
187
|
+
* GPU family. Other shapes, row counts, dtypes and numerical variants retain
|
|
188
|
+
* inline decode. The table uses variant 6 arithmetic, not the host's rounded LUT. */
|
|
189
|
+
export function gateUpCodebookEligible(g: TrellisGeometry, m: number, dtype: Dtype, selected: number,
|
|
190
|
+
architecture: string): boolean {
|
|
191
|
+
return qualifiedRepresentations(architecture).gateUpCodebook && codebookShape(g, m, dtype, selected);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/** Variants 7..13 share each decoded weight across rows (`GATEUP_SHARED_M_SOURCE`). */
|
|
195
|
+
const sharesRows = (selected: number) => selected >= 7 && selected <= 13;
|
|
196
|
+
|
|
197
|
+
/** silu(gate(x))·up(x) for exactly one activation row, gate and up at the same
|
|
198
|
+
* width: the per-row kernel. `codebook` applies at the measured shape; layers
|
|
199
|
+
* pass the choice they resolved at construction (`qualifiedRepresentations`).
|
|
200
|
+
* Borrows x and the weights; returns owned lazy output with x's leading dimensions. */
|
|
201
|
+
export function gateUpReduceRow(x: MlxArray, gate: TrellisWeights, up: TrellisWeights, selected: number,
|
|
202
|
+
codebook: boolean): MlxArray {
|
|
203
|
+
if (x.size !== x.shape.at(-1)) throw new Error("gateUpReduceRow: expects one activation row");
|
|
204
|
+
return launch(gateUpKernel(), x, gate, up, selected, codebook, 1, false);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/** silu(gate(x))·up(x) for 2..4 activation rows sharing each decoded weight
|
|
208
|
+
* (variants 7..13), gate and up at the same width. Borrows x and the weights;
|
|
209
|
+
* returns owned lazy output with x's leading dimensions. */
|
|
210
|
+
export function gateUpReduceRows(x: MlxArray, gate: TrellisWeights, up: TrellisWeights, selected: number): MlxArray {
|
|
211
|
+
const M = x.size / x.shape.at(-1)!;
|
|
212
|
+
if (M < 2 || M > MATVEC_MAX_M) throw new Error(`gateUpReduceRows: M=${M} outside 2..${MATVEC_MAX_M}`);
|
|
213
|
+
if (!sharesRows(selected)) throw new Error(`gateUpReduceRows: variant ${selected} does not share rows (7..13 do)`);
|
|
214
|
+
return launch(sharedGateUpKernel(), x, gate, up, selected, false, M, true);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** Borrow matching axis-1 gate/up weights with the same bit width; M must be 1..4.
|
|
218
|
+
* Return owned lazy SwiGLU output, retaining the input's leading dimensions.
|
|
219
|
+
* `codebook` applies at the measured shape: layers pass the choice they resolved
|
|
220
|
+
* at construction (`qualifiedRepresentations`), benches and tests the one they compare. */
|
|
221
|
+
export function fusedGateUpSwiglu(x: MlxArray, gate: TrellisWeights, up: TrellisWeights, selected: number,
|
|
222
|
+
codebook: boolean): MlxArray {
|
|
223
|
+
const M = x.shape.slice(0, -1).reduce((a, b) => a * b, 1);
|
|
224
|
+
if (M > MATVEC_MAX_M) throw new Error(`fusedGateUpSwiglu: M=${M} > ${MATVEC_MAX_M}`);
|
|
225
|
+
const shared = sharesRows(selected) && M > 1;
|
|
226
|
+
return launch(shared ? sharedGateUpKernel() : gateUpKernel(), x, gate, up, selected, codebook, M, shared);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function launch(kernel: MetalKernel, x: MlxArray, gate: TrellisWeights, up: TrellisWeights, selected: number,
|
|
230
|
+
codebook: boolean, M: number, shared: boolean): MlxArray {
|
|
231
|
+
const g = gate.geometry;
|
|
232
|
+
const lead = x.shape.slice(0, -1);
|
|
233
|
+
const useCodebook = codebook && codebookShape(g, M, x.dtype, selected);
|
|
234
|
+
const threads = useCodebook ? TRELLIS_CODEBOOK_THREADS : TRELLIS_THREADS;
|
|
235
|
+
const rowsPerGroup = useCodebook ? TRELLIS_CODEBOOK_SG_PER_TG : TRELLIS_SG_PER_TG;
|
|
236
|
+
const x2 = ops.reshape(x, [M, g.inFeatures]);
|
|
237
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales, lutFor(g.L)], {
|
|
238
|
+
outputs: [{ shape: [M, g.rows], dtype: x.dtype }],
|
|
239
|
+
grid: [threads, Math.ceil(g.rows / rowsPerGroup), shared ? 1 : M],
|
|
240
|
+
threadGroup: [threads, 1, 1],
|
|
241
|
+
templateDtypes: { T: x.dtype },
|
|
242
|
+
templateInts: { M, R: g.rows, C: g.cols, BT: g.T, K: g.k, L: g.L, ROWS_TG: rowsPerGroup, VARIANT: decoderVariant(selected), THREADS: threads, CODEBOOK: Number(useCodebook) },
|
|
243
|
+
});
|
|
244
|
+
x2.dispose();
|
|
245
|
+
const out = ops.reshape(mid!, [...lead, g.rows]);
|
|
246
|
+
mid!.dispose();
|
|
247
|
+
return out;
|
|
248
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { MlxArray } from "@mlx-bun/mlx/array";
|
|
2
|
+
|
|
3
|
+
export interface TrellisGeometry {
|
|
4
|
+
k: number;
|
|
5
|
+
L: number;
|
|
6
|
+
T: number;
|
|
7
|
+
axis: 0 | 1;
|
|
8
|
+
/** Stored-matrix rows / coded columns. */
|
|
9
|
+
rows: number;
|
|
10
|
+
cols: number;
|
|
11
|
+
inFeatures: number;
|
|
12
|
+
outFeatures: number;
|
|
13
|
+
/** Two coded blocks interleaved across rows; absent for row-major codes. */
|
|
14
|
+
blockInterleave?: 2;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Borrowed packed weights and their caller-supplied geometry. */
|
|
18
|
+
export interface TrellisWeights {
|
|
19
|
+
codes: MlxArray;
|
|
20
|
+
scales: MlxArray;
|
|
21
|
+
geometry: TrellisGeometry;
|
|
22
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Packed Trellis projection kernels (QTIP 1MAD code) and the decode-variant
|
|
2
|
+
// semantics their callers pass (layers/trellis-linear.ts passes 13).
|
|
3
|
+
//
|
|
4
|
+
// Format: `.weight` = uint32 bitstream, `.scales` = fp16 [rows], config entry
|
|
5
|
+
// `{mode:"trellis", bits:k, group_size:T, trellis:{L, code:"1mad", axis}}`.
|
|
6
|
+
// axis=1 (gate/up) is coded along the INPUT dim, stored [out, in*k/32]; axis=0
|
|
7
|
+
// (down) is coded along the OUTPUT dim, stored [in, out*k/32] (the stored matrix
|
|
8
|
+
// is W^T, coded along its last axis). The k3/axis0 layout [cols/512, rows, 48]
|
|
9
|
+
// interleaves two coded blocks across rows (`blockInterleave`); the tensor
|
|
10
|
+
// shape identifies it and no second code copy is kept.
|
|
11
|
+
//
|
|
12
|
+
// One decode primitive: state_t is the L-bit window at bit offset (T-1-t)*k of
|
|
13
|
+
// the block (wrapping), so any weight decodes in O(1) with the 1MAD code
|
|
14
|
+
// computed inline (codebook.ts HEADER), no LUT and no threadgroup memory.
|
|
15
|
+
// - reduce (M <= 4, axis=1): one SIMD group per output row; each lane owns
|
|
16
|
+
// runs of 32 consecutive positions held in K+1 registers (every
|
|
17
|
+
// window shift a compile-time constant); simd_sum.
|
|
18
|
+
// - scatter (M <= 4, axis=0): lane-per-WORD of a block, running sums per
|
|
19
|
+
// position in the word, split-K over input rows (partials folded
|
|
20
|
+
// by one mlx sum). One kernel each: scatterRow / balancedScatterRow
|
|
21
|
+
// (one row; balanced = 3-bit codes at T 256) and scatterRows /
|
|
22
|
+
// balancedScatterRows (2..4 rows sharing each decoded weight);
|
|
23
|
+
// trellisScatter chooses among them by row count and geometry.
|
|
24
|
+
// - expand (M > 4 fallback): decode the whole tensor to bf16, then a stock
|
|
25
|
+
// matmul; the transient is one tensor.
|
|
26
|
+
// - gate-up / mixed-gate-up: fused gate+up+SwiGLU for M <= 4 rows
|
|
27
|
+
// (gateUpReduceRow one row, gateUpReduceRows 2..4 shared rows;
|
|
28
|
+
// fusedGateUpSwiglu chooses between them by row count). The mixed
|
|
29
|
+
// kernel serves layers whose gate and up bit widths differ (one
|
|
30
|
+
// word layout and bit offset each); TAIL "split" reproduces MLX's
|
|
31
|
+
// compiled swiglu over two bf16 projections bit for bit (no output
|
|
32
|
+
// changes vs the two-kernel path), "fused" the float32 sigmoid of
|
|
33
|
+
// the same-width kernel.
|
|
34
|
+
//
|
|
35
|
+
// Decode VARIANT, an explicit argument of each kernel. TrellisLinear passes
|
|
36
|
+
// 13; benches and tests pass the others to compare them. 0-6 select the decode
|
|
37
|
+
// arithmetic (see HEADER in codebook.ts): 0-3 reconstruct bf16(lut[state]*scale);
|
|
38
|
+
// 6 is f32 code*scale in the packed kernels (expansion still stores bf16).
|
|
39
|
+
// Variants 7-13 keep variant 6's decoded values (`decoderVariant`) and add
|
|
40
|
+
// kernel selection, each including the ones below it:
|
|
41
|
+
// 7 weight decoding shared across M=2..4 in reduce and gate-up
|
|
42
|
+
// 8 balanced 3-bit scatter (k=3, T=256, L<=12)
|
|
43
|
+
// 9 same kernels as 8; it once also deferred prefill projection evaluation
|
|
44
|
+
// to the Qwen layer barrier, which no longer exists
|
|
45
|
+
// 10 shared-M scatter across M=2..4
|
|
46
|
+
// 11 tiled axis-1 prefill at M=5..32 on the measured MLP shape; wide prefill
|
|
47
|
+
// when the input is proven row-contiguous
|
|
48
|
+
// 12 tiled axis-0 prefill at M=5..8 with MLX's split-K reduction
|
|
49
|
+
// 13 shared packed-word loads in the remaining bf16 expansion (vector
|
|
50
|
+
// expand), and the shared scatter codebook for M=3..4 bf16 on the
|
|
51
|
+
// interleaved k3 layout
|
|
52
|
+
//
|
|
53
|
+
// Threadgroup-codebook one-row kernels (every code value of the 2^L states
|
|
54
|
+
// generated once per threadgroup), the variant-13 output of the kernels above
|
|
55
|
+
// bit for bit:
|
|
56
|
+
// - gate-up-codebook: gate/up/SwiGLU, the same or different widths
|
|
57
|
+
// - down-codebook: lanes owning word-aligned runs of positions (every window
|
|
58
|
+
// shift a constant), row-major 2/4-bit and 3-bit block-interleaved codes
|
|
59
|
+
//
|
|
60
|
+
// Factored-scale kernels: weights contribute their code value y and the scale
|
|
61
|
+
// (with 1/147.8) applies once per output (gate/up) or per input row (down);
|
|
62
|
+
// one kernel per row form and code layout:
|
|
63
|
+
// - gate-up-factored: same-width gate/up, one row / 2..4 shared rows
|
|
64
|
+
// - mixed-gate-up-factored: different-width gate/up, 1..4 rows
|
|
65
|
+
// - down-factored: row-major axis-0 codes, one row / 2..4 rows
|
|
66
|
+
// - down-k3-interleaved-factored: 3-bit block-interleaved axis-0 codes
|
|
67
|
+
// - gate-up-mma / down-mma: 1..8 rows on the simdgroup matrix unit
|
|
68
|
+
// - gate-up-mma-wide / down-mma-wide: the same fragments for any number of
|
|
69
|
+
// rows, each decoded fragment feeding the MMAs of several 8-row blocks,
|
|
70
|
+
// each code value read from a threadgroup codebook; down-mma-wide in
|
|
71
|
+
// passes the rows plan or the caller fixes (one block for 1..8 rows)
|
|
72
|
+
// - gate-up-codebook-mma: gate-up-mma's fragments and bits for 1..8 rows,
|
|
73
|
+
// each code value read from a threadgroup codebook (the M1 Max form)
|
|
74
|
+
//
|
|
75
|
+
// ExpandedTrellisLinear (layers/trellis-linear.ts) decodes a trellis tensor at
|
|
76
|
+
// construction into 8-bit g64 affine (the eval-carrier numerics, about -45 dB)
|
|
77
|
+
// and serves it through the stock QuantizedLinear, for a machine where the
|
|
78
|
+
// kernels lose.
|
|
79
|
+
export type { TrellisGeometry, TrellisWeights } from "./geometry";
|
|
80
|
+
export { vectorTrellisExpand, vectorTrellisExpandEligible } from "./vector-expand";
|
|
81
|
+
export { expandTrellis } from "./expand";
|
|
82
|
+
export { trellisReduce, TRELLIS_MATVEC_MAX_M } from "./reduce";
|
|
83
|
+
export { trellisScatter, scatterRow, scatterRows, balancedScatterRow, balancedScatterRows } from "./scatter";
|
|
84
|
+
export { qualifiedRepresentations, type ScatterRepresentation, type TrellisRepresentations } from "./qualified";
|
|
85
|
+
export { fusedGateUpSwiglu, gateUpReduceRow, gateUpReduceRows } from "./gate-up";
|
|
86
|
+
export { gateUpCodebookRow } from "./gate-up-codebook";
|
|
87
|
+
export { downCodebookRow, downK3InterleavedCodebookRow } from "./down-codebook";
|
|
88
|
+
export { fusedGateUpSwigluMixed, type MixedGateUpTail } from "./mixed-gate-up";
|
|
89
|
+
export { tiledTrellisPrefill, tiledTrellisPrefillEligible } from "./tiled-prefill";
|
|
90
|
+
export { splitKTrellisPrefill, splitKTrellisPrefillEligible } from "./splitk-prefill";
|
|
91
|
+
export { wideTrellisPrefill, wideTrellisPrefillEligible, nativeTrellisWidePrefill } from "./wide-prefill";
|
|
92
|
+
export { lut1mad, wordsPerBlock } from "./codebook";
|
|
93
|
+
export { gateUpFactoredRow, gateUpFactoredRows } from "./gate-up-factored";
|
|
94
|
+
export { mixedGateUpFactoredRows } from "./mixed-gate-up-factored";
|
|
95
|
+
export { downFactoredRow, downFactoredRows } from "./down-factored";
|
|
96
|
+
export { downK3InterleavedFactoredRow, downK3InterleavedFactoredRows } from "./down-k3-interleaved-factored";
|
|
97
|
+
export { gateUpMma } from "./gate-up-mma";
|
|
98
|
+
export { downMma, downK3InterleavedMma } from "./down-mma";
|
|
99
|
+
export { gateUpMmaWide } from "./gate-up-mma-wide";
|
|
100
|
+
export {
|
|
101
|
+
downMmaWide, downK3InterleavedMmaWide, downMmaWidePass, downK3InterleavedMmaWidePass, DOWN_ONE_BLOCK, type DownPass,
|
|
102
|
+
} from "./down-mma-wide";
|
|
103
|
+
export { gateUpCodebookMma } from "./gate-up-codebook-mma";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/** Default Trellis matvec launch: four SIMD groups of 32 lanes per threadgroup,
|
|
2
|
+
* one output row per SIMD group. Qualified codebook decode uses wider groups. */
|
|
3
|
+
export const TRELLIS_THREADS = 128;
|
|
4
|
+
export const TRELLIS_SG_PER_TG = 4;
|
|
5
|
+
/** Amortize the 16 KiB codebook over sixteen rows in the qualified M1 decode. */
|
|
6
|
+
export const TRELLIS_CODEBOOK_THREADS = 512;
|
|
7
|
+
export const TRELLIS_CODEBOOK_SG_PER_TG = 16;
|
|
8
|
+
/** The one-row gate/up codebook kernel: one threadgroup per M1 Max core, each table serving 32 rows at a time. */
|
|
9
|
+
export const TRELLIS_CODEBOOK_ROW_THREADS = 1024;
|
|
10
|
+
export const TRELLIS_CODEBOOK_ROW_SG_PER_TG = 32;
|
|
11
|
+
/** The one-row down codebook kernel: eight SIMD groups per threadgroup (each split's lanes own 16 positions). */
|
|
12
|
+
export const TRELLIS_CODEBOOK_DOWN_THREADS = 256;
|
|
@@ -0,0 +1,119 @@
|
|
|
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 for layers whose gate and up were coded at different
|
|
9
|
+
// bit widths (KG, KU), 1..4 activation rows sharing each decoded weight. Row
|
|
10
|
+
// scales are factored out of the reduction as in gate-up-factored.ts. The
|
|
11
|
+
// SwiGLU tail is MLX's compiled swiglu over bf16 gate and up (sigmoid via
|
|
12
|
+
// exp(|g|) in T), the arithmetic of two separate projections plus swiglu.
|
|
13
|
+
const SOURCE = String.raw`
|
|
14
|
+
const uint lane = thread_index_in_simdgroup;
|
|
15
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
16
|
+
const uint row = thread_position_in_grid.y * (uint)ROWS_TG + sg;
|
|
17
|
+
if (row >= (uint)R) return;
|
|
18
|
+
const uint gWpb = (uint)(BT * KG / 32);
|
|
19
|
+
const uint uWpb = (uint)(BT * KU / 32);
|
|
20
|
+
const uint runsPerBlock = (uint)BT / 32u;
|
|
21
|
+
const uint nRuns = (uint)C / 32u;
|
|
22
|
+
const device uint32_t* gRow = gcodes + (ulong)row * (ulong)((C / BT) * gWpb);
|
|
23
|
+
const device uint32_t* uRow = ucodes + (ulong)row * (ulong)((C / BT) * uWpb);
|
|
24
|
+
const float gScale = float(gscales[row]);
|
|
25
|
+
const float uScale = float(uscales[row]);
|
|
26
|
+
float gAcc[M], uAcc[M];
|
|
27
|
+
#pragma clang loop unroll(full)
|
|
28
|
+
for (uint m = 0; m < (uint)M; ++m) { gAcc[m] = 0.0f; uAcc[m] = 0.0f; }
|
|
29
|
+
for (uint run = lane; run < nRuns; run += 32u) {
|
|
30
|
+
const uint blk = run / runsPerBlock;
|
|
31
|
+
const uint t0 = (run - blk * runsPerBlock) * 32u;
|
|
32
|
+
const device uint32_t* gw = gRow + blk * gWpb;
|
|
33
|
+
const device uint32_t* uw = uRow + blk * uWpb;
|
|
34
|
+
const uint gW0 = ((uint)BT - 32u - t0) * (uint)KG / 32u;
|
|
35
|
+
const uint uW0 = ((uint)BT - 32u - t0) * (uint)KU / 32u;
|
|
36
|
+
uint g[KG + 1];
|
|
37
|
+
uint u[KU + 1];
|
|
38
|
+
#pragma clang loop unroll(full)
|
|
39
|
+
for (uint i = 0; i <= (uint)KG; ++i) {
|
|
40
|
+
const uint wi = gW0 + i;
|
|
41
|
+
g[i] = gw[wi >= gWpb ? wi - gWpb : wi];
|
|
42
|
+
}
|
|
43
|
+
#pragma clang loop unroll(full)
|
|
44
|
+
for (uint i = 0; i <= (uint)KU; ++i) {
|
|
45
|
+
const uint wi = uW0 + i;
|
|
46
|
+
u[i] = uw[wi >= uWpb ? wi - uWpb : wi];
|
|
47
|
+
}
|
|
48
|
+
const uint c0 = blk * (uint)BT + t0;
|
|
49
|
+
#pragma clang loop unroll(full)
|
|
50
|
+
for (uint j4 = 0; j4 < 8u; ++j4) {
|
|
51
|
+
float4 xv4[M];
|
|
52
|
+
#pragma clang loop unroll(full)
|
|
53
|
+
for (uint m = 0; m < (uint)M; ++m)
|
|
54
|
+
xv4[m] = float4(((const device metal::vec<T, 4>*)(x + (ulong)m * (ulong)C + c0))[j4]);
|
|
55
|
+
#pragma clang loop unroll(full)
|
|
56
|
+
for (uint q = 0; q < 4u; ++q) {
|
|
57
|
+
const uint j = j4 * 4u + q;
|
|
58
|
+
const uint gb = (31u - j) * (uint)KG;
|
|
59
|
+
const uint ub = (31u - j) * (uint)KU;
|
|
60
|
+
const uint gwi = gb >> 5, goff = gb & 31u;
|
|
61
|
+
const uint uwi = ub >> 5, uoff = ub & 31u;
|
|
62
|
+
uint gwin = g[gwi] >> goff;
|
|
63
|
+
uint uwin = u[uwi] >> uoff;
|
|
64
|
+
if (goff + (uint)L > 32u) gwin |= g[gwi + 1] << (32u - goff);
|
|
65
|
+
if (uoff + (uint)L > 32u) uwin |= u[uwi + 1] << (32u - uoff);
|
|
66
|
+
gwin &= (1u << (uint)L) - 1u;
|
|
67
|
+
uwin &= (1u << (uint)L) - 1u;
|
|
68
|
+
const float gv = trellis_y_f32(gwin);
|
|
69
|
+
const float uv = trellis_y_f32(uwin);
|
|
70
|
+
#pragma clang loop unroll(full)
|
|
71
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
72
|
+
const float xv = xv4[m][q];
|
|
73
|
+
gAcc[m] = metal::fma(gv, xv, gAcc[m]); uAcc[m] = metal::fma(uv, xv, uAcc[m]);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
#pragma clang loop unroll(full)
|
|
79
|
+
for (uint m = 0; m < (uint)M; ++m) {
|
|
80
|
+
const float gate = metal::simd_sum(gAcc[m]) * (gScale * TRELLIS_RCP);
|
|
81
|
+
const float up = metal::simd_sum(uAcc[m]) * (uScale * TRELLIS_RCP);
|
|
82
|
+
if (lane == 0u) {
|
|
83
|
+
const T gateT = T(gate);
|
|
84
|
+
const T upT = T(up);
|
|
85
|
+
const T sigY = 1 / (1 + metal::exp(metal::abs(gateT)));
|
|
86
|
+
const T sigmoidT = (gateT < 0) ? sigY : 1 - sigY;
|
|
87
|
+
const T siluT = gateT * sigmoidT;
|
|
88
|
+
mid[(ulong)m * (ulong)R + row] = siluT * upT;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
let kernel: MetalKernel | undefined;
|
|
94
|
+
|
|
95
|
+
/** silu(gate(x))·up(x) for 1..4 activation rows when gate and up share their
|
|
96
|
+
* axis-1 geometry but not their bit width. Borrows x and the weights; returns
|
|
97
|
+
* owned lazy output with x's leading dimensions. */
|
|
98
|
+
export function mixedGateUpFactoredRows(x: MlxArray, gate: TrellisWeights, up: TrellisWeights): MlxArray {
|
|
99
|
+
const g = gate.geometry, u = up.geometry;
|
|
100
|
+
if (g.axis !== 1 || u.axis !== 1 || g.k === u.k || g.rows !== u.rows || g.cols !== u.cols || g.T !== u.T || g.L !== u.L)
|
|
101
|
+
throw new Error("mixedGateUpFactoredRows: gate and up need the same axis-1 geometry at different widths");
|
|
102
|
+
const lead = x.shape.slice(0, -1);
|
|
103
|
+
const M = lead.reduce((a, b) => a * b, 1);
|
|
104
|
+
if (M < 1 || M > 4) throw new Error(`mixedGateUpFactoredRows: M=${M} outside 1..4`);
|
|
105
|
+
kernel ??= new MetalKernel({ name: "mlx_bun_trellis_gateup_mixed_factored", inputNames: ["x", "gcodes", "gscales", "ucodes", "uscales"],
|
|
106
|
+
outputNames: ["mid"], source: SOURCE, header: HEADER, ensureRowContiguous: true });
|
|
107
|
+
const x2 = ops.reshape(x, [M, g.inFeatures]);
|
|
108
|
+
const [mid] = kernel.apply([x2, gate.codes, gate.scales, up.codes, up.scales], {
|
|
109
|
+
outputs: [{ shape: [M, g.rows], dtype: x.dtype }],
|
|
110
|
+
grid: [TRELLIS_THREADS, Math.ceil(g.rows / TRELLIS_SG_PER_TG), 1],
|
|
111
|
+
threadGroup: [TRELLIS_THREADS, 1, 1],
|
|
112
|
+
templateDtypes: { T: x.dtype },
|
|
113
|
+
templateInts: { M, R: g.rows, C: g.cols, BT: g.T, KG: g.k, KU: u.k, L: g.L, ROWS_TG: TRELLIS_SG_PER_TG },
|
|
114
|
+
});
|
|
115
|
+
x2.dispose();
|
|
116
|
+
const out = ops.reshape(mid!, [...lead, g.rows]);
|
|
117
|
+
mid!.dispose();
|
|
118
|
+
return out;
|
|
119
|
+
}
|