Pool Apple Silicon Macs for distributed compute and ML training
Project description
MacFleet
Distributed ML training on Apple Silicon. Pool your Macs into a cluster in 5 seconds, run PyTorch or MLX across them, keep zero cloud spend.
macfleet join macfleet join macfleet join
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ MacBook Pro │◄────────►│ MacBook Air │◄────────►│ Mac Studio │
│ M4 Pro │ WiFi / │ M4 │ WiFi / │ M4 Ultra │
│ 16 GPU cores│ ETH / │ 10 GPU cores│ ETH / │ 60 GPU cores│
│ 48 GB RAM │ TB4 │ 16 GB RAM │ TB4 │ 192 GB RAM │
└──────────────┘ └──────────────┘ └──────────────┘
▲ ▲ ▲
└──────────────────────────┴──────────────────────────┘
Ring AllReduce (gradient sync)
Why MacFleet
Apple Silicon is everywhere. Every researcher, student, and founder has a serious ML machine on their desk. What's missing is a way to team them up.
- PyTorch on MPS has no distributed story. NCCL is CUDA-only. Gloo is broken on MPS. Single-GPU-on-MPS only.
- MLX is native but most researchers' code is still PyTorch.
- Cloud is expensive and the iteration loop is slow.
MacFleet fills that gap. Any two Macs on the same WiFi can pool their
GPUs. Security is baked in (HMAC + TLS). Adaptive compression keeps
WiFi viable for gradient sync. The framework-agnostic core lets you
pick your engine (torch or mlx) per call.
Install
pip install macfleet # core
pip install "macfleet[torch]" # + PyTorch
pip install "macfleet[mlx]" # + Apple MLX
pip install "macfleet[all]" # everything
The 5-minute path
1. Scaffold a starter script:
macfleet quickstart
# Wrote my_macfleet_demo.py
2. Run it:
python my_macfleet_demo.py
# Pool world size: 1
# Training done: {'loss': 0.31, 'epochs': 10, 'time_sec': 1.4}
3. Pair a second Mac:
On Mac #1:
macfleet join --bootstrap
# prints a QR code + pairing URL, also copies URL to pasteboard
On Mac #2 (same Apple ID → Handoff pasteboard sync):
macfleet pair && macfleet join
Or: scan the QR from Mac #1 with your iPhone camera. Tap the link. Done.
4. Set enable_pool_distributed=True in your script — training now
spans both Macs.
Features
- Dual engine — PyTorch (MPS) and Apple MLX, same pool infrastructure
- Zero config — mDNS discovery, no coordinator setup, no config files
- Safe task dispatch —
@macfleet.taskregistry + msgpack args (no cloudpickle on the wire) - Adaptive compression — auto-selects TopK + FP16 based on link speed (locally; sparse-on-wire arrives in v2.3, see TODOS.md Issue 3)
- Heterogeneous scheduling — faster Macs get bigger batches, adjusts for thermal throttling
- Secure by default — auto-generated fleet tokens, HMAC mutual auth, mandatory TLS, per-IP rate limiting
- Framework-agnostic core — communication layer uses only numpy, never imports torch or mlx
Security
Security is on by default. The first macfleet join auto-generates a
fleet token at ~/.macfleet/token (mode 0600). See the
security reference for the full threat
model.
Short version:
- Fleet isolation — nodes with different tokens can't see each other on the network (mDNS service type is scoped by fleet hash)
- Mutual authentication — HMAC-SHA256 challenge-response on every connection, plus signed hardware profile exchange (v2.2)
- Encryption — TLS mandatory whenever auth is enabled
- Rate limiting — 5 failed auth attempts per IP → 5-minute ban, exponential backoff in between (heartbeat read timeout tightened to 1s to stop slowloris)
- No cloudpickle over the wire —
@macfleet.taskroutes registered callables by name, not by pickled closures
CLI
macfleet join Join the pool (auto-discovers peers)
macfleet pair Read a pairing URL from pasteboard / stdin
macfleet status Show pool members and network info
macfleet info Show local hardware profile
macfleet train Run training (demo or custom script)
macfleet bench Benchmark compute, network, or allreduce
macfleet doctor System health check
macfleet quickstart Write a starter training script
How it works
MacFleet uses data parallelism: every Mac holds a full copy of the model, trains on a weighted portion of the data, and averages gradients via Ring AllReduce after each step.
The compression layer (TopK + FP16) is applied locally before the allreduce; v2.2 transmits dense gradients on the wire (sparse allreduce is on the v2.3 roadmap as Issue 3). The bandwidth savings table below describes the target ratios once sparse-on-wire ships:
| Network | Compression | 100 MB gradients (v2.3 target) |
|---|---|---|
| Thunderbolt 4 | None | 100 MB |
| Ethernet | TopK 10% + FP16 | ~5 MB |
| WiFi | TopK 1% + FP16 | ~500 KB |
Requirements
- macOS 14+ with Apple Silicon (M1/M2/M3/M4)
- Python 3.11+
- PyTorch 2.1+ or MLX 0.5+ (optional, pick your engine)
Documentation
Full docs: run mkdocs serve after pip install "macfleet[docs]", or
read the Markdown source in docs/:
Development
git clone https://github.com/vikranthreddimasu/MacFleet.git
cd MacFleet
pip install -e ".[dev,all]"
make test # 447 tests
make lint # ruff + mypy
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file macfleet-2.2.0.tar.gz.
File metadata
- Download URL: macfleet-2.2.0.tar.gz
- Upload date:
- Size: 117.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
be28802656ae56edd063c1b39eb76dd0ee730cbef2ed32cee70c30d10f1cdc67
|
|
| MD5 |
fdc6a3aea64ce1af107a4f3a7302b23b
|
|
| BLAKE2b-256 |
1546a1752f88e880e22a4c07199c5b06d9fda05336a46baa4ba49e69d0f3294c
|
Provenance
The following attestation bundles were made for macfleet-2.2.0.tar.gz:
Publisher:
release.yml on vikranthreddimasu/MacFleet
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
macfleet-2.2.0.tar.gz -
Subject digest:
be28802656ae56edd063c1b39eb76dd0ee730cbef2ed32cee70c30d10f1cdc67 - Sigstore transparency entry: 1424500924
- Sigstore integration time:
-
Permalink:
vikranthreddimasu/MacFleet@d0f7e489d950443a78adaa79a0bb3449d0ab2708 -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/vikranthreddimasu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d0f7e489d950443a78adaa79a0bb3449d0ab2708 -
Trigger Event:
push
-
Statement type:
File details
Details for the file macfleet-2.2.0-py3-none-any.whl.
File metadata
- Download URL: macfleet-2.2.0-py3-none-any.whl
- Upload date:
- Size: 136.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5ffef8d911072d612a1db77895955d1a7b31cf016dc64f8df75c34b825ffc32
|
|
| MD5 |
1271d15999b2200ec2894da35e36b728
|
|
| BLAKE2b-256 |
5df6e9099195b648924cd6916b7f76521665e4cc931e27c817cdd4ec89b49bae
|
Provenance
The following attestation bundles were made for macfleet-2.2.0-py3-none-any.whl:
Publisher:
release.yml on vikranthreddimasu/MacFleet
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
macfleet-2.2.0-py3-none-any.whl -
Subject digest:
c5ffef8d911072d612a1db77895955d1a7b31cf016dc64f8df75c34b825ffc32 - Sigstore transparency entry: 1424501005
- Sigstore integration time:
-
Permalink:
vikranthreddimasu/MacFleet@d0f7e489d950443a78adaa79a0bb3449d0ab2708 -
Branch / Tag:
refs/tags/v2.2.0 - Owner: https://github.com/vikranthreddimasu
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d0f7e489d950443a78adaa79a0bb3449d0ab2708 -
Trigger Event:
push
-
Statement type: