mlx-bun 0.2.0 → 0.3.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/README.md +71 -588
- package/docs/README.md +91 -0
- package/docs/{design → archive/investigations}/audio-input-plan.md +4 -4
- package/docs/{design → archive/investigations}/diffusion-gemma-port.md +3 -3
- package/docs/{design → archive/investigations}/faithful-l1-consolidation.md +4 -4
- package/docs/{design → archive/investigations}/minicpm5-decode-megakernel.md +11 -11
- package/docs/{design → archive/investigations}/optimization_plan.md +1 -1
- package/docs/{design → archive/investigations}/pre-colibri-stabilization.md +5 -5
- package/docs/{design → archive/investigations}/the-dreaming-handoff.md +2 -2
- package/docs/design/batching.md +569 -0
- package/docs/design/decode-speed-program.md +3178 -169
- package/docs/design/dreaming-nightly-pipeline.md +675 -282
- package/docs/design/generic-model-support.md +579 -334
- package/docs/design/kv-cache.md +680 -0
- package/docs/design/orpo-training.md +673 -1239
- package/docs/design/speculative-decoding.md +1627 -0
- package/docs/design/turboquant.md +2102 -0
- package/docs/design/unified-engine-frontier-plan.md +1831 -727
- package/docs/design/web-chat-redesign.md +666 -1083
- package/docs/planning/PRODUCT_ROADMAP.md +34 -1
- package/docs/planning/release-notes-v0.3.0.md +35 -0
- package/docs/planning/video-series.md +2 -2
- package/docs/reference/benchmarks.md +1162 -0
- package/docs/reference/cli.md +394 -159
- package/docs/reference/distribution.md +321 -182
- package/docs/reference/environment.md +348 -0
- package/docs/reference/glossary.md +39 -0
- package/docs/reference/library-api.md +566 -168
- package/docs/reference/memory.md +227 -64
- package/docs/reference/models.md +104 -6
- package/docs/reference/server-api.md +886 -425
- package/docs/reference/server-config.md +638 -330
- package/docs/reference/training.md +393 -254
- package/docs/reference/troubleshooting.md +166 -0
- package/package.json +9 -4
- package/src/audio/decode.ts +2 -2
- package/src/audio/features.ts +2 -2
- package/src/backends/mlx/autoregressive.ts +108 -0
- package/src/backends/mlx/batch-group.ts +1646 -0
- package/src/backends/mlx/diffusion.ts +39 -0
- package/src/backends/mlx/draft-target.ts +47 -0
- package/src/backends/mlx/evaluation.ts +105 -0
- package/src/backends/mlx/fill-append.ts +45 -0
- package/src/backends/mlx/gateway-binding.ts +71 -0
- package/src/backends/mlx/graph.ts +38 -0
- package/src/backends/mlx/memory-client.ts +189 -0
- package/src/backends/mlx/memory-guard.ts +40 -0
- package/src/backends/mlx/methods.ts +90 -0
- package/src/backends/mlx/model-prompt.ts +164 -0
- package/src/backends/mlx/model-serving.ts +79 -0
- package/src/backends/mlx/prefill.ts +33 -0
- package/src/backends/mlx/request-policy.ts +20 -0
- package/src/backends/mlx/rollback.ts +51 -0
- package/src/backends/mlx/serial-executor.ts +273 -0
- package/src/backends/mlx/speculative.ts +114 -0
- package/src/backends/mlx/state-views.ts +26 -0
- package/src/backends/mlx/text-engine.ts +73 -0
- package/src/cli.ts +58 -25
- package/src/client.ts +66 -0
- package/src/config.ts +21 -4
- package/src/contracts/completion.ts +16 -0
- package/src/contracts/execution.ts +49 -0
- package/src/contracts/generation.ts +103 -0
- package/src/contracts/host.ts +7 -0
- package/src/contracts/jobs.ts +66 -0
- package/src/contracts/pi-provider.ts +30 -0
- package/src/contracts/pi.ts +259 -0
- package/src/contracts/resources.ts +18 -0
- package/src/contracts/scheduling.ts +27 -0
- package/src/contracts/tsconfig.json +14 -0
- package/src/diffusion/diffusion-generate.ts +218 -153
- package/src/embed.ts +1 -1
- package/src/engine/admission.ts +59 -0
- package/src/engine/cancellation.ts +38 -0
- package/src/engine/engine.ts +56 -0
- package/src/engine/execution-coordinator.ts +70 -0
- package/src/engine/execution-plan.ts +51 -0
- package/src/engine/resources.ts +42 -0
- package/src/engine/scheduler.ts +67 -0
- package/src/engine/session.ts +247 -0
- package/src/eval/README.md +44 -1
- package/src/eval/kl.ts +236 -3
- package/src/eval/reference-logits.ts +207 -0
- package/src/eval/runner.ts +8 -96
- package/src/fill/echo-index.ts +188 -0
- package/src/fill/fill-session.ts +452 -0
- package/src/fill/proposal.ts +68 -0
- package/src/fill/schema-rows.ts +506 -0
- package/src/fill/tool-boundary.ts +103 -0
- package/src/fit.ts +1 -1
- package/src/generate.ts +656 -268
- package/src/grammar.ts +12 -7
- package/src/harness-pi.ts +14 -33
- package/src/hub-rest.ts +4 -4
- package/src/index.ts +7 -0
- package/src/inference/denoising.ts +17 -0
- package/src/inference/graph.ts +33 -0
- package/src/inference/prefill.ts +39 -0
- package/src/inference/rollback.ts +7 -0
- package/src/jobs/db.ts +4 -0
- package/src/jobs/index.ts +2 -0
- package/src/jobs/job-entry.ts +12 -12
- package/src/jobs/runner.ts +98 -13
- package/src/jobs/task-client.ts +19 -0
- package/src/jobs/types.ts +2 -58
- package/src/kv-store.ts +109 -49
- package/src/lab/README.md +18 -0
- package/src/{assets → lab/curve}/curve-designer.html +2 -2
- package/src/{curve-sampler.ts → lab/curve/curve-sampler.ts} +2 -2
- package/src/{expert-trace.ts → lab/expert-trace/expert-trace.ts} +5 -5
- package/src/{model → lab/paged-kv}/paged-kv.ts +9 -6
- package/src/library.ts +40 -0
- package/src/lora.ts +18 -0
- package/src/media-fetch.ts +1 -1
- package/src/memory/article.ts +1 -1
- package/src/memory/chunk.ts +1 -1
- package/src/memory/model.ts +30 -169
- package/src/memory/prompts.ts +1 -1
- package/src/memory/rest.ts +1 -1
- package/src/memory/schedule.ts +1 -1
- package/src/memory/stages.ts +4 -1
- package/src/memory/vault.ts +1 -3
- package/src/mlx/array.ts +9 -10
- package/src/mlx/compile.ts +12 -2
- package/src/mlx/ffi.ts +58 -11
- package/src/mlx/materialize.ts +23 -0
- package/src/mlx/metal-kernel.ts +10 -11
- package/src/mlx/ops.ts +33 -13
- package/src/mlx/quantized-rows.ts +36 -0
- package/src/mlx/token-bitmask.ts +52 -0
- package/src/mlx/turboquant-kv-decode.ts +82 -0
- package/src/mlx/turboquant-kv-inverse.ts +122 -0
- package/src/mlx/turboquant-ops.ts +33 -3
- package/src/mlx/turboquant-tables.ts +2 -2
- package/src/model/batched-mask.ts +8 -2
- package/src/model/batched-quant.ts +1 -1
- package/src/model/batched-rotating-quant.ts +2 -2
- package/src/model/batched-rotating.ts +1 -1
- package/src/model/compiled-decode.ts +1 -1
- package/src/model/diffusion-gemma.ts +8 -8
- package/src/model/factory.ts +76 -33
- package/src/model/fingerprint.ts +1 -1
- package/src/model/flash-attention.ts +3 -3
- package/src/model/gemma4-base.ts +26 -9
- package/src/model/gemma4.ts +6 -6
- package/src/model/generated/gemma4-12b.ts +2 -2
- package/src/model/generated/gemma4-26b.ts +2 -2
- package/src/model/generated/gemma4-e4b.ts +2 -2
- package/src/model/glm52-dsa.ts +13 -9
- package/src/model/glm52-memory.ts +1 -1
- package/src/model/implementation.ts +69 -0
- package/src/model/minicpm5.ts +6 -8
- package/src/model/profile.ts +12 -2
- package/src/model/qwen-append.ts +12 -0
- package/src/model/qwen-conv.ts +52 -0
- package/src/model/qwen3_5-checkpoint.ts +164 -0
- package/src/model/qwen3_5.ts +140 -56
- package/src/model/support.ts +1 -1
- package/src/model/trellis-balanced-scatter.ts +51 -0
- package/src/model/trellis-linear.ts +672 -0
- package/src/model/trellis-shared-m.ts +151 -0
- package/src/model/trellis-shared-scatter.ts +144 -0
- package/src/model/trellis-splitk-prefill.ts +158 -0
- package/src/model/trellis-tiled-prefill.ts +136 -0
- package/src/model/trellis-vector-expand.ts +62 -0
- package/src/model/trellis-wide-prefill.ts +94 -0
- package/src/model/universal/dense.ts +1 -1
- package/src/model/universal/modules.ts +8 -1
- package/src/native-pack.ts +6 -5
- package/src/pi-provider.ts +6 -64
- package/src/pi-web.ts +8 -315
- package/src/prompt-cache.ts +96 -53
- package/src/quantize/allocator.ts +1 -1
- package/src/quantize/config-writer.ts +10 -3
- package/src/quantize/rotate.ts +4 -4
- package/src/quantize/trellis.ts +586 -0
- package/src/responses.ts +28 -1
- package/src/runtime-config.ts +18 -4
- package/src/sampler.ts +4 -4
- package/src/serve/batch-scheduler.ts +8 -1671
- package/src/serve/chat-request.ts +391 -0
- package/src/serve/chat-stage.ts +195 -0
- package/src/serve/checkpoint-identity.ts +64 -0
- package/src/serve/completion-executor.ts +15 -7
- package/src/serve/discovery-routes.ts +12 -13
- package/src/serve/generation-gateway.ts +154 -193
- package/src/serve/http.ts +159 -0
- package/src/serve/inference-request.ts +79 -0
- package/src/serve/isolate.ts +297 -105
- package/src/serve/lab-routes.ts +3 -0
- package/src/serve/lane-registry.ts +2 -1
- package/src/serve/model-admin-routes.ts +7 -5
- package/src/serve/model-binding.ts +43 -0
- package/src/serve/model-host.ts +512 -0
- package/src/serve/openai-wire.ts +103 -0
- package/src/serve/parent-application.ts +56 -0
- package/src/serve/pipeline.ts +33 -0
- package/src/serve/preparation.ts +33 -0
- package/src/serve/request-plan.ts +19 -15
- package/src/serve/request-prep.ts +346 -0
- package/src/serve/response-lease.ts +24 -0
- package/src/serve/responses-client.ts +69 -0
- package/src/serve/session-completion-engine.ts +110 -0
- package/src/serve/session-search.ts +1 -1
- package/src/serve/static-routes.ts +5 -5
- package/src/serve/text-completion-stage.ts +104 -0
- package/src/serve/token-streams.ts +519 -0
- package/src/server.ts +317 -2649
- package/src/spec/assistant-source.ts +10 -44
- package/src/spec/deepspec-source.ts +6 -6
- package/src/spec/dflash-source.ts +8 -8
- package/src/spec/dspark/ab-stats.ts +3 -3
- package/src/spec/dspark/calibration.ts +2 -2
- package/src/spec/dspark/deepspec-module.ts +2 -2
- package/src/spec/dspark/generate-dflash.ts +2 -2
- package/src/spec/dspark/generate.ts +2 -2
- package/src/spec/dspark/loader.ts +1 -1
- package/src/spec/dspark/module-dflash.ts +4 -3
- package/src/spec/dspark/module.ts +3 -3
- package/src/spec/dspark/quantize-drafter.ts +1 -1
- package/src/spec/generate.ts +1 -1
- package/src/spec/glm52-mtp-source.ts +1 -1
- package/src/spec/ngram-source.ts +1 -1
- package/src/spec/prefix-state.ts +45 -0
- package/src/spec/qwen-mtp-source.ts +166 -69
- package/src/spec/serve-loop.ts +154 -156
- package/src/spec/source.ts +42 -10
- package/src/spec/two-model.ts +1 -1
- package/src/ssd-cache.ts +80 -12
- package/src/ssd-durability.ts +25 -13
- package/src/tool-call.ts +51 -14
- package/src/train/flash-cce.ts +2 -2
- package/src/train/forward.ts +6 -0
- package/src/train/loss.ts +1 -1
- package/src/train/prefix-shared.ts +5 -1
- package/src/train/segmented.ts +5 -3
- package/src/train/trainer.ts +6 -6
- package/src/vision/prompt.ts +1 -1
- package/src/vision/qwen3vl-tower.ts +52 -10
- package/src/web/app.html +1 -1
- package/src/web/app.js +5 -3
- package/src/web/src/adapters-panel.ts +3 -3
- package/src/web/src/assistant.ts +2 -36
- package/src/web/src/chat.ts +4 -4
- package/src/web/src/composer.ts +4 -4
- package/src/web/src/hub.ts +1 -1
- package/src/web/src/markdown.ts +0 -0
- package/src/web/src/memory-panel.ts +1 -1
- package/src/web/src/model-picker.ts +1 -1
- package/src/web/src/palette.ts +1 -1
- package/src/web/src/protocol.ts +3 -39
- package/src/web/src/sessions.ts +1 -1
- package/src/web/src/ui-catalog.ts +4 -18
- package/src/web-assets.ts +47 -0
- package/src/weights.ts +55 -9
- package/docs/archive/investigations/curve-runs/bisector-route.json +0 -98
- package/docs/archive/investigations/curve-runs/bisector-trace.json +0 -1393
- package/docs/archive/investigations/curve-runs/curve-terrain.json +0 -1179
- package/docs/archive/investigations/curve-runs/curve-terrain.svg +0 -42
- package/docs/archive/investigations/hlg-ab.html +0 -34
- package/docs/archive/investigations/hlg-explorer.html +0 -238
- package/docs/archive/investigations/hlg-figs/cliff.svg +0 -1
- package/docs/archive/investigations/hlg-figs/cross.svg +0 -1
- package/docs/archive/investigations/hlg-figs/edges.svg +0 -1
- package/docs/archive/investigations/hlg-figs/k20-grids.svg +0 -1
- package/docs/archive/investigations/hlg-figs/k20-peaks.svg +0 -1
- package/docs/archive/investigations/hlg-figs/lw-curve.svg +0 -1
- package/docs/archive/investigations/hlg-figs/terrain.svg +0 -1
- package/docs/archive/investigations/hlg-report.html +0 -262
- package/docs/archive/investigations/hlg-runs/hlg-ab.json +0 -149
- package/docs/archive/investigations/hlg-runs/hlg-blind-prompts.md +0 -87
- package/docs/archive/investigations/hlg-runs/hlg-blind.json +0 -107
- package/docs/archive/investigations/hlg-runs/hlg-cliff.json +0 -197
- package/docs/archive/investigations/hlg-runs/hlg-cross.json +0 -505
- package/docs/archive/investigations/hlg-runs/hlg-edge.json +0 -388
- package/docs/archive/investigations/hlg-runs/hlg-eval1.json +0 -25
- package/docs/archive/investigations/hlg-runs/hlg-frontier.json +0 -86
- package/docs/archive/investigations/hlg-runs/hlg-grid.json +0 -242
- package/docs/archive/investigations/hlg-runs/hlg-grid2.json +0 -343
- package/docs/archive/investigations/hlg-runs/hlg-lw-coarse.json +0 -110
- package/docs/archive/investigations/hlg-runs/hlg-map.json +0 -383
- package/docs/archive/investigations/hlg-runs/run0-original.log +0 -159
- package/docs/archive/investigations/hlg-runs/runA-recommended.log +0 -131
- package/docs/archive/investigations/hlg-runs/runAA-cliff-cpm5.log +0 -26
- package/docs/archive/investigations/hlg-runs/runAB-grid2-e4b.log +0 -18
- package/docs/archive/investigations/hlg-runs/runAC-peak-e4b-partial.log +0 -25
- package/docs/archive/investigations/hlg-runs/runAD-ab-samples.log +0 -8
- package/docs/archive/investigations/hlg-runs/runAE-edge-e4b.log +0 -51
- package/docs/archive/investigations/hlg-runs/runAF-logit-calibration.log +0 -10
- package/docs/archive/investigations/hlg-runs/runAG-eval-config2.log +0 -16
- package/docs/archive/investigations/hlg-runs/runB-gain-variants.log +0 -192
- package/docs/archive/investigations/hlg-runs/runC-pivots.log +0 -162
- package/docs/archive/investigations/hlg-runs/runD-oetf.log +0 -132
- package/docs/archive/investigations/hlg-runs/runE-eotf.log +0 -162
- package/docs/archive/investigations/hlg-runs/runF-shaper-working.log +0 -86
- package/docs/archive/investigations/hlg-runs/runG-shaper-sweep.log +0 -101
- package/docs/archive/investigations/hlg-runs/runH-wsweep.log +0 -176
- package/docs/archive/investigations/hlg-runs/runI-asweep.log +0 -176
- package/docs/archive/investigations/hlg-runs/runJ-knobmap.log +0 -49
- package/docs/archive/investigations/hlg-runs/runK-frontier.log +0 -19
- package/docs/archive/investigations/hlg-runs/runL-widemap.log +0 -65
- package/docs/archive/investigations/hlg-runs/runM-frontier-emb.log +0 -15
- package/docs/archive/investigations/hlg-runs/runN-verify.log +0 -116
- package/docs/archive/investigations/hlg-runs/runO-frontier-seed5000.log +0 -15
- package/docs/archive/investigations/hlg-runs/runP-grid-AxSm.log +0 -15
- package/docs/archive/investigations/hlg-runs/runQ-grid-tgW.log +0 -15
- package/docs/archive/investigations/hlg-runs/runR-blind-transcript.log +0 -79
- package/docs/archive/investigations/hlg-runs/runS-cross-coherence.log +0 -33
- package/docs/archive/investigations/hlg-runs/runT-cross-cpm5.log +0 -33
- package/docs/archive/investigations/hlg-runs/runU-cross-12b.log +0 -33
- package/docs/archive/investigations/hlg-runs/runV-lw-e4b.log +0 -22
- package/docs/archive/investigations/hlg-runs/runW-lw-12b.log +0 -22
- package/docs/archive/investigations/hlg-runs/runX-lw-cpm5.log +0 -22
- package/docs/archive/investigations/hlg-runs/runY-cliff-e4b.log +0 -26
- package/docs/archive/investigations/hlg-runs/runZ-cliff-12b.log +0 -26
- package/docs/archive/mlx-bun-lab-report.html +0 -275
- package/docs/archive/wwdc-mlx-bun.html +0 -848
- package/docs/design/adapters-end-to-end.md +0 -205
- package/docs/design/batching-perf-path.md +0 -255
- package/docs/design/batching-v2-plan.md +0 -529
- package/docs/design/bucketing-stage.md +0 -197
- package/docs/design/compat-cli-surface-design.md +0 -230
- package/docs/design/docs-reorg-plan.md +0 -165
- package/docs/design/dspark-serving-program.md +0 -371
- package/docs/design/dspark-speculative-decoding.md +0 -318
- package/docs/design/grammar-spec-batching-integration.md +0 -301
- package/docs/design/memory-inference-path.md +0 -422
- package/docs/design/memory-synthesis.md +0 -287
- package/docs/design/memory-system.md +0 -237
- package/docs/design/mlx-lm-serving-execution-seam.md +0 -81
- package/docs/design/mlx-lm-tool-parity-plan.md +0 -545
- package/docs/design/omlx-adoption-map.md +0 -98
- package/docs/design/orpo-dynamic-lambda.md +0 -220
- package/docs/design/orpo-future-enhancements.md +0 -340
- package/docs/design/paged-kv-cache.md +0 -214
- package/docs/design/parallel-slots.md +0 -567
- package/docs/design/parity-tier-dag.md +0 -161
- package/docs/design/repo-cleanup-plan.md +0 -231
- package/docs/design/runtime-isolation.md +0 -263
- package/docs/design/segmented-backward-training.md +0 -543
- package/docs/design/spec-decode-larger-targets.md +0 -229
- package/docs/design/ssd-kv-cold-tier.md +0 -415
- package/docs/design/structured-output.md +0 -484
- package/docs/design/tauri-desktop-app.md +0 -127
- package/docs/design/the-dreaming-master-plan.md +0 -445
- package/docs/design/turboquant-kv.md +0 -235
- package/docs/design/turboquant-weights.md +0 -467
- package/docs/design/w4a16-compute-precision-spike.md +0 -232
- package/docs/design/web-chat-beat-matrix.md +0 -315
- package/docs/design/write-pipeline-entity.md +0 -468
- package/docs/planning/IDEAS.md +0 -69
- package/docs/reference/embedding.md +0 -197
- package/docs/reference/features-matrix.md +0 -101
- package/docs/reference/orpo-quickstart.md +0 -135
- package/src/flags.ts +0 -11
- /package/docs/{design → archive/investigations}/colibri-glm52-port.md +0 -0
- /package/docs/{planning → archive/planning}/chunk-task-roadmap.md +0 -0
- /package/docs/{planning → archive/planning}/curve-sampler-research-plan.md +0 -0
- /package/docs/{planning → archive/planning}/memory-docs-and-dag-plan.md +0 -0
- /package/docs/{planning → archive/planning}/pi-integration-review.md +0 -0
- /package/docs/{planning → archive/planning}/release-notes-v0.2.0.md +0 -0
- /package/src/{memory-plan.ts → admission-plan.ts} +0 -0
- /package/{docs/archive/investigations → src/serve/assets}/curve-terrain.html +0 -0
- /package/{docs/dag → src/serve/assets}/training-inference-map.html +0 -0
package/src/model/qwen3_5.ts
CHANGED
|
@@ -12,9 +12,11 @@
|
|
|
12
12
|
import type { ModelConfig } from "../config";
|
|
13
13
|
import type { Weights } from "../weights";
|
|
14
14
|
import { MlxArray } from "../mlx/array";
|
|
15
|
-
import { Dtype } from "../mlx/ffi";
|
|
15
|
+
import { Dtype, deviceArchitecture } from "../mlx/ffi";
|
|
16
16
|
import * as ops from "../mlx/ops";
|
|
17
17
|
import { CompiledFunction } from "../mlx/compile";
|
|
18
|
+
import { qwenAppendChunkSize } from "./qwen-append";
|
|
19
|
+
import { TrellisLinear, fusedGateUpEligible, fusedGateUpSwiglu, TRELLIS_MATVEC_MAX_M } from "./trellis-linear";
|
|
18
20
|
import {
|
|
19
21
|
argmaxLastPosition,
|
|
20
22
|
disposeTriple,
|
|
@@ -29,7 +31,10 @@ import {
|
|
|
29
31
|
type Cache,
|
|
30
32
|
type Mask,
|
|
31
33
|
} from "./gemma4-base";
|
|
34
|
+
import { qwen35WeightsView } from "./qwen3_5-checkpoint";
|
|
35
|
+
import { materializeCopy } from "../mlx/materialize";
|
|
32
36
|
import { gatedDeltaUpdate, SSMCache } from "./qwen3-delta";
|
|
37
|
+
import type { QwenConvolution } from "./qwen-conv";
|
|
33
38
|
import {
|
|
34
39
|
activeMrope, applyInterleavedRope, buildMropePositions, mropeInvFreq,
|
|
35
40
|
setActiveMrope, type MropeRequestState,
|
|
@@ -107,6 +112,10 @@ export function compiledSilu(x: MlxArray): MlxArray {
|
|
|
107
112
|
|
|
108
113
|
/** Gated-DeltaNet linear-attention layer (mlx-lm GatedDeltaNet). */
|
|
109
114
|
export class GatedDeltaNet {
|
|
115
|
+
/** Per-model experiment seam; null retains the oracle graph. The same
|
|
116
|
+
* implementation advances speculative rollback prefixes. Borrowed inputs,
|
|
117
|
+
* owned activation and independent state tail; no global runtime mutation. */
|
|
118
|
+
convolution: QwenConvolution | null = null;
|
|
110
119
|
readonly inProjQkv: QuantizedLinear;
|
|
111
120
|
readonly inProjZ: QuantizedLinear;
|
|
112
121
|
readonly inProjB: QuantizedLinear;
|
|
@@ -146,7 +155,24 @@ export class GatedDeltaNet {
|
|
|
146
155
|
this.normWeight = weights.tensor(`${prefix}.norm.weight`);
|
|
147
156
|
}
|
|
148
157
|
|
|
149
|
-
|
|
158
|
+
#convolve(qkv: MlxArray, state: MlxArray): [MlxArray, MlxArray] {
|
|
159
|
+
if (this.convolution) return this.convolution(qkv, state, this.convWeight);
|
|
160
|
+
const [B, S, D] = qkv.shape as [number, number, number];
|
|
161
|
+
const nKeep = this.convKernel - 1;
|
|
162
|
+
const input = ops.concatAxis([state, qkv], 1);
|
|
163
|
+
// MLX copy and contiguous can both alias the whole prefill buffer.
|
|
164
|
+
// Materialize only the tail so cache residency follows its logical size.
|
|
165
|
+
const view = input.slice([0, S, 0], [B, S + nKeep, D]);
|
|
166
|
+
const tail = materializeCopy(view);
|
|
167
|
+
view.dispose();
|
|
168
|
+
const conv = ops.conv1d(input, this.convWeight, 1, 0, 1, D);
|
|
169
|
+
input.dispose();
|
|
170
|
+
const out = compiledSilu(conv);
|
|
171
|
+
conv.dispose();
|
|
172
|
+
return [out, tail];
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
forward(x: MlxArray, cache: SSMCache, independentRows = false): MlxArray {
|
|
150
176
|
const [B, S] = x.shape as [number, number, number];
|
|
151
177
|
const convDim = this.keyDim * 2 + this.valueDim;
|
|
152
178
|
const nKeep = this.convKernel - 1;
|
|
@@ -168,38 +194,25 @@ export class GatedDeltaNet {
|
|
|
168
194
|
}
|
|
169
195
|
|
|
170
196
|
const t0 = prof ? performance.now() : 0;
|
|
171
|
-
const qkv = this.inProjQkv.forward(x); // [B,S,convDim]
|
|
172
|
-
let z = this.inProjZ.forward(x);
|
|
197
|
+
const qkv = this.inProjQkv.forward(x, independentRows); // [B,S,convDim]
|
|
198
|
+
let z = this.inProjZ.forward(x, independentRows);
|
|
173
199
|
z = disposing(z, ops.reshape(z, [B, S, this.numVHeads, this.headVDim]));
|
|
174
|
-
const b = this.inProjB.forward(x); // [B,S,numVHeads]
|
|
175
|
-
const a = this.inProjA.forward(x);
|
|
200
|
+
const b = this.inProjB.forward(x, independentRows); // [B,S,numVHeads]
|
|
201
|
+
const a = this.inProjA.forward(x, independentRows);
|
|
176
202
|
if (prof) { ops.evalAll([qkv, z, b, a]); prof.proj = (prof.proj ?? 0) + performance.now() - t0; }
|
|
177
203
|
const tc = prof ? performance.now() : 0; // [B,S,numVHeads]
|
|
178
204
|
|
|
179
205
|
// Causal depthwise conv with the conv-state prefix (B=1: no ssm mask).
|
|
180
206
|
const convState =
|
|
181
207
|
cache.conv ?? ops.zeros([B, nKeep, convDim], x.dtype);
|
|
182
|
-
const
|
|
208
|
+
const [convOut, newConv] = this.#convolve(qkv, convState);
|
|
183
209
|
if (!cache.conv) convState.dispose();
|
|
184
210
|
if (spec) spec.qkv = qkv;
|
|
185
211
|
else qkv.dispose();
|
|
186
|
-
// New conv state = last nKeep rows. MUST be a TRUE copy (mx.copy):
|
|
187
|
-
// this tail slice is already row-contiguous at B=1, so ops.contiguous
|
|
188
|
-
// is a no-op VIEW sharing convInput's buffer — caching it pinned the
|
|
189
|
-
// whole [B, S+nKeep, convDim] chunk buffer (~42 MB/layer/chunk, 48
|
|
190
|
-
// layers = the measured 2.0 GB-per-2048-chunk prefill leak; 46 GB
|
|
191
|
-
// active at 32k, async-GPU-OOM on 24 GB — M4 2026-08-20).
|
|
192
|
-
const newConvView = convInput.slice([0, S, 0], [B, S + nKeep, convDim]);
|
|
193
|
-
const newConv = ops.copyOf(newConvView);
|
|
194
|
-
newConvView.dispose();
|
|
195
212
|
if (spec) spec.prevConv = cache.conv;
|
|
196
213
|
else cache.conv?.dispose();
|
|
197
214
|
cache.conv = newConv;
|
|
198
215
|
|
|
199
|
-
const conv = ops.conv1d(convInput, this.convWeight, 1, 0, 1, convDim);
|
|
200
|
-
convInput.dispose();
|
|
201
|
-
const convOut = compiledSilu(conv); // nn.silu (mx.compile), matches mlx-lm
|
|
202
|
-
conv.dispose();
|
|
203
216
|
if (prof) { ops.evalAll([convOut]); prof.conv = (prof.conv ?? 0) + performance.now() - tc; }
|
|
204
217
|
const tn = prof ? performance.now() : 0;
|
|
205
218
|
|
|
@@ -248,7 +261,7 @@ export class GatedDeltaNet {
|
|
|
248
261
|
z.dispose();
|
|
249
262
|
const merged = ops.reshape(gated, [B, S, this.valueDim]);
|
|
250
263
|
gated.dispose();
|
|
251
|
-
const result = this.outProj.forward(merged);
|
|
264
|
+
const result = this.outProj.forward(merged, independentRows);
|
|
252
265
|
merged.dispose();
|
|
253
266
|
if (prof) { ops.evalAll([result]); prof.out = (prof.out ?? 0) + performance.now() - to; }
|
|
254
267
|
return result;
|
|
@@ -273,21 +286,12 @@ export class GatedDeltaNet {
|
|
|
273
286
|
const qkvPfx = ops.contiguous(qkvPfxView);
|
|
274
287
|
qkvPfxView.dispose();
|
|
275
288
|
const convState = cache.conv ?? ops.zeros([B, nKeep, convDim], qkvPfx.dtype);
|
|
276
|
-
const
|
|
289
|
+
const [convOut, newConv] = this.#convolve(qkvPfx, convState);
|
|
277
290
|
if (!cache.conv) convState.dispose();
|
|
278
291
|
qkvPfx.dispose();
|
|
279
|
-
// TRUE copy, same reason as forward(): the contiguous tail slice would
|
|
280
|
-
// otherwise be a view pinning the whole replay convInput buffer.
|
|
281
|
-
const rConvView = convInput.slice([0, keep, 0], [B, keep + nKeep, convDim]);
|
|
282
|
-
const newConv = ops.copyOf(rConvView);
|
|
283
|
-
rConvView.dispose();
|
|
284
292
|
cache.conv?.dispose();
|
|
285
293
|
cache.conv = newConv;
|
|
286
294
|
|
|
287
|
-
const conv = ops.conv1d(convInput, this.convWeight, 1, 0, 1, convDim);
|
|
288
|
-
convInput.dispose();
|
|
289
|
-
const convOut = compiledSilu(conv);
|
|
290
|
-
conv.dispose();
|
|
291
295
|
const [qFlat, kFlat, vFlat] = ops.split(
|
|
292
296
|
convOut, [this.keyDim, 2 * this.keyDim], -1,
|
|
293
297
|
) as [MlxArray, MlxArray, MlxArray];
|
|
@@ -365,18 +369,18 @@ export class Qwen3Attention {
|
|
|
365
369
|
this.kNorm = new RMSNorm(weights.tensor(`${prefix}.k_norm.weight`), t.rmsNormEps);
|
|
366
370
|
}
|
|
367
371
|
|
|
368
|
-
forward(x: MlxArray, mask: Mask, cache: Cache): MlxArray {
|
|
372
|
+
forward(x: MlxArray, mask: Mask, cache: Cache, independentRows = false): MlxArray {
|
|
369
373
|
const [B, L] = x.shape as [number, number, number];
|
|
370
374
|
|
|
371
375
|
// q_proj emits 2× head_dim per head → split into queries + gate.
|
|
372
|
-
const qp = this.qProj.forward(x);
|
|
376
|
+
const qp = this.qProj.forward(x, independentRows);
|
|
373
377
|
const qpr = disposing(qp, ops.reshape(qp, [B, L, this.nHeads, this.headDim * 2]));
|
|
374
378
|
const [qHeads, gateHeads] = ops.split(qpr, [this.headDim], -1) as [MlxArray, MlxArray];
|
|
375
379
|
qpr.dispose();
|
|
376
380
|
const gate = disposing(gateHeads, ops.reshape(gateHeads, [B, L, this.nHeads * this.headDim]));
|
|
377
381
|
|
|
378
|
-
let k = this.kProj.forward(x);
|
|
379
|
-
let v = this.vProj.forward(x);
|
|
382
|
+
let k = this.kProj.forward(x, independentRows);
|
|
383
|
+
let v = this.vProj.forward(x, independentRows);
|
|
380
384
|
|
|
381
385
|
// q/k norm over head_dim BEFORE transpose (reference order).
|
|
382
386
|
let q = this.qNorm.forward(qHeads);
|
|
@@ -391,7 +395,7 @@ export class Qwen3Attention {
|
|
|
391
395
|
// Batched decode: the scheduler's mask wrapper exposes each row's REAL
|
|
392
396
|
// position as ropeOffsetArr (rows have different prompt lengths); the
|
|
393
397
|
// dynamic-offset kernel is the same fast::rope, bit-exact vs the static
|
|
394
|
-
// form (tests/compile.test.ts). Serial lane: scalar offset, unchanged.
|
|
398
|
+
// form (tests/unit/compile.test.ts). Serial lane: scalar offset, unchanged.
|
|
395
399
|
// Vision requests (serial lane only) install activeMrope for the current
|
|
396
400
|
// forward: 3D interleaved positions via the manual apply — the reference
|
|
397
401
|
// never uses the fused fast-rope kernel when position_ids are supplied,
|
|
@@ -439,32 +443,56 @@ export class Qwen3Attention {
|
|
|
439
443
|
const gated = ops.mul(merged, sig);
|
|
440
444
|
merged.dispose();
|
|
441
445
|
sig.dispose();
|
|
442
|
-
const out = this.oProj.forward(gated);
|
|
446
|
+
const out = this.oProj.forward(gated, independentRows);
|
|
443
447
|
gated.dispose();
|
|
444
448
|
return out;
|
|
445
449
|
}
|
|
446
450
|
}
|
|
447
451
|
|
|
452
|
+
/** MLP projections are affine-quantized (QuantizedLinear) or, in a Q2b
|
|
453
|
+
* packed-trellis artifact, TrellisLinear — chosen per module by the config's
|
|
454
|
+
* quantization entry (`mode: "trellis"`). */
|
|
455
|
+
export type MlpLinear = QuantizedLinear | TrellisLinear;
|
|
456
|
+
function loadMlpLinear(weights: Weights, path: string, config: ModelConfig): MlpLinear {
|
|
457
|
+
if (!TrellisLinear.isTrellis(config, path)) return QuantizedLinear.load(weights, path, config);
|
|
458
|
+
// M4 Pro measurements support the 27B down projection at M3/4. The
|
|
459
|
+
// operation also checks variant, dtype and packed-code layout eligibility.
|
|
460
|
+
const useSharedScatterCodebook = config.text.hiddenSize === 5120 &&
|
|
461
|
+
config.text.intermediateSize === 17408 && path.endsWith(".down_proj");
|
|
462
|
+
return TrellisLinear.load(weights, path, config, useSharedScatterCodebook);
|
|
463
|
+
}
|
|
464
|
+
|
|
448
465
|
export class Qwen3MLP {
|
|
449
|
-
readonly gate:
|
|
450
|
-
readonly up:
|
|
451
|
-
readonly down:
|
|
466
|
+
readonly gate: MlpLinear;
|
|
467
|
+
readonly up: MlpLinear;
|
|
468
|
+
readonly down: MlpLinear;
|
|
452
469
|
|
|
453
470
|
constructor(weights: Weights, config: ModelConfig, prefix: string) {
|
|
454
|
-
this.gate =
|
|
455
|
-
this.up =
|
|
456
|
-
this.down =
|
|
471
|
+
this.gate = loadMlpLinear(weights, `${prefix}.gate_proj`, config);
|
|
472
|
+
this.up = loadMlpLinear(weights, `${prefix}.up_proj`, config);
|
|
473
|
+
this.down = loadMlpLinear(weights, `${prefix}.down_proj`, config);
|
|
457
474
|
}
|
|
458
475
|
|
|
459
|
-
forward(x: MlxArray): MlxArray {
|
|
460
|
-
|
|
461
|
-
|
|
476
|
+
forward(x: MlxArray, inputRowContiguous = false, independentRows = false): MlxArray {
|
|
477
|
+
// Packed-trellis decode (M ≤ 4): gate, up and the swiglu in ONE kernel —
|
|
478
|
+
// x read once, no gate/up vectors materialized. This Lab path retains
|
|
479
|
+
// the packed activation arithmetic documented in turboquant.md.
|
|
480
|
+
if (this.gate instanceof TrellisLinear && this.up instanceof TrellisLinear &&
|
|
481
|
+
fusedGateUpEligible(this.gate, this.up) &&
|
|
482
|
+
x.shape.slice(0, -1).reduce((a, b) => a * b, 1) <= TRELLIS_MATVEC_MAX_M) {
|
|
483
|
+
const hidden = fusedGateUpSwiglu(x, this.gate, this.up);
|
|
484
|
+
const out = this.down instanceof QuantizedLinear ? this.down.forward(hidden, independentRows) : this.down.forward(hidden);
|
|
485
|
+
hidden.dispose();
|
|
486
|
+
return out;
|
|
487
|
+
}
|
|
488
|
+
const g = this.gate instanceof TrellisLinear ? this.gate.forward(x, inputRowContiguous) : this.gate.forward(x, independentRows);
|
|
489
|
+
const u = this.up instanceof TrellisLinear ? this.up.forward(x, inputRowContiguous) : this.up.forward(x, independentRows);
|
|
462
490
|
// Oracle: down_proj(swiglu(gate_proj(x), up_proj(x))) — swiglu ALWAYS compiled
|
|
463
491
|
// (mlx-lm's @mx.compile swiglu; no unfused silu+mul, matches its kernel set).
|
|
464
492
|
const hidden = compiledSwiglu(g, u);
|
|
465
493
|
g.dispose();
|
|
466
494
|
u.dispose();
|
|
467
|
-
const out = this.down.forward(hidden);
|
|
495
|
+
const out = this.down instanceof QuantizedLinear ? this.down.forward(hidden, independentRows) : this.down.forward(hidden);
|
|
468
496
|
hidden.dispose();
|
|
469
497
|
return out;
|
|
470
498
|
}
|
|
@@ -489,16 +517,18 @@ export class Qwen3Layer {
|
|
|
489
517
|
this.postAttnNorm = new RMSNorm(weights.tensor(`${prefix}.post_attention_layernorm.weight`), config.text.rmsNormEps);
|
|
490
518
|
}
|
|
491
519
|
|
|
492
|
-
forward(x: MlxArray, faMask: Mask, cache: Cache): MlxArray {
|
|
520
|
+
forward(x: MlxArray, faMask: Mask, cache: Cache, independentRows = false): MlxArray {
|
|
493
521
|
const xn = this.inputNorm.forward(x);
|
|
494
522
|
const r = this.isLinear
|
|
495
|
-
? this.linearAttn!.forward(xn, cache as SSMCache)
|
|
496
|
-
: this.selfAttn!.forward(xn, faMask, cache);
|
|
523
|
+
? this.linearAttn!.forward(xn, cache as SSMCache, independentRows)
|
|
524
|
+
: this.selfAttn!.forward(xn, faMask, cache, independentRows);
|
|
497
525
|
xn.dispose();
|
|
498
526
|
const h = ops.add(x, r);
|
|
499
527
|
r.dispose();
|
|
500
528
|
const hn = this.postAttnNorm.forward(h);
|
|
501
|
-
|
|
529
|
+
// RMSNorm allocates an aligned row-contiguous output. Pass that layout
|
|
530
|
+
// proof so Trellis can match native small-prefill matmul without an eval.
|
|
531
|
+
const m = this.mlp.forward(hn, true, independentRows);
|
|
502
532
|
hn.dispose();
|
|
503
533
|
const out = ops.add(h, m);
|
|
504
534
|
h.dispose();
|
|
@@ -522,6 +552,14 @@ export class Qwen35Model {
|
|
|
522
552
|
readonly faIdx: number;
|
|
523
553
|
|
|
524
554
|
constructor(weights: Weights, config: ModelConfig) {
|
|
555
|
+
// Checkpoint-generation normalization BEFORE the first tensor() call: the
|
|
556
|
+
// 5.8-family export names the trunk `model.language_model.*` with a
|
|
557
|
+
// top-level `lm_head`, ships `mtp.*` in-repo, and stores RMSNorm gains as
|
|
558
|
+
// γ−1 with HF-layout conv1d. The view maps all of that onto the names and
|
|
559
|
+
// values this graph reads (mlx-lm's post-sanitize space). No-op — nothing
|
|
560
|
+
// installed at all — for artifacts already in that space.
|
|
561
|
+
const view = qwen35WeightsView(weights);
|
|
562
|
+
if (view) weights.setView(view);
|
|
525
563
|
this.config = config;
|
|
526
564
|
this.tied = config.text.tieWordEmbeddings;
|
|
527
565
|
this.weightsBytes = [...weights.shards.files.values()]
|
|
@@ -555,9 +593,10 @@ export class Qwen35Model {
|
|
|
555
593
|
out.set(`${p}.linear_attn.in_proj_a`, l.linearAttn.inProjA);
|
|
556
594
|
out.set(`${p}.linear_attn.out_proj`, l.linearAttn.outProj);
|
|
557
595
|
}
|
|
558
|
-
|
|
559
|
-
out.set(`${p}.mlp.
|
|
560
|
-
out.set(`${p}.mlp.
|
|
596
|
+
// Trellis-coded MLP tensors are not LoRA targets (no adapter seam yet).
|
|
597
|
+
if (l.mlp.gate instanceof QuantizedLinear) out.set(`${p}.mlp.gate_proj`, l.mlp.gate);
|
|
598
|
+
if (l.mlp.up instanceof QuantizedLinear) out.set(`${p}.mlp.up_proj`, l.mlp.up);
|
|
599
|
+
if (l.mlp.down instanceof QuantizedLinear) out.set(`${p}.mlp.down_proj`, l.mlp.down);
|
|
561
600
|
}
|
|
562
601
|
return out;
|
|
563
602
|
}
|
|
@@ -566,6 +605,38 @@ export class Qwen35Model {
|
|
|
566
605
|
return this.layers.map((l) => (l.isLinear ? new SSMCache() : new KVCache()));
|
|
567
606
|
}
|
|
568
607
|
|
|
608
|
+
/** The 27B append path keeps the native M1 affine arithmetic while Trellis
|
|
609
|
+
* shares up to four rows. Other shapes retain single-token execution. */
|
|
610
|
+
createAppend(policy: { hasAdapters: boolean; pagedKv: boolean }) {
|
|
611
|
+
const t = this.config.text;
|
|
612
|
+
if (policy.hasAdapters || policy.pagedKv || this.loraState.active.length || this.mrope ||
|
|
613
|
+
t.hiddenSize !== 5120 || t.intermediateSize !== 17408 || this.layers.length !== 64 ||
|
|
614
|
+
t.headDim !== 256 || t.numAttentionHeads !== 24 || t.numKeyValueHeads !== 4)
|
|
615
|
+
return null;
|
|
616
|
+
if (deviceArchitecture() !== "applegpu_g16s") return null;
|
|
617
|
+
const qualified = (linear: QuantizedLinear | TrellisLinear) => {
|
|
618
|
+
if (linear instanceof TrellisLinear) return true;
|
|
619
|
+
const { mode, bits, groupSize } = linear.spec;
|
|
620
|
+
return mode === "affine" && [2, 3, 4, 6, 8].includes(bits) && [32, 64, 128].includes(groupSize);
|
|
621
|
+
};
|
|
622
|
+
for (const layer of this.layers) {
|
|
623
|
+
const a = layer.linearAttn, s = layer.selfAttn;
|
|
624
|
+
const attention = a ? [a.inProjQkv, a.inProjZ, a.inProjB, a.inProjA, a.outProj]
|
|
625
|
+
: [s!.qProj, s!.kProj, s!.vProj, s!.oProj];
|
|
626
|
+
if (!attention.every(qualified) || ![layer.mlp.gate, layer.mlp.up, layer.mlp.down].every(qualified))
|
|
627
|
+
return null;
|
|
628
|
+
}
|
|
629
|
+
return {
|
|
630
|
+
maxChunkSize: (state: readonly Cache[]) => qwenAppendChunkSize(state[0]!.offset),
|
|
631
|
+
forwardHidden: (ids: MlxArray, cache: Cache[]): MlxArray => {
|
|
632
|
+
if (ids.shape.length !== 2 || ids.shape[0] !== 1 || ids.shape[1]! > 4)
|
|
633
|
+
throw new Error("Qwen committed-token append supports one row and at most four positions");
|
|
634
|
+
const hidden = this.embed.encode(ids);
|
|
635
|
+
return this.forwardLayers(hidden, cache, true);
|
|
636
|
+
},
|
|
637
|
+
};
|
|
638
|
+
}
|
|
639
|
+
|
|
569
640
|
forwardHidden(ids: MlxArray, cache: Cache[]): MlxArray {
|
|
570
641
|
const h = this.embed.encode(ids);
|
|
571
642
|
return this.forwardLayers(h, cache);
|
|
@@ -576,6 +647,8 @@ export class Qwen35Model {
|
|
|
576
647
|
* the bit-exact fast-rope path). While set, forwardLayers installs the
|
|
577
648
|
* per-forward interleaved cos/sin consumed by every full-attn layer. */
|
|
578
649
|
mrope: MropeRequestState | null = null;
|
|
650
|
+
/** Serving's memory-pressure check, scoped to the serial request. */
|
|
651
|
+
prefillMemoryGuard: (() => void) | null = null;
|
|
579
652
|
#mropeInvFreq: MlxArray | null = null;
|
|
580
653
|
|
|
581
654
|
/** Vision prefill: spliced input embeddings [1, L, H] (image features
|
|
@@ -609,7 +682,7 @@ export class Qwen35Model {
|
|
|
609
682
|
tap.captured.set(i, copy);
|
|
610
683
|
}
|
|
611
684
|
|
|
612
|
-
protected forwardLayers(h0: MlxArray, cache: Cache[]): MlxArray {
|
|
685
|
+
protected forwardLayers(h0: MlxArray, cache: Cache[], independentRows = false): MlxArray {
|
|
613
686
|
const L = h0.shape[1]!;
|
|
614
687
|
// One full-attention mask shared by all full layers (same offset); linear
|
|
615
688
|
// layers see no ssm mask at B=1.
|
|
@@ -633,10 +706,21 @@ export class Qwen35Model {
|
|
|
633
706
|
| undefined;
|
|
634
707
|
try {
|
|
635
708
|
for (let i = 0; i < this.layers.length; i++) {
|
|
709
|
+
if (L > 1) this.prefillMemoryGuard?.();
|
|
636
710
|
const tl = prof ? performance.now() : 0;
|
|
637
|
-
const next = this.layers[i]!.forward(h, faMask, cache[i]
|
|
711
|
+
const next = this.layers[i]!.forward(h, faMask, cache[i]!, independentRows);
|
|
638
712
|
h.dispose();
|
|
639
713
|
h = next;
|
|
714
|
+
const mlp = this.layers[i]!.mlp;
|
|
715
|
+
if (L > TRELLIS_MATVEC_MAX_M &&
|
|
716
|
+
[mlp.gate, mlp.up, mlp.down].some((p) => p instanceof TrellisLinear && !p.fallback)) {
|
|
717
|
+
// Materialize the cache outputs too. In particular, the tiny
|
|
718
|
+
// copied conv tail is not a dependency of `h`; leaving it lazy
|
|
719
|
+
// pins the whole prefill conv buffer until the chunk ends.
|
|
720
|
+
const state = cache[i]!.state();
|
|
721
|
+
try { ops.evalAll([h, ...state]); }
|
|
722
|
+
finally { if (cache[i]!.stateNeedsDispose) for (const a of state) a.dispose(); }
|
|
723
|
+
}
|
|
640
724
|
if (prof) {
|
|
641
725
|
ops.evalAll([h]);
|
|
642
726
|
const key = this.layers[i]!.isLinear ? "layerLin" : "layerFull";
|
package/src/model/support.ts
CHANGED
|
@@ -56,7 +56,7 @@ export function isDrafterModelType(modelType: string): boolean {
|
|
|
56
56
|
|
|
57
57
|
/** DiffusionGemma (model_type `diffusion_gemma`): block/masked-diffusion canvas
|
|
58
58
|
* model. Non-autoregressive — routed through the diffusion engine, not the AR
|
|
59
|
-
* loop. See docs/design/
|
|
59
|
+
* loop. See docs/design/generic-model-support.md. */
|
|
60
60
|
export function isDiffusionGemmaConfig(config: ModelConfig): boolean {
|
|
61
61
|
return config.modelType === "diffusion_gemma";
|
|
62
62
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Experimental variant 8, k=3 / T=256 / L<=12 only.
|
|
2
|
+
// The word-per-lane kernel uses 24 of 32 SIMD lanes for a 3-bit block.
|
|
3
|
+
// Assign eight outputs to every lane, load adjacent packed words, and align
|
|
4
|
+
// them once so each unrolled decoder has constant shifts. Row accumulation,
|
|
5
|
+
// split boundaries and the separate partial reduction stay identical to v6.
|
|
6
|
+
export const BALANCED_SCATTER_SOURCE = String.raw`
|
|
7
|
+
const uint lane = thread_index_in_simdgroup;
|
|
8
|
+
const uint sg = simdgroup_index_in_threadgroup;
|
|
9
|
+
const uint block = thread_position_in_grid.y * (uint)SG_TG + sg;
|
|
10
|
+
const uint nBlocks = (uint)C / (uint)BT;
|
|
11
|
+
const uint zi = thread_position_in_grid.z;
|
|
12
|
+
const uint sample = zi / (uint)SPLITS;
|
|
13
|
+
const uint split = zi - sample * (uint)SPLITS;
|
|
14
|
+
if (block >= nBlocks || sample >= (uint)M) return;
|
|
15
|
+
const uint wpb = (uint)(BT * K / 32);
|
|
16
|
+
const ulong rowWords = (ulong)(INTERLEAVE ? 2 : nBlocks) * wpb;
|
|
17
|
+
const uint pBase = lane * 8u * (uint)K;
|
|
18
|
+
const uint wi = pBase >> 5u;
|
|
19
|
+
const uint off = pBase & 31u;
|
|
20
|
+
const uint next = (wi + 1u == wpb) ? 0u : wi + 1u;
|
|
21
|
+
const device uint32_t* words = codes + (INTERLEAVE
|
|
22
|
+
? (ulong)(block / 2) * R * 2 * wpb + (block % 2) * wpb : (ulong)block * wpb);
|
|
23
|
+
const uint rowsPer = ((uint)R + (uint)SPLITS - 1u) / (uint)SPLITS;
|
|
24
|
+
const uint r0 = split * rowsPer;
|
|
25
|
+
const uint r1 = metal::min((uint)R, r0 + rowsPer);
|
|
26
|
+
const device T* xs = x + (ulong)sample * (ulong)R;
|
|
27
|
+
float acc[8];
|
|
28
|
+
#pragma clang loop unroll(full)
|
|
29
|
+
for (uint i = 0; i < 8u; ++i) acc[i] = 0.0f;
|
|
30
|
+
for (uint r = r0; r < r1; ++r) {
|
|
31
|
+
const uint word = words[(ulong)r * rowWords + wi];
|
|
32
|
+
const uint nxt = words[(ulong)r * rowWords + next];
|
|
33
|
+
const uint lo = off == 0u ? word : (word >> off) | (nxt << (32u - off));
|
|
34
|
+
const uint hi = off == 0u ? nxt : nxt >> off;
|
|
35
|
+
const float xr = float(xs[r]);
|
|
36
|
+
const float sr = float(scales[r]);
|
|
37
|
+
#pragma clang loop unroll(full)
|
|
38
|
+
for (uint i = 0; i < 8u; ++i) {
|
|
39
|
+
const uint shift = i * (uint)K;
|
|
40
|
+
uint win = lo >> shift;
|
|
41
|
+
if (shift + (uint)L > 32u) win |= hi << (32u - shift);
|
|
42
|
+
win &= (1u << (uint)L) - 1u;
|
|
43
|
+
const float value = (float)trellis_y(win) * (1.0f / 147.800537109375f);
|
|
44
|
+
acc[i] = metal::fma(value * sr, xr, acc[i]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const ulong outBase = ((ulong)sample * (ulong)SPLITS + split) * (ulong)C;
|
|
48
|
+
#pragma clang loop unroll(full)
|
|
49
|
+
for (uint i = 0; i < 8u; ++i)
|
|
50
|
+
partial[outBase + block * (uint)BT + (uint)BT - 1u - lane * 8u - i] = acc[i];
|
|
51
|
+
`;
|