Laya MLX 效能研究
研究日期:2026-09-19。目標:Apple M3 Max,40 個 GPU 核心,128 GiB 統一記憶體,MLX/MLX Metal 0.32.2。這是對原生執行時、已安裝的 MLX 實現、官方文件和現有基準 JSON 的靜態審閱。本次研究沒有執行任何 GPU 基準或模型推理。本報告中下面提出的任何最佳化都沒有實測加速。
最初的實驗應該是整模型編譯和有代表性的批排程,然後是選擇性的量化矩陣乘法。它們處理的是佔主導的重複工作。針對區域性注意力的專用 kernel 對長輸入來說是一個可信的長期專案。精確裁剪最後決策頭層是可行的,但它對整模型的算術節省只有幾個百分點。在不改變 checkpoint 的前提下取得大幅改進,需要改進稠密主幹、消除真正冗餘的請求,或找出一個經實測的實現瓶頸;僅僅替換一個啟用函式或再開啟一個 attention 標誌不太可能夠用。
現有測量確立了哪些結論
下面這些是現有的端到端中位延遲,包含提示準備和結果格式化,帶同步的 GPU 完成、五次預熱和 50 次測量迭代。模型載入和下載不計入。基準允許 64 個問題的批;公開執行時的預設值是 16,所以 50 問題的結果不是預設 API 配置。
| Checkpoint / 精度 | 短 1 問題 | 短 10 問題 | 短 50 問題 | 長 1 問題 | 長 10 問題 |
|---|---|---|---|---|---|
| Laya MLX FP16 | 13.421 ms | 71.068 ms | 336.030 ms | 44.927 ms | 420.987 ms |
| Laya MLX FP32 | 15.954 ms | 98.820 ms | 450.712 ms | 61.331 ms | 534.242 ms |
| Laya stock Torch MPS FP32 | 24.918 ms | 95.265 ms | 497.856 ms | 65.581 ms | 586.594 ms |
| Multilingual MLX FP16 | 7.390 ms | 27.386 ms | 127.565 ms | 37.635 ms | 389.487 ms |
| Multilingual MLX FP32 | 7.988 ms | 32.337 ms | 151.387 ms | 47.208 ms | 451.331 ms |
| Multilingual stock Torch MPS FP32 | 19.349 ms | 43.158 ms | 194.171 ms | 52.939 ms | 534.492 ms |
來源:Laya FP16、Laya FP32、Laya MPS、multilingual FP16、multilingual FP32,以及 multilingual MPS。長輸入對 Laya 含 512 個 token,對 multilingual 含 1024 個;因此比較它們的長輸入延遲並不是在相同序列長度下比較。短輸入填充長度分別是 93 和 91。Torch 的比較必須保留 FP32 標籤:與 MLX FP16 相比時,它們把後端變化和精度變化合在了一起。
執行之間存在明顯的波動。例如,multilingual FP16 長 10 問題執行的 p50 是 389.487 ms、p95 是 462.319 ms、最大值是 619.663 ms。它短單問題的前向中位數是 8.023 ms,而獨立測得的端到端中位數是 7.390 ms。把這些中位數相減會得到一個荒謬的負預處理時間。當前檔案沒有隔離 tokenizer、Python 排程、單個 GPU kernel 或同步的開銷。它們確立了有用的基線,而不是 kernel 級的瓶頸診斷。
驗證報告 記錄了三個 checkpoint 在 FP32 和 FP16 下各 63/63 的 argmax 一致,以及每個變體 100 次有限、確定性的重複呼叫:共 378/378 個答案一致和 600 次重複呼叫。這是在一個小型固定樣本語料上的迴歸檢查,其中包含重複的問題。它們不是「未來的量化或架構改動會保持通用任務準確率」的證據。
為什麼稠密矩陣乘法值得優先
模型實現 對每一個填充過的 token 施加 QKV 和輸出投影、一個帶門控的編碼器 MLP,以及兩個常規的 Transformer 決策頭層。設 D 為隱藏維度,I 為編碼器中間維度,N 為編碼器層數,H 為決策頭層數。這些塊中每個 token 用到的矩陣權重數量是:
A = N * (4 * D^2 + 3 * D * I) + H * 12 * D^2
dense FLOPs per batch ~= 2 * B * L * A
dense attention FLOPs ~= 4 * B * (N + H) * L^2 * D
這些估計把乘法和加法分開計數,並排除歸一化、啟用、嵌入、評分、掩碼、記憶體搬運和 kernel 開銷。它們是一個算術模型,不是執行時剖面。
| Checkpoint 系列 | D / I / 編碼器層數 | Token 嵌入權重 | 主要的逐 token 矩陣權重 A | 編碼器全域性 / 區域性層 |
|---|---|---|---|---|
| Laya / typed decisions | 1024 / 2624 / 28 | 51,576,832 | 368,312,320 | 10 / 18 |
| Multilingual | 768 / 1152 / 22 | 196,608,000 | 124,452,864 | 8 / 14 |
multilingual checkpoint 約 3.22 億的總參數裡有 1.966 億是嵌入參數。推理時只收集選中的嵌入行;這不是一次完整的詞表投影。它主要的逐 token 矩陣工作量大約是英文模型的三分之一,儘管兩者的總參數量看起來接近得多。這與實測的短批延遲差距一致,儘管它並不能證明某個特定的硬體瓶頸。只量化嵌入主要會減小常駐權重的體積,對 multilingual 尤其如此;它不必改善推理延遲。
在當前稠密注意力路徑下,attention 乘積在 Laya 的 L=93 時約佔建模 FLOPs 的 1.5%,Laya 的 L=512 時佔 7.9%,multilingual 的 L=1024 時佔 23.3%。它們佔真即時間的比例可能大不相同。在投入自定義 Metal 工作之前,剖析器應當區分矩陣 kernel、注意力 kernel、逐元素 kernel、CPU 圖構造和空閒間隙。
按優先順序排列的實驗
| 優先順序 | 實驗 | 最佳目標 | 主要取捨 / 驗收條件 |
|---|---|---|---|
| P0 | 對一短一長兩個形狀做剖析;編譯模型或編碼器塊 | 單請求延遲和 Python 排程 | 在現有精度容差內保持輸出一致;單獨測量首次使用編譯 |
| P0 | 按實際 token 預算和長度分佈調優批處理 | 許多不同問題和混合長度流量 | 在 p95 延遲和記憶體預算約束下最佳化吞吐;把排隊計入 |
| P1 | 量化選定的主幹線性層,先 8-bit 後 4-bit | 權重流量,或許還有稠密推理 | 質量與校準門檻;實際的 M3 Max 速度可能倒退 |
| P1 | 快取共享的 state 分詞和穩定的問句模板 | 許多問題共享一個 state 或重複的評分細則 | 精確的 token 同一性;有界快取;把快取和未快取的結果分開 |
| P1 | 只計算最後一個頭層所需的輸出 | 每一個工作負載,尤其是更長的序列 | 精確的依賴裁剪;整模型算術節省不大 |
| P2 | 帶 tile 邊界的真正區域性視窗注意力 | 512/1024 token 工作負載 | 新 kernel 的複雜度;保留雙向視窗和填充語義 |
| P2 | 只在剖析支援的地方融合 residual/norm 或 GELU/gate | 小 kernel 開銷或啟用流量 | 現有的快速 kernel 已經覆蓋了其中大部分;保持精確的 GELU 語義 |
| 單獨的產品特性 | 對相同的 forward 輸入去重 | 確實重複問題的負載 | 報告唯一推理數和快取命中;不要把它當作通用的 kernel 加速來呈現 |
編譯完整的、被評估的推理路徑
Agent.forward() 目前構造陣列、呼叫 self.model 並求值結果。在模型或塊層級沒有外層的 mx.compile。固定形狀編譯可以減少 Python 圖構造並融合受支援的操作。MLX 記錄了形狀特化和顯式狀態捕獲;它也警告說,無形狀編譯無法安全地保留任意依賴形狀的 Python 操作。見官方編譯指南。
從載入、轉換並求值權重之後建立的已編譯可呼叫物件開始,使用常規的形狀特化。保留現有的未編譯可呼叫物件,用於一致性比較和 CPU 相容。對於一個凍結的推理模型,權重可以保持為該模型例項所捕獲;如果權重或模組結構改變,重建該可呼叫物件或顯式捕獲相關狀態。不要在替換 checkpoint 時複用一個已編譯閉包。
測試一個整模型包裝器;如果追蹤限制或編譯成本讓它不划算,就分別編譯編碼器塊和頭。當前程式碼把 x.shape 讀進 Python 整數、用顯式的批/長度值做 reshape、建立 arange(length) 掩碼,並用由形狀推匯出的行範圍索引標記。在不重新設計的情況下對這個完整圖應用 shapeless=True 是不安全的。把動態掩碼構造移到已編譯塊之外,並使用與形狀無關的展平/還原操作,可能使之後的無形狀變體成為可能;要在變化的 B、L 和標記數量上驗證它。
形狀桶可以限制重追蹤,但填充有計算成本。把 L=93 填充到 96 會增加約 3.2% 的逐 token 工作;填充到 128 會增加約 37.6%。比較精確形狀編譯與小的長度倍數,以及一組有界、來自工作負載的桶。把 (batch size, padded length, marker slots, dtype, device/model instance) 納入快取策略決策,並測量形狀頻繁變動下的冷編譯延遲和保留記憶體。
worker.py 裡獨立的 forward 基準直接呼叫 agent.model。如果只在 Agent.forward 里加入編譯,當前的 forward 基準會繞過它,而端到端基準會使用它。為了讓比較有意義,兩條路徑都必須顯式選擇同一個候選實現。在計時流程中保留 mx.eval 和 GPU 同步:只測量圖構造並不會測量推理。
按有用的 token 批處理,然後檢查矩陣排程
collate_items 把每個塊右側填充到它最長的序列;執行時按插入順序對問題分組。對異構流量,按準備後的長度排序或分桶,在問題數量上限之外再加一個 token 預算,並恢復原始的問題 ID 和輸出順序。只在能代表該服務的地方比較 1、2、4、8、16、32 和 64 的批。對線上請求,要把等待一個批的時間算進去;僅看離線的問題/秒會掩蓋不可接受的延遲。
當前的短 50 問題工作負載對 Laya 浪費約 8.9% 的填充 token,對 multilingual 浪費 5.8%。長基準行沒有填充浪費。因此,僅靠去填充或排序在這些固定樣本上的算術收益有限。要揭示生產收益,需要一種混合長度的分佈,比如許多短問題中夾一個長問題。移除填充必須保留逐樣本的 RoPE 位置、標記位置和注意力邊界;在沒有隔離掩碼的情況下把樣本拼進一個序列會改變模型。
對稠密 kernel,檢查實際的形狀和步長。QKV 已經是一次投影,編碼器 MLP 的兩個輸入分支已經共享一次投影。不加區分地拆分會增加 launch。只有在剖析器或 MLX 排程追蹤顯示有不理想的批 GEMM 時,才比較把連續的 [B,L,D] 輸入顯式展平成 [B*L,D];框架可能已經高效地展平了。僅憑原始碼審查不能成為「漏掉了一個 GEMM 最佳化」的理由。
不要在生產實現裡每一層之後插入同步。當前的執行時每個塊只求值一次。額外的等待可能消除 CPU/GPU 的重疊並掩蓋排程改進;層級的剖析應當是一次單獨的診斷執行。
量化:瞄準主幹並實現其儲存契約
已安裝的 MLX 0.32.2 量化層實現 提供 nn.quantize(..., class_predicate=...) 和 QuantizedLinear,經由 mx.quantized_matmul 做僅權重的矩陣乘法。分組仿射量化支援 8-bit 和 4-bit 實驗。從組大小 64 的編碼器線性層開始,把啟用、歸一化、型別嵌入、評分器和動作頭保留為 FP16。然後獨立地加入決策頭線性層,並可選地加入嵌入量化。測量每個變體;在高 token 數量下,僅權重 kernel 可能不如 FP16 GEMM。
當前的載入器和模型裡有具體的整合隱患:
Agent.__init__把每一個儲存的權重轉換為浮點 dtype,並在嚴格載入之前只例項化稠密模組。量化 checkpoint 需要描述所選模組、組大小、位寬和模式的後設資料;在載入前例項化匹配的量化模組並保留打包的整數權重。把打包權重轉換成浮點並不是合法的載入。- 動作頭的第一個線性層輸入寬度是
D+4,即 1028 或 772,不能被 32、64 或 128 的仿射組大小整除。因此一刀切的量化呼叫不合適。轉換前檢查每一個所選層的輸入寬度。 DecisionModel.__call__從self.act_head.layers[0].weight.dtype選擇動作頭的輸入 dtype。對量化層來說,那個權重會是打包的整數儲存,而不是所期望的啟用 dtype。最初排除動作頭可以避開這條路徑;之後要支援它需要一個顯式的啟用 dtype 契約。- 量化會改變 logits 和校準機率。現有小型 FP16 固定樣本的一致性不足以證明 4-bit 質量。使用留出的帶標籤 choice、score 和 noul 任務、多語言輸入、接近的決策、不同選項數量和升級例子。跟蹤 argmax 一致、任務準確率、評分誤差、機率漂移、校準和動作機率。飽和的動作輸出可能掩蓋巨大的動作 logit 變化。
對組大小 64、FP16 仿射 scale 和 offset 的情況,近似的矩陣儲存是每個參數 bits/8 + 4/64 位元組:8-bit 時 1.0625 位元組,4-bit 時 0.5625 位元組,對比 FP16 的 2 位元組。這些是量化矩陣的儲存估計,不含其他張量和打包開銷;它們不是加速估計。官方 quantize API 描述了組整除性和格式。
更新的低位格式應當針對實際的 M3 Max 後端來評估,而不是假定它會使用來自更晚 Apple 晶片的硬體。MLX 的 NAX 可用性檢查要求比所記錄的 applegpu_g15s 裝置更新的架構代。見 MLX 0.32.2 裝置檢查。
在輸入確實相同時複用 CPU 準備
build_sequence 為每一個問題分別把同一個 state 序列化、清洗和分詞。它還分別對每條指令和每個選項分詞。Rust tokenizer 已經被直接使用;替換 Transformers 分詞不是一個尚未做的最佳化。
每次 prepare 呼叫把 state 只序列化並清洗一次、編碼一次,再把它的 token ID 切片到每個問題可用的空間。當同一個評分細則跨 state 使用時,快取不可變的已準備問題字首,鍵要包含 tokenizer 身份/revision、問題型別、有序 criteria、指令序列化、特殊 token 清洗和 token 預算。有界快取在 tokenizer 或配置變化後不得複用結果。批次的 tokenizer 編碼是另一個實驗,前提是它的輸出與當前那一串獨立編碼完全一致。
不要把對新拼接的提示分詞當作「拼接獨立編碼片段」的替代:子詞邊界可能改變。逐位元組校驗輸入 ID、注意力掩碼、標記位置、qtypes、截斷行為、結構化 criteria、mask 字面量、空輸入和輸出對映。
對長基準來說,state 在截斷前把一句話重複了 200 次。避免 N 次重複的 state 編碼可能有助於 CPU 準備,但現有的端到端/前向計時差並沒有測量這項節省。分別對 prepare、collate/陣列構造、forward 和後處理做基準,然後用一個不重複的留出語料確認端到端結果。
解碼器 KV 快取不適用於這個編碼器。 它的第一層是全域性雙向注意力;state token 表示取決於問題、選項及其位置。在不同的問題之間複用 state 隱藏狀態或 K/V 會改變結果。分詞和完全相同的整輸入結果可以快取;任意的上下文編碼器狀態不能。
精確裁剪最終決策頭的輸出
在最後一個 HeadLayer 之後,只有 [CLS] token 和選項標記 token 會被用到。更早的頭層仍必須產生所有 token,因為最後一層讀取它們的 K/V。只在最後一層中:
- 歸一化所有輸入 token 並計算所有 K/V。
- 在
[CLS]和合法選項位置收集 Q,並把這些 query 跑在整個帶掩碼的 K/V 序列上。 - 只對這些選定位置施加輸出投影、殘差、第二次歸一化和前饋網路。
- 用選中的
[CLS]輸出給動作頭,用選中的標記輸出做評分;保留標記填充和原始順序。
第一版實現可以保留融合的完整 QKV 投影,之後再收集 Q。更激進的變體把它的權重拆成一個全長 KV 投影和一個選定 token 的 Q 投影。那會節省更多算術,但可能讓 GEMM 排程效率更低。重複的填充標記索引只有在被掩碼的結果保持不可見時才無害。1 選項、多選項和可變標記的情形需要顯式的保真檢查。由於更少的 query 可能選中不同的 SDPA kernel,數學等價並不意味著浮點結果逐位相同。
設 R = 1 + number of option slots,保留完整 QKV 會從最後一個頭層移除約 18 * B * (L-R) * D^2 的稠密 FLOPs 和 4 * B * L * (L-R) * D 的注意力 FLOPs。拆分 Q/KV 會把稠密係數從 18 變成 20。相對於上面的整模型算術估計,取 R=5 得到:
| Checkpoint / 長度 | 保留融合的完整 QKV | 也只計算選中的 Q |
|---|---|---|
| Laya, L=93 | 2.44% | 2.70% |
| Laya, L=512 | 2.60% | 2.86% |
| Typed decisions, L=1024 | 2.66% | 2.90% |
| Multilingual, L=93 | 4.03% | 4.47% |
| Multilingual, L=1024 | 4.22% | 4.58% |
這些是靜態的 FLOP 削減,不是預測的延遲削減。該技術從一個頭層移除了大部分工作,而不是從模型移除大部分工作。它有用,是因為它保留了依賴關係並能不改訓練地實現,而不是因為它承諾整模型速度的某個倍數。
只有在測量其貢獻之後,才構建真正的區域性注意力
所有編碼器注意力呼叫已經使用 mx.fast.scaled_dot_product_attention;RoPE 已經是 mx.fast.rope;nn.LayerNorm 呼叫快速歸一化原語。MLX 的注意力 API 接受布林掩碼並在 FP32 中做 softmax。當前的 head 維度是 64。MLX 0.32.2 Metal 排程 支援這種形狀配陣列掩碼,並且在推理時不會為它選擇未融合的兜底實現。沒有證據表明 Laya 的布林掩碼會停用融合注意力。 已安裝版本中可用的 force_fused=True 作為診斷斷言很有用,但不該在這裡被宣傳成一條新的快速路徑。
剩下的限制是結構化稀疏。該實現構造一個形狀為 [B,1,L,L] 的稠密區域性布林掩碼。在常規的 Metal 注意力 kernel 中,非因果迴圈遍歷完整的 KV tile 範圍;陣列掩碼在 QK 乘法之後作用於分數。它保留了區域性注意力語義,卻沒有利用區域性 tile 範圍。
一個精確的專用 kernel 可以把每個 query tile 限制在重疊的 K/V 視窗內、保持 FP32 softmax 累加,並避免一個稠密的 L×L 掩碼。正確的視窗是雙向且包含端點的:abs(query_position - key_position) <= 64。內部 query 能看到 129 個位置,儘管配置名是 local_attention=128。全注意力層和兩個決策頭層必須保持全域性。填充的 key 必須繼續被排除,未使用的填充 query 需要有定義的有限行為。
一個省力的原型可以把 query 塊與重疊的 K/V 切片分組,並用一個更小的精確掩碼呼叫現有的 SDPA。使用已經定位好的 RoPE Q/K,或顯式保留絕對偏移。優先使用成批的塊而不是大量 Python 呼叫,並考慮重複的 K/V 物化。這個原型在短長度下可能不如當前 kernel;在維護自定義 Metal 之前,它是一個正確性和盈虧平衡實驗。
移除所有被禁止的區域性注意力對所帶來的建模整模型 FLOPs 最大削減,對短輸入很小,對長輸入更有希望:
| Checkpoint / 長度 | 精確區域性稀疏帶來的理想總 FLOP 削減 |
|---|---|
| Laya, L=93 | 0.086% |
| Laya, L=512 | 3.61% |
| Typed decisions, L=1024 | 7.69% |
| Multilingual, L=93 | 0.147% |
| Multilingual, L=1024 | 11.92% |
這些估計對 L>r 使用 local_pairs = L*(2*r+1) - r*(r+1),取 r=64。它們包含所有稠密投影和兩個全注意力決策頭層。它們排除掩碼生成和記憶體流量。執行時收益可能高於或低於 FLOP 比例,因為注意力和 GEMM 的效率不同;只有剖析才能確定。在 8192 token 時權衡會不同,但隨附的 agent 把輸入限制在 512 或 1024,所以一個 8192 token 的說法需要一個單獨支援的工作負載。
編譯之外的融合
已安裝的精確 nn.gelu 已經用無形狀編譯裝飾,nn.Linear 已經在合適時使用帶偏置感知的 addmm。整塊編譯仍可能把 GELU 與它的門控乘法、殘差加法、型別轉換、掩碼和小型評分特徵操作融合。在實現等價的專用 kernel 之前,檢查已編譯的 kernel 圖。
如果啟用流量仍然顯著,原型化精確的 GELU-and-gate 或 residual-and-LayerNorm 融合。保留當前精確的基於 erf 的 GELU;tanh 或 sigmoid 近似會改變模型,需要單獨的質量測量。在添加布局轉換之前檢查實際的 Q/K/V 步長和複製:MLX 的全注意力實現接受一個連續 head 維度配其他步長,並寫出便於合併 head 的輸出佈局。無條件的連續複製可能增加工作。
標記 softmax、top-two 排序、熵、小型動作頭和 NumPy 結果格式化只有在實測過之後才是合理的後續目標。與數百次全寬 Transformer 操作相比,選項位置很少,所以先最佳化它們不太可能觸及佔主導的路徑。
在追求激進收益的同時保護基準的含義
當前的工作負載生成器 迴圈使用三個問題定義來構造 5、10 或 50 個問題。那些批裡至多隻有三個唯一的模型輸入。逐呼叫的精確去重可以在真實應用裡避免冗餘推理,但它會不成比例地改善這些固定樣本。把這項特性與 kernel 最佳化分開,並報告 questions、unique_forward_inputs、快取命中和實際求值的 token。用各自的標籤、有序 criteria 和校準後設資料重建每一個原始答案。保留一個含 50 個真正不同問題的套件和一個刻意重複輸入的套件。
不要在主推理基準裡使用跨呼叫結果快取:它會反覆呼叫完全相同的請求。任何快取實驗都要如實標註。tokenizer 快取基準應當同時包含重複評分細則的場景和全新輸入的場景。
對每個候選,使用這樣的實驗設計:
- 保持目標不變。 記錄源 revision/雜湊、模型 revision、dtype、編譯標誌、所選量化模組、token ID 或其雜湊、形狀、標記數量、批策略、預熱、同步和裝置。現有的
input_sha256雜湊的是 state/questions,而不是實際的 token 張量;它不能確立跨 tokenizer 的張量同一性。從同一個最終源 revision 重跑基線,因為歷史 JSON 的源雜湊不同。 - 分離工作負載類別。 受控的 kernel 比較用固定形狀;排程和編譯用真實的可變長度;吞吐用不同的問題;合法的 CPU 快取用重複的評分細則;去重用刻意重複的問題。包含長長度尾部區間和不同的選項數量。在每個後端比較內部保持源文本和截斷一致。
- 測量冷熱行為。 分別記錄模型載入和首次編譯。測量準備、圖構造、同步求值的前向、輸出轉換和端到端延遲,不要把獨立的中位數當作可加的。在單獨一次執行裡剖析 kernel,因為追蹤會擾動延遲。
- 一次只改一個最佳化。 用現有的迭代次數篩選,然後在交替的基線/候選塊裡重複入圍者,並收集足夠樣本以獲得可信的 p95,例如每個工作負載至少 200 個計時請求。只跑一個活動的 GPU 基準,保持一致的功耗/散熱條件,並保留原始樣本。要求改進大於實測的執行波動。
- 檢查正確性和穩定性。 在相同 dtype 下與 MLX 以及現有 FP32 參考比較;對排程和 CPU 準備的改動強制執行 token 同一性。測試 64、128 附近以及桶邊界處的長度;塊上限附近的批;單選項和多選項;多語言輸入;填充;以及編譯後的形狀變化。重複變化形狀的請求,在預熱後同時觀察活動記憶體和快取記憶體,並驗證每種配置內的結果有限且確定。
- 對近似改動施加更強的門檻。 量化、啟用近似、token 裁剪、提前退出和蒸餾需要小型迴歸固定樣本之外的留出任務與校準結果。改變訓練行為時要保留單獨的模型身份和基準標籤。更快的 multilingual checkpoint 或蒸餾模型是另一種模型,而不是同一個 Laya checkpoint 的加速。
對任何佔據端到端時間比例 f 並以因子 s 加速的實測熱點,用 Amdahl 上界 1 / (1 - f + f/s) 評估預期的總影響。f 要用實測的時間比例;上面的算術比例不能替代它。下一個具體的工程決策應當跟隨編譯/批處理消融和短對長的 kernel 剖析,而不是一個未經驗證的倍數。
文件與可復現性說明
文件查詢使用了規定的 Context7 工作流:一次 library MLX 解析,然後分別對編譯和快速注意力做官方文件查詢,使用 /websites/ml-explore_github_io_mlx_build_html(共三條命令)。檢查了已安裝的 .pyi 和 Python 原始碼以核實 MLX 0.32.2 的行為,包括 force_fused、量化 API、已編譯的 GELU 和快速 LayerNorm。閱讀了鎖定版本的上下游 C++/Metal 原始碼以瞭解排程和 tile 迴圈細節。本次研究沒有升級任何庫。
用於詳細觀察的兩個 FP16 基線檔案在檢查時的 SHA-256 摘要如下:
laya-mlx-float16.json
63146dd664d039dde1a728b17aad896e491bd01ea36ea0786953691180e55b09
laya-multilingual-mlx-float16.json
9af74bd5a11e4edc15e6a8c9dc929a7b9fd2d19cb06f348cd0e04a076f912473
在本研究進行期間,主基準程序仍在產生額外的工件。表格刻意引用審閱時已經可用的完整基線檔案,並且不對未測量的候選實現作任何聲稱。