Fork for thermals request add-json-schema-dpeq
0

Configure Feed

Select the types of activity you want to include in your feed.

vmlx-swift / VMLX_README.md
4.5 kB 112 lines
1# vmlx-swift — local development fork 2 3This is a local working copy of `osaurus-ai/mlx-swift` (branch 4`osaurus-0.31.3`) set up as the upstream for `vmlx-swift-lm` optimization 5work. **Not pushed to any remote.** Edits here flow directly into 6`../vmlx-swift-lm` on the next `swift build` because `vmlx-swift-lm`'s 7`Package.swift` uses a local path dependency. 8 9## Layout 10 11| Path | Purpose | 12|------|---------| 13| `~/vmlx-swift` | this fork | 14| `~/vmlx-swift-lm` | model library consuming it | 15 16## Branches 17 18| Branch | Purpose | 19|--------|---------| 20| `osaurus-0.31.3` | pristine `osaurus-ai/mlx-swift` tracking branch, don't edit | 21| `vmlx-0.31.3` (HEAD) | working branch for optimizations | 22 23Submodule `Source/Cmlx/mlx` also has a local branch: 24 25| Branch | Purpose | 26|--------|---------| 27| (detached at upstream) | default `ml-explore/mlx` state | 28| `vmlx-patches-0.31.3` (HEAD) | committed patches for `GatherQMM::output_shapes` + `CustomKernel::set_output_shapes` that `vmlx-swift-lm`'s compiled-kernel path depends on | 29 30## Remotes 31 32| Name | URL | Purpose | 33|------|-----|---------| 34| `osaurus-upstream` | `https://github.com/osaurus-ai/mlx-swift.git` | pull latest osaurus work into `osaurus-0.31.3` | 35 36**No `origin` remote.** A plain `git push` will fail. This is intentional — 37the fork is local-only until we decide to publish. 38 39## Iteration workflow 40 411. Edit a file under `Source/MLX/…` or `Source/Cmlx/mlx/mlx/…`. 422. In `../vmlx-swift-lm`, run `swift build -c release`. SPM picks up the 43 local path dep automatically and rebuilds the Cmlx C++ + MLX Swift 44 modules against the new source. 453. Run a bench (`swift run -c release CompileBench` for op-level, 46 `swift run -c release RunBench` for full Qwen 3.5-35B multi-turn). 474. Iterate. 48 49## Runtime quirk: `default.metallib` 50 51`swift build` from the terminal does NOT compile the `.metal` kernel 52files in `Source/Cmlx/mlx-generated/metal/` into a `default.metallib` 53(only Xcode's build phase does that). As a workaround: 54 55```sh 56cp ~/Library/Developer/Xcode/DerivedData/vmlx-swift-lm-*/Build/Products/Release/mlx-swift_Cmlx.bundle/Contents/Resources/default.metallib \ 57 ~/vmlx-swift-lm/default.metallib 58``` 59 60The C++ loader falls through four paths before finally trying 61`default_mtllib_path` (= literal `"default.metallib"` resolved against 62cwd). Running `swift run` from `vmlx-swift-lm/` with a metallib sitting 63in that directory makes the load succeed. 64 65**TODO:** add an SPM build plugin or prebuild command to `Package.swift` 66that compiles `mlx-generated/metal/*.metal` into 67`Sources/Cmlx/Resources/default.metallib` and declares it as a resource. 68Then the Xcode DerivedData workaround goes away. This is blocked on 69deciding whether to patch Package.swift directly or submit the change 70upstream to `osaurus-ai/mlx-swift`. 71 72## Switching back to URL dependency 73 74When this fork is not needed, edit `vmlx-swift-lm/Package.swift`: 75 76```swift 77// From: 78.package(name: "mlx-swift", path: "../vmlx-swift"), 79// Back to: 80.package(url: "https://github.com/osaurus-ai/mlx-swift", branch: "osaurus-0.31.3"), 81``` 82 83Then `swift package clean && swift build -c release`. 84 85## Current optimization targets 86 87Per `vmlx-swift-lm/docs/research/2026-04-13-decode-speed-to-120.md`, the 88Swift-vs-Python gap on Qwen 3.5-35B-A3B-4bit is ~10-12 tok/s end-to-end, 89and microbench attribution puts it at: 90 911. **~5 tok/s** — Swift eager per-op overhead (~0.5 us/op extra vs Python) 922. **~3 tok/s** — compile-site coverage differences (Python compiles 93 more than Swift captures) 943. **~3 tok/s** — structural: ARC on `MLXArray` class, module-boundary 95 dispatch, heap alloc on every op return 96 97Concrete things to try in this fork: 98 99- [ ] `@inlinable` on hot-path `MLXArray+Ops.swift` methods (`exp`, 100 `add`, `multiply`, `matmul`, `reshape`) **plus** `MLXArray.init(_:)` 101 so cross-module inlining actually works end-to-end 102- [ ] `@inline(__always)` on `MLXArray.ctx` getter to avoid dispatch on 103 every bridge call 104- [ ] Pool `mlx_array_new()` allocations to avoid repeated C-side 105 alloc/free on hot paths (requires mlx-c change) 106- [ ] Investigate whether `MLXArray` can become a struct (with a 107 `ManagedBuffer` holding `mlx_array`) instead of a `final class`. 108 High impact but breaks every caller. 109- [ ] Build plugin for Metal kernel compilation — removes the Xcode 110 DerivedData metallib workaround and enables clean CI builds 111 112Measurements go in the parent repo's research doc.