桌上已經有兩台 Mac,你想讓它們一起跑同一個大型語言模型(LLM),第一個問題往往是:「記憶體加起來,回答就會比較快嗎?」這篇 MLX 雙機教學,帶你把容量、通訊與等待時間分開驗收,學會比較單機、Pipeline 與 Tensor 三條路。
專為第一次接觸分散式推論、願意照著終端機操作的讀者寫。操作需要兩台你能管理的 Apple Silicon Mac、既有 Python 3.11 以上環境,以及可合法使用的本機模型。RDMA 路線另核對 Thunderbolt 5 與 macOS 26.2 以上。還沒備齊設備,也能先看懂分工,再準備自己的測試紀錄。
本文查核至 2026 年 10 月 18 日,指令以 MLX 0.32.4、MLX LM 0.32.2 原始碼為基準;AlphaLab 這次沒有可用的相容雙機環境,以下是文件導向的操作與驗收流程,速度觀察明確歸屬 Apple 的公開測試。
先說結論:兩台電腦,先決定怎麼分工
雙機推論=模型切分+跨機傳輸+同步等待。像兩位廚師一起做同一道菜:分工能讓工作桌變大,但每做一步都要交接,時間也會花在傳菜上。多一台機器,增加的是選擇;加速多少,要量。
- Pipeline「前後接力」:依層切開,適合先解決模型放置問題;一條回答的下一步仍要等前一步。
- Tensor「同層合做」:把每層的工作拆開,同時算、再交換結果;對低延遲通訊更敏感。
- 驗收「同一張考卷」:固定模型檔、精度、輸入長度、輸出長度和版本;另外量真實任務的正確率與完成時間。
MLX 雙機教學原理:Pipeline、Tensor 與 RDMA 分別管什麼?
MLX 是 Apple 的機器學習陣列框架;MLX LM 是用它載入、生成文字與提供服務的套件。Pipeline 與 Tensor 是「怎麼分工作」,JACCL、Ring 是「怎麼搬資料」。RDMA(遠端直接記憶體存取)則是跨機傳輸技術;本篇的 JACCL 路線使用 Thunderbolt RDMA。不要把分工方式與連線後端當成同一個旋鈕。
Pipeline 按模型深度切:甲先算前面的層,將中間結果交給乙算後面的層。長提示可以切成小塊,讓乙處理上一塊時,甲開始下一塊。Tensor 則按層內的矩陣運算切分,兩台一起做同一層的一部分,再合併。白話說,一個像接力,一個像每站都共同作業。

Apple 在 10 月 15 日的分散式推論文章中,使用 M5 Ultra Mac Studio、雙 Thunderbolt 連線,觀察到 Pipeline 的逐 token 生成速度接近單機;長輸入則可藉分塊重疊改善前處理。Tensor 的收益受模型與通訊影響。這些是 Apple 的特定配置結果,不能直接套成你的兩台設備會快幾倍。
①「先點名」:盤點設備、版本與模型檔
不確定兩台能不能合作?先做兩份相同的環境紀錄。各自執行下面指令;系統版本、晶片架構與實體記憶體分別記下。Thunderbolt 規格到「系統資訊 → Thunderbolt/USB4」與該機型技術規格核對;USB-C 接頭外形相同,不代表連線能力相同。
sw_vers -productVersion
uname -m
sysctl -n hw.memsize
python3 --version
以下共用工作路徑為 /Users/Shared/mlx-lab,只放測試檔,不放機密。兩台各自建立虛擬環境;Python 須為 3.11 以上,別用較舊的系統 Python 硬裝。這組版本可從 MLX 發布頁與 MLX LM 發布頁核對。
mkdir -p /Users/Shared/mlx-lab
python3 -m venv /Users/Shared/mlx-lab/.venv
source /Users/Shared/mlx-lab/.venv/bin/activate
python -m pip install "mlx==0.32.4" "mlx-lm==0.32.2"
python -m pip freeze > /Users/Shared/mlx-lab/environment.txt
mlx.launch --print-python
把兩份 environment.txt 比對,依賴版本也要一致。依 官方啟動指南,SSH 能連通之外,Python 與測試腳本須在各台相同路徑。先在系統設定開啟需要的「遠端登入」,以金鑰登入自己的兩台機器;第一次核對主機指紋。下文的 mac-a、mac-b 是你要換成實際 SSH 別名的範例。
兩台都在 /Users/Shared/mlx-lab/model 放入同一份完整、已可單機載入的 MLX checkpoint,包含權重、config 與 tokenizer;分散式載入自行切分,不是手動把檔案各分一半。起步可選 MLX 社群的 Qwen3.5-0.8B-4bit練接線;本文核對的 revision 為 da28692b5f139cb0ec58a356b437486b7dac7462。先讀模型卡與來源授權,它是文件核對的候選,並非本篇已通過雙機的成績單。這版 Qwen3.5 架構提供兩種切分實作;選別的模型時,要另核對。
還要確認模型目錄包含 model.safetensors.index.json;這版 分散式載入程式的 Pipeline 路徑會讀這份權重索引。本文候選的完整快照含此檔,下載時不要只抓一個 safetensors。
記錄模型來源 revision,並比對兩台檔案雜湊。只寫「Q4」不夠:同名量化也可能有不同檔案、轉換方式與 tokenizer。較大模型還要為 KV Cache(對話運算留下的索引)與暫存預留空間;先讀 本機模型記憶體規劃,別把實體記憶體總和當成可全數使用的模型空間。
②「先驗道路」:建立 Hostfile,再做最小通訊測試
RDMA 路線先讀 JACCL 官方設定:文件列出 macOS 26.2 起、Thunderbolt 5 的條件,並要求到 macOS 復原環境的終端機執行 rdma_ctl enable 後重開機。這一步要在每台實體機操作;回到正常系統,用 ibv_devices 檢查是否列出 RDMA 裝置。
保留 Ethernet 或 Wi-Fi 作為 SSH 管理線,再接 Thunderbolt。設定工具會調整 Thunderbolt Bridge 與點對點網路;先記錄原設定,不要在唯一的管理連線上盲改。下面不帶 --auto-setup,依工具列出的各主機專屬命令手動處理並確認,不為了省一步而開放免密碼 sudo。
mlx.distributed_config --verbose --hosts mac-a,mac-b --over thunderbolt --backend jaccl --output /Users/Shared/mlx-lab/hostfile.json
Hostfile 是「工作夥伴與路線的名冊」。JACCL 需要 ssh、rank 0 可達的 ips,以及描述每對主機連線裝置的 rdma 矩陣;讓工具依實際插孔產生,避免照抄別人的 rdma_en2。兩台直接互連就形成完整的兩點網格;多條線時,兩端裝置的配對順序也要一致。
若設備這次不走 RDMA,可另以 --backend ring --over ethernet 產生 Ring hostfile,先學通訊;之後啟動也要選 Ring。這是另一條後端路線,不能把它的成績填成 JACCL。第一輪只選一條路,把變因固定。
在兩台相同路徑儲存下列 /Users/Shared/mlx-lab/check.py。這是依 MLX 分散式 API 寫的小測試:強制使用 JACCL、確認世界大小是二,再把兩台各自的十個 1 相加。
import mlx.core as mx
world = mx.distributed.init(backend="jaccl")
assert world.size() == 2, f"Expected 2 ranks, got {world.size()}"
x = mx.distributed.all_sum(mx.ones(10))
mx.eval(x)
assert bool(mx.all(x == 2).item()), "Unexpected collective result"
print("rank", world.rank(), "size", world.size(), x)
mlx.launch --verbose --cwd /Users/Shared/mlx-lab --backend jaccl --hostfile /Users/Shared/mlx-lab/hostfile.json -- /Users/Shared/mlx-lab/.venv/bin/python /Users/Shared/mlx-lab/check.py
驗收條件是兩個不同 rank 都回報 size 2,十個值都是 2,並正常退出。這能驗基本通訊,還不是頻寬或模型效能測試。若只顯示一個程序,或一直停在初始化,先查 SSH、Python 路徑、rank 0 位址、線材配對和 RDMA 裝置;暫停載入大模型。Ring 練習則須把腳本與啟動命令的後端一起改為 ring。
③「只換分工」:MLX 雙機教學的三組對照
同一個模型,單機放得下,才有完整的速度對照。下面先以短輸入 512 tokens、生成 128 tokens、batch 1、prefill 每塊 512 tokens 做冒煙測試。三組都用同一路徑、同版本、同精度;這些數字是練習設定,沒有預填你的成績。
python -m mlx_lm.benchmark --model /Users/Shared/mlx-lab/model -p 512 -g 128 -b 1 -n 3 --prefill-step-size 512
mlx.launch --cwd /Users/Shared/mlx-lab --hostfile /Users/Shared/mlx-lab/hostfile.json --backend jaccl -- /Users/Shared/mlx-lab/.venv/bin/python -m mlx_lm.benchmark --model /Users/Shared/mlx-lab/model -p 512 -g 128 -b 1 -n 3 --prefill-step-size 512 --pipeline
mlx.launch --cwd /Users/Shared/mlx-lab --hostfile /Users/Shared/mlx-lab/hostfile.json --backend jaccl -- /Users/Shared/mlx-lab/.venv/bin/python -m mlx_lm.benchmark --model /Users/Shared/mlx-lab/model -p 512 -g 128 -b 1 -n 3 --prefill-step-size 512
第一段單機;第二段加 --pipeline;第三段在分散式下不加該旗標,走 Tensor。這個行為核對自 0.32.2 benchmark 原始碼。每段分開執行、保存完整終端輸出;先確認模型架構可用所選切分方式。程式報架構或切分錯誤,就記失敗,不換另一個模型冒充同模型比較。
小模型過關後,再把三組的 -p 一起改成 8192,--prefill-step-size 一起改成 8192;若容量允許,再一起改成 65536,prefill 塊仍固定 8192。這能看長輸入是否給 Pipeline 重疊工作的空間。模型無法單機載入時,單機欄填「此配置無法載入」,只比較兩個可跑的雙機配置,別製造相對單機加速倍率。
Apple 範例還使用 MLX_METAL_FAST_SYNCH=1;但查核日的 現行 MLX 文件警告快速同步可能導致死鎖與 GPU 卡住,建議保持未設定。本篇命令因此不啟用它;環境原本若有該變數,先在兩台測試 shell 移除。這也表示這輪設定與 Apple 跑分不同,數字要各自留帳。
④「分開計時」:首字、生成、記憶體與交付
Prefill 是先讀完提示;decode 是接著逐 token 生成;TTFT 是用戶端送出請求到第一個輸出 token 的等待。讀得快、吐字快、整件事做得快,是三張成績單。benchmark 以隨機 token 序列測運算,會先暖機;它適合比較負載,不是繁中理解或程式正確率考試。
這版 benchmark 列 prompt_tps、generation_tps、peak_memory 與各輪 total_time,沒有直接列用戶端 TTFT。用提示長度除以 prompt_tps 只能得到提示處理時間的近似,不能把它直接標成端到端首字延遲。峰值輸出也不要直接當成兩台總記憶體:這版主要由 rank 0 印出其 response 的 MLX 峰值,兩台的系統記憶體與 Swap 另外觀察。

每個配置留三輪原始數字及中位數,另外寫明暖機、失敗、換頁與是否重用提示快取。需要用戶端首字指標時,使用下一節的串流端點,以單調時鐘從送出計到第一個非空 delta.content;把它標成「首段可見文字時間」。若模型先輸出推理或工具呼叫,還要分開記,別把等待可見文字誤當純模型 TTFT。
⑤「真的交一件事」:接到本機 Coding Agent
先把獲選配置開成服務。以下是 Tensor;要試 Pipeline,就加 --pipeline。以 server 原始碼核對,這版支援分散式載入、--host 與 --port。把服務綁在 rank 0 的 loopback,只由同機測試用戶端存取,先不要改成對外監聽。
mlx.launch --cwd /Users/Shared/mlx-lab --hostfile /Users/Shared/mlx-lab/hostfile.json --backend jaccl -- /Users/Shared/mlx-lab/.venv/bin/python -m mlx_lm.server --model /Users/Shared/mlx-lab/model --host 127.0.0.1 --port 8080
服務會在前景持續執行。保持它運作,在 rank 0 另開第二個終端機查模型清單:
curl -fsS http://127.0.0.1:8080/v1/models
在第二個終端機,使用回傳的確切模型 ID 發送一個固定的繁中短題。下面用 default_model,是此版 server 對啟動模型的別名。串流標頭或角色事件可能早於文字出現,所以下面的命令只驗 API 連通與文字內容,不拿它代替模型首字成績。
curl -fsS http://127.0.0.1:8080/v1/chat/completions -H 'Content-Type: application/json' -d '{"model":"default_model","messages":[{"role":"user","content":"只輸出繁體中文:連線成功"}],"max_tokens":128,"temperature":0,"stream":true}'
要接 Coding Agent,可依 OpenCode 自訂 provider 文件在測試專案的 opencode.json 加入下列配置;已有設定先合併,不覆蓋其他 provider。以 mlx/default_model 選到這個端點,記下 OpenCode 版本;端點可聊天後,工具呼叫仍要單獨驗。
{
"$schema": "https://opencode.ai/config.json",
"model": "mlx/default_model",
"provider": {
"mlx": {
"npm": "@ai-sdk/openai-compatible",
"name": "Local MLX",
"options": {"baseURL": "http://127.0.0.1:8080/v1"},
"models": {"default_model": {"name": "Local test model"}}
}
}
}
測試任務用一個可丟棄副本:裡面只有 calc.py,其 add(a, b) 錯寫成 return a - b,以及本來已準備好的三個測試:add(2,3)==5、add(-1,1)==0、add(0,0)==0。要求 Agent:「只修 add,不改測試;執行測試後交出差異。」保留工具批准,限制可寫目錄,不接真實金鑰或部署工具。
從同一份乾淨副本開始,每組使用相同提示、模型、token 上限、工具與測試,記總秒數、測試通過、改動檔案與重試次數。小模型即使能聊天,也可能無法正確呼叫工具;這時先以 API 短題驗服務,把 Agent 欄記失敗,另選具工具能力的模型重開一整輪。想理解模型與執行層的分工,可先讀 Agent Harness 原理與 最小 Harness 實作。
常見坑:加機後變慢,先查哪裡?
- 通訊測試都沒過:回到 SSH、路徑、hostfile 與裝置配對;先讓兩個 rank 正常退出。
- Pipeline 只增加容量:看長輸入分塊是否重疊;單條短回答仍有前後相依,別期待每個 token 都同時完成。
- Tensor 較慢:先確認實際後端,再看小模型是否算太少、同步太多;一台較慢的設備也可能拖住每次會合。
- 某台 Swap 增加:降輸入長度、保留系統空間,再重跑全部對照;更換量化後須建立新實驗。
- Agent 快卻交錯答案:用測試、diff 與工具紀錄判分;tokens/秒只回答生成速度。
FAQ:八個新手問題
1. 兩台記憶體可以當成一整塊嗎?
要按切分配置算。權重、快取、暫存與系統占用分布在不同機器;總容量相加只是盤點起點。
2. USB-C 線插上就有 RDMA 嗎?
要核對整條鏈。機型、Thunderbolt 5、系統、復原環境啟用與裝置列舉都需過關。
3. Pipeline 一定讓生成更快嗎?
不一定。接力仍有先後關係;長輸入的分塊重疊與逐字生成要分開量。
4. Tensor 是不是任何模型都可用?
先核對架構實作。選用模型與量化必須能被該版切分載入;通訊成功只證明道路可通。
5. 為什麼先拿小模型練?
先縮小故障範圍。它能幫你驗環境與指令;小模型的加速比例不能代表巨型模型。
6. 單機裝不下,還能做比較嗎?
可以比較可跑的雙機配置。單機欄保留載入失敗,結論寫容量可行性與雙機差異。
7. benchmark 的 peak_memory 是整個叢集嗎?
這版不能直接如此解讀。另記每台 MLX/系統記憶體與 Swap,再說明聚合口徑。
8. 本機模型就等於 Agent 全程離線嗎?
要查完整資料流。工具仍可能搜尋、下載或連外;第一次用假資料、測試副本與有限工具。
給新手的三個重點
先驗道路,再搬模型;先固定考卷,再換分工;最後用正確交付決定值不值得留下雙機。容量、速度與品質各自過關,任何一項漂亮都不能代替其餘兩項。
接著閱讀
左右滑動查看更多推薦
下一步:先取得一張可信的雙機成績單
回到公式:模型切分+跨機傳輸+同步等待。今天先做最小通訊測試,然後保存同一小模型的三組輸出;等你能解釋每一欄,再換到真正需要的大模型。想把部署和驗收延伸成可交付專案,可到 AlphaLab 課程選下一個練習,或從 AI 專區繼續補足原理。
