Apple Silicon 向けオンデバイス推論の最適化

プリフィルおよびデコードのスループットを向上させるカスタムローカルエンジン。

著者Perplexity Engineering

Appleシリコン上のハイブリッド・コンピュートは、クラウド内のフロンティアインテリジェンスとMac上のローカルモデルの間でタスクを調整します。クラウドモデルは調査と推論を処理し、ローカルモデルはMac上のプライベートファイルやアプリを処理します。

この労働分担をシームレスに感じさせるためには、ローカル推論が残りのタスクに遅れずについていく必要があります。そのためには、プロンプトを素早く処理し、高いトークン生成率を維持できるエンジンが必要です。

当社の軽量なローカル推論エンジンである Lily は、Apple シリコンおよび Qwen3.6-35B-A3B 専用に構築されており、プリフィルとデコードに対してそれぞれ個別の最適化が施されています。スタンドアロンのデモが GitHub で一般公開されています。

はじめに

MacでLLMを実行する一般的な方法として、Appleシリコン向けのAppleのオープンソース機械学習フレームワークであるMLXを使用するものがあります。その付随ライブラリであるMLX-LMには、幅広い言語モデルでテキストをロードして生成するために必要なコンポーネントが追加されています。MLXとMLX-LMを合わせることで、ローカルLLM推論のためのすぐに使える汎用スタックが提供されます。

Qwen3.6-35B-A3Bはスパースなハイブリッドモデルであり、Mixture-of-Experts(MoE)ルーティングを使用し、固定サイズのリカレント状態とフルアテンションを組み合わせています。これらのアーキテクチャの選択により必要な計算量は削減されますが、同時に不規則なワークロードも発生します。トークンは異なるエキスパートの重みにルーティングされ、リカレント状態の本質はシーケンシャルです。

MLX-LMはすでに推論フェーズや一般的なワークロードの形状に対して最適化されたカーネルを選択していますが、その再利用可能な演算は多くのモデルアーキテクチャをサポートする必要があります。Qwen専用のエンジンであれば、モデルおよびランタイムレベルで特化することができ、モデルの固定構造に合わせてカーネル、データ移動、およびスケジューリングを調整できます。

Lilyはこの特化を単一のプロセスでエンドツーエンドで実装しています。Rustランタイムがモデルチェックポイントをロードし、セッション状態と生成ループを管理し、OpenAI互換のチャット補完APIがリクエストを受け入れてトークンをストリーミングし、カスタムMetalカーネルがQwen固有の操作を実行します。実行パスにPyTorchもMLXも存在しません。

2つの推論スタックにおける汎用性と特化性の位置づけ。MLX-LMはモデルを合成可能なMLX配列演算として記述し、MLXは再利用可能なカーネルを通じてそれをスケジュールします。一方、Lilyはモデル構造、フェーズ固有の実行プラン、およびカーネル選択を、QwenとAppleシリコンを中心に構築された単一のRustランタイムに配置します。

プリフィルとデコードのパフォーマンスは個別に測定されます。プリフィルスループットはエンジンがプロンプトを処理する速度を捉え、デコードスループットは出力トークンを生成する速度を捉えます。

40コアGPUと128 GBの統合メモリを搭載したM5 MaxのMacBook Pro 1台で、Qwen3.6-35B-A3Bをベンチマークしました。256トークンから128Kトークン(K = 1,024)まで、prefill用に10種類のプロンプト長、decode用に10種類のコンテキスト長で評価した結果、このエンジンはMLX-LMと比べて、prefillスループットで平均1.22倍、decodeスループットで平均1.32倍を記録しました。4Kトークンのプロンプトと4Kトークンのdecodeコンテキストでは、カスタムエンジンは1秒あたり5,749.9 prefillトークン、186.6 decodeトークンに達し、MLX-LMの4,737.5および140.9を上回りました。マルチターンのセッションでは、これらの時間短縮はモデル呼び出しを重ねるたびに積み上がります。

256トークンから128Kトークンまでの10個の同等重み付けの長さにわたる算術平均スループット。Lilyはprefillで平均4,135トークン/秒、MLX-LMは3,383で、1.22倍です。decodeではLilyが167.1トークン/秒、MLX-LMが126.9で、1.32倍です。Prefillはプロンプト長によって変化し、decodeはコンテキスト長によって変化します。

次に、QwenのアーキテクチャがAppleシリコン上でどのようにモデル固有の最適化の機会を生み出すかについて説明します。その後、結果として得られるプリフィルとデコードの変更点について順に説明します。また、MLX-LMとのエンドツーエンドの比較で締めくくる前に、追加の最適化の効果が頭打ちになる箇所についても取り上げます。

AppleシリコンにおけるQwen固有の最適化の機会

Qwenは3つの異なるワークロードの形状を作成します

Qwen3.6-35B-A3Bには350億個のパラメータが含まれていますが、各トークンに対してアクティブ化されるのは約30億個のみです。ルーターが256個のエキスパートサブネットワークをスコアリングして8個を選択し、すべてのトークンを処理する1つの共有エキスパートが並行して使用されます。このスパースMoE設計により計算量は削減されますが、エキスパートが受け取るトークンの数が異なり、各トークンが異なるエキスパートの組み合わせからの重みを必要とするため、不均一な作業が生じます。

また、Qwenは10個のフルアテンション層と30個のGated DeltaNet層を組み合わせています。これら2つの層のタイプは、異なる方法で以前の情報を保持します。

アテンション層はグループ化クエリ・アテンション(GQA)を使用します。Qwenには16個のクエリヘッドと2個のキー・バリュー(KV)ヘッドがあり、8個のクエリヘッドが各KVヘッドを共有しています。共有によりKVキャッシュが小さくなり、キャッシュされたデータをクエリヘッド間で再利用できるようになります。キャッシュには依然としてすべてのトークンの新しいキーと値が保存されるため、コンテキストが大きくなるにつれて各デコードステップでより多くのデータが読み取られます。

Gated DeltaNetは代わりに、以前の情報を固定サイズのリカレント状態に圧縮します。学習されたゲートが既存の状態をどれだけ保持するかを制御し、デルタ更新が現在のトークンからの情報を統合します。モデルはこれらの更新をリカレントに定義するため、各トークンは先行するトークンによって生成された状態に依存します。ただし、プリフィル中、エンジンは同じ計算を2つの方法で評価できます。状態を前方に伝播させながらトークンを直接スキャンするか、より多くの行列演算とトークンレベルの並列性を露出するブロックに更新を再編成するかです。どちらのアプローチが高速かは、モデルの次元、ワークロード、およびハードウェアによって異なります。

これら構造が組み合わさることで、不均一なエキスパートグループ、増大するキャッシュに対するアテンション、直接またはブロック単位で評価可能な固定サイズのリカレンスという3つの計算パターンが生まれます。

Appleシリコンは、異なるワークロードに対して異なるパスを提供します

プリフィルは、多くのプロンプトトークンアクティベーション行を一度に処理します。ここで考慮されるローカルワークロードは通常、一度に1つのリクエストをデコードし(バッチ1)、ステップごとに1つの新しい行を処理します。この違いにより、同じモデルの重みがどのように使用されるかが変化します。プリフィルは、重みの各ブロックを何百または何千もの行にわたって再利用できます。デコードでは新しいトークンごとに重みを通過する別のパスが必要になるため、これは大部分において不可能です。

Appleシリコンは、CPUとGPUを、両方がアクセス可能な単一の物理メモリプールであるユニファイドメモリの背後に配置します。これにより、個別のGPUコピーを維持することなくモデルを常駐させることができますが、データ移動が無料になるわけではありません。重みと中間値の読み取りには依然としてメモリ帯域幅が消費されますが、レジスタやその他のオンチップストレージは高速ですがはるかに小規模です。

また、M5 GPUは異なる計算パスも提供します。プリフィルの線形層は一般行列-行列乗算(GEMM)を使用し、重み行列を一度に多くの行に適用します。互換性のあるGEMMは、Metal 4テンソル演算を通じて各GPUコア内のニューラルアクセラレータを使用できます。代わりに、バッチ1のデコードは一般行列-ベクトル乗算(GEMV)を使用し、同じ重みを1つの行に適用します。重みの再利用が少ないため、GEMVは主にメモリ帯域幅によって制限され、データ再利用率の高い行列演算向けに設計されたニューラルアクセラレータよりも、GPUのベクトル算術論理ユニット(ALU)に適しています。

これらの実行パスはLily固有のものではありません。MLXは同じユニファイドメモリ上で動作し、ワークロードの形状に応じて最適化された行列およびベクトルカーネルを選択します。MLX-LMのQwen実装はすでにエキスパートの作業をグループ化し、融合されたリカレントMetalカーネルでGated DeltaNetを評価し、GQA認識アテンションを使用しています。これらの機能は、Appleシリコン上で効率的なQwen推論を行うための共通の出発点となります。

最適化戦略

Lilyのより狭いスコープにより、Qwenの正確なアーキテクチャと次元に合わせて、これらの共有実行パスを調整できます。フェーズ固有のGPUパスを使用し、Qwenのエキスパート、リカレント、およびアテンションのワークロードをマッピングしてデータ移動を最小限に抑え、測定されたワークロードの形状からカーネルとレイアウトを選択します。この戦略には3つのパートがあります。

  1. GPUパスを推論フェーズに合わせる。プリフィルが多くの行にわたって重みを再利用できる場合は行列指向の実行を使用し、バッチ1のデコードが一度に1行を処理する場合はベクトル指向の実行を使用します。
  2. データ移動を最小限に抑えながら、Qwenの構造をGPUにマッピングする。重みが使用されるまで圧縮された状態を維持し、CPUに戻ることなくルーティングされたエキスパートの作業を整理し、リカレントスキャンを通じてGated DeltaNetの状態をオンチップに保持し、グループ化クエリ・アテンションによって共有されるKVデータを再利用します。
  3. カーネルをワークロードの形状に適応させる。各フェーズ内で、利用可能な行数、エキスパートへの行の分布、演算の次元、および現在のコンテキスト長から、タイルサイズ、実行レイアウト、およびアテンションパスを選択します。

以下のセクションでは、これらの選択について説明します。M5 Max上で一致するアブレーションにて評価された最適化については、研究中の最適化のみが異なる、それ以外は同一のエンジン構成を比較することでその効果を推定します。これらの実験ではエンジンのバージョン同士を比較するため、MLX-LMに対する最終結果の分解ではなく、メカニズムの説明が行われます。

プリフィル:重みの再利用とGPU上でのルーティングの維持

プリフィルは多くのトークン行を一度に露出しますが、Qwenはそれらの行をエキスパート間で不均一にルーティングし、シーケンスを通じてリカレント状態を更新します。その最適化は、ルーティングされた行を中心にスパースエキスパートの作業を整理すること、Gated DeltaNetのスキャンをオンチップに維持すること、長いプロンプトを境界のあるチャンクに分割することの3つのグループに分かれます。

Qwen層を通じた1つの境界のあるプリフィルチャンクの実行とデータの常駐。アテンションはKVキャッシュを拡張し、Gated DeltaNetはその作業用リカレント状態をレジスタ内に保持します。エキスパートルーティングのメタデータはGPU上に残り、Q4の重みはグループ化されたGEMM内で量子化解除されるまでパックされたままになり、一時的なアクティベーションは現在のチャンクに制限されます。

スパースエキスパートの計算を最適化する

行列乗算中に重みを量子化解除する

Qwen3.6-35B-A3Bチェックポイントは、グループ単位のアフィン4ビット量子化を使用します。各重みは4ビット整数コードとして保存され、64個の重みの各グループは、その値を再構築するために使用されるbfloat16のスケールとバイアスを共有します。これにより、350億パラメータのモデルが約70 GBのbfloat16の重みから19.4 GBのチェックポイントに削減され、モデルをMac内に常駐させることが実用的になります。

行列乗算に使用されるMetal 4テンソル演算は、パックされた4ビット表現ではなくbfloat16オペランドを消費します。乗算の前に、GPUはbfloat16で重みを再構築する必要があります。Lilyの最適化されたグループ化GEMMは、この変換を一度に1つの小さな重みタイルで実行し、ルーティングされたアクティベーション行と乗算するのに十分な時間だけ、結果をオンチップのスレッドグループメモリに保持します。累積には32ビット浮動小数点を使用し、出力はbfloat16で書き込まれます。完全に展開された重み配列がユニファイドメモリ内で作成されることはありません。

アブレーションでは、量子化解除は独立した操作として実行されます。4ビットの重みをユニファイドメモリ内のbfloat16配列に展開し、その後に行列カーネルがその配列を読み戻します。512トークンのプロンプトにおいて、量子化解除をグループ化されたGEMMに組み込むことで、この中間書き込みと読み取りが排除され、エンドツーエンドのプリフィルスループットが77.4%向上しました。

エキスパートルーティングをGPU上に維持する

グループ化されたGEMMでは、各エキスパートに割り当てられたアクティベーション行を一緒に保存する必要があります。トークンごとに8つのエキスパートを選択した後、ヒストグラムで各エキスパートに割り当てられた数がカウントされます。プレフィックススキャンによりそれらのカウントが開始オフセットに変換され、スキャッタースペップにより行がエキスパートグループに配置され、ブロックマップによりグループ化されたGEMMが処理する必要がある固定サイズの行列ブロックがリストされます。

最適化されたパスでは、プロンプトチャンクごとに、このシーケンス全体をGPU操作の順序付きバッチである単一のコマンドバッファに保持します。アブレーションでは代わりに一時停止して、CPUがルーティングの中間体を検査し、次の操作を送信できるようにします。ヒストグラムとプレフィックススキャンをGPU上に保持すると、2つのカーネルが追加されますが、各MoE層内のCPUとGPU間の同期が排除されます。

512トークンのプロンプトにおいて、GPU常駐ルーティングを有効にすることで、エンドツーエンドのプリフィルが89%増加しました。これは、カーネルの数だけでは誤解を招く可能性がある理由をも示しています。より高速なルートではより多くのカーネルが起動されますが、層内でCPUを待機することは決してありません。

タイルサイズをエキスパートの負荷に合わせる

2Kトークンのプロンプトにおいて、すべてのトークンを256個のエキスパートのうち8個にルーティングすると、16,384個のトークンとエキスパートの割り当て、つまりエキスパートあたり平均64個のアクティベーション行が生成されます。実際の分布は不均一です。多くの行を受け取るエキスパートもいれば、数行しか受け取らないエキスパートもいます。

グループ化されたGEMMは、各エキスパートの出力をタイルに分割します。タイルは、行列乗算の出力の小さな長方形のブロックです。各タイルは1つのGPUスレッドグループに割り当てられます。AppleシリコンのGPUでは、スレッドグループには1つ以上のsimdgroupが含まれており、それぞれが命令をロックステップで実行する32個のスレッドで構成されています。

タイルを大きくすると、セットアップコストがより多くの行に分散され、より多くの並列作業が露出されますが、エキスパートが少数の行しか受け取らない場合、大きなタイルの部分はアイドル状態のままになります。したがって、タイルサイズとsimdgroupの数は結合されています。

アブレーションではタイルを16行に固定します。そのコントロールに対して、4つのsimdgroupを持つ32行のタイルを有効にすると、2Kトークンでのエンドツーエンドのプリフィルが13.2%向上しました。

リカレント状態をオンチップに維持する

プリフィル中、各Gated DeltaNet層はリカレント状態を前方に伝播させながら、プロンプトを順番にスキャンします。レジスタ常駐が無効な場合、アブレーションではブロック単位のスキャンを使用します。2Kトークンのプロンプトでは、そのパスは層ごとに256 MiB(メビバイト)の状態を移動し、参加しているすべてのスレッドが互いを待機しなければならない同期ポイントであるバリアで、協力するスレッドを繰り返し停止させます。

リカレント状態は行列です。最適化されたカーネルは、各列を1つのsimdgroupに割り当てます。simdgroupはそのスレッド間で列を分割し、列をレジスタに1回ロードし、スキャン全体を通じて状態を維持します。スレッドは、スレッドグループ間で共有されるオンチップストレージであるスレッドグループメモリではなく、simdgroup演算を介して中間結果を交換します。完了した状態は、スキャン後にのみ書き戻されます。

小さな丸め誤差が連続的な更新を通じて蓄積されるため、状態とそのゲートには32ビット浮動小数点形式が使用されます。クエリとキーのアクティベーションはbfloat16のままです。

2Kトークンのプロンプトにおいて、レジスタ常駐スキャンを有効にすることで、エンドツーエンドのプリフィルが5.6%向上しました。エキスパートのGEMMはプリフィル時間の約90%を占めました。シーケンシャルスキャンでは、ニューラルアクセラレータの恩恵を受けるのに十分な再利用可能な行列作業が露出されません。

プロンプトのチャンク化によって一時メモリを制限する

ランタイムは、すべてのプロンプトトークンの一時データを一度にメモリ内に保持するのではなく、長いプロンプトを境界のあるチャンクのシーケンスとして処理します。モデルの重みはユニファイドメモリ内に常駐したままであり、リカレント状態とKVキャッシュが1つのチャンクから次のチャンクへとコンテキストを引き継ぎます。以前のコンテキストが破棄されることはありません。

チャンク化を行わない場合、一時的なアクティベーション配列はプロンプト全体とともに成長し、ユニファイドメモリを巡ってモデルの重み、リカレント状態、およびKVキャッシュと競合します。チャンク化により、一度にライブ状態になるのは1つのセグメントの一時的な値のみになり、次のセグメントを処理する前にそのストレージが解放または再利用されます。これによりピーク時のワーキングメモリが上限内に抑えられ、モデルの出力を変更することなく、エンジンがより長いプロンプトを処理できるようになります。

チャンク化されたプリフィルは多くのエンジンで一般的であり、これらのメモリ制約のある環境で長いマルチターントラジェクトリをサービングするために不可欠です。アテンション層の合計プリフィル時間はプロンプト長に対して二次関数のままであり、以前のチャンクの繰り返しKVロードによる追加のオーバーヘッドがいくらか発生します。

デコード:トークンあたりに移動するバイト数を最小化する

バッチ1のデコードは、一度に1つの新しい行を処理します。重みの再利用が少ないため、そのスループットは主にエンジンがトークンごとに移動するバイト数に依存します。デコードの変更点は、1行の重みパスの最適化、各ステップのGPU上の維持、中間および状態のトラフィックの削減、アテンションキャッシュの効率的な読み取りの4つのグループに分かれます。

バッチ1のデコードステップ1回あたりのデータフローと、アイドル時間およびキャッシュトラフィックを削減する2つのメカニズム。(A) GPUはQ4の重みとモデル状態をアテンション、Gated DeltaNet、ルーティング、および融合エキスパートカーネルを通じてストリーミングし、選択されたトークンを次のステップの入力スロットに直接書き込むと同時に、CPUにコピーを送信します。(B) 依存関係を認識したスケジューリングにより、独立したカーネルをオーバーラップさせることができます。(C) GQAパッキングにより、4つのクエリヘッドが各KV行のロードを共有できるようになり、8つの独立したリクエストが2つの共有ロードに削減されます。

1行の重みパスを最適化する

MLXはすでに1行の作業を特殊な行列-ベクトルカーネルにディスパッチしています。LilyはMLXを使用していないため、カスタムランタイムが同じ基本戦略を提供する必要があります。当社の行並列GEMVは、1つのアクティベーション行向けに設計されています。simdgroupは、重み行列の異なる部分を並列に読み取りながら、出力に関して協力します。

各デコードステップをGPU上に維持する

トークンのハンドオフをGPU上に維持する

各デコードステップは次のトークンを選択して終了し、次のステップはそのトークンを入力として開始します。選択をCPUに送信してからGPUに戻すと、すべてのトークンに同期ポイントが追加されます。私たちのランタイムは代わりに、2つのコマンドバッファと2つのGPU常駐トークンスロットを交互に使用します。GPUは最高スコアのトークンを選択し、そのトークンIDを次のデコードステップの入力スロットに直接書き込み、CPUは後続の作業を準備します。

独立したGPUの作業をオーバーラップさせる

記録されたバッチ1のデコードステップ1回において、トークンの生成により795個のGPUカーネルが起動されました。それらの依存関係は555個のシーケンシャルステージを形成し、一部のカーネルは同時に実行可能になりました。それにもかかわらず、Metalのシリアル実行モードはすべてのカーネルを順番に実行しました。

最適化されたデコードパスは、コンカレントなMetalパスで実際のデータの依存関係を記録します。GPUリソースが許す場合、独立したカーネル起動を同時に実行できます。バリアは、後続の作業で以前の結果が必要になる場合にのみ挿入されます。

中間および状態のトラフィックを削減する

別々のカーネルが中間体を具体化することがよくあります。1つのカーネルが一時的な結果をメモリに書き込み、次のカーネルがその結果を読み戻します。最適化されたデコードパスは、2つのエキスパート入力射影とゲート付きアクティベーション、エキスパート出力射影とルーティングスコアおよび共有エキスパートの結果、アテンション前のクエリとキーの準備、およびリカレント更新と正規化の4つのチェインを融合します。各融合カーネルは、一時的な値をメモリに送信する代わりにレジスタ内に保持します。

また、融合により依存関係グラフも短縮されます。中間書き込みがなくなると、そのコンシューマーを保護していたバリアもなくなります。

アテンションキャッシュを効率的に読み取る

アテンションキャッシュの読み取りをコアレスする

アテンションは、すべてのデコードステップ中にKVキャッシュからキーと値を読み取ります。アブレーションでは、隣接するGPUスレッドが必ずしも隣接するバイトを要求するとは限らないため、メモリシステムにより多くの個別トランザクションの処理が強要されます。コアレスロードを有効にすると、隣接するスレッドが隣接するバイトを要求するようになり、ハードウェアで読み取りを結合できるようになります。

bfloat16構成では、コアレッシングによりキーの帯域幅が33.8から47.9 GB/sに増加し、値の帯域幅が42.0から61.8 GB/sに増加し、3,840トークンのコンテキストでエンドツーエンドのデコードが2.1%向上しました。

クエリヘッドをパックしてKV行を再利用する

グループ化クエリ・アテンションにより、8つのクエリヘッドが1つのKVヘッドを共有できるようになります。アブレーションでは、各クエリヘッドが個別のsimdgroupで実行されるため、8つすべてが独立して同じキャッシュされたKV行を要求します。最適化されたカーネルは、4つのクエリヘッドを1つのスレッドグループにまとめ、各KV行を1回ロードして4つのアテンション計算全体で再利用します。2つ目のスレッドグループが残りの4つのヘッドを処理します。

GQAパッキングと呼ばれることが多いこのテクニックは、同じ算術を実行し同一の出力バイトを生成すると同時に、8つの独立したKVリクエストを2つの共有ロードに削減します。アンパックされたアブレーションと比較して、32Kトークンのコンテキストでエンドツーエンドのデコードスループットが23.8%向上しました。

長いコンテキストでアテンションレイアウトを切り替える

フルアテンション層におけるすべてのデコードステップは、既存のKVキャッシュをスキャンします。固定ブロックレイアウトにより、そのキャッシュはGPUが並列処理できる等しいピースに分割されます。キャッシュが小さい場合、追加のスケジューリングは価値を生みませんが、コンテキストが拡大するにつれて、固定ブロックレイアウトは作業をより均等に分散させます。

このモデルの場合、ランタイムは32Kトークン未満では通常のアテンションパスを維持し、32K以上では固定ブロックパスを使用します。この切り替えは、各ヘッドが256個の値を持ち、8つのクエリヘッドが1つのKVヘッドを共有する場合に適用されます。その他の形状は通常のアテンションパスのままです。アブレーションによりこの切り替えが無効化され、常に通常パスが使用されます。固定ブロックのルートを有効にすると、エンドツーエンドのデコードが32Kで7.7%、64Kで27.4%、128Kで40.2%向上しました。

さらなる最適化の限界

一部の変更により孤立した操作は改善されましたが、エンドツーエンドの推論の改善には至りませんでした。

推論的デコーディング(小型モデルを使用してフルモデルが検証するトークンを提案するもの)は、バッチ1のデコードを18%遅くしました。検証は2〜5行のグループを処理しましたが、これはこのハードウェアにとって非効率的な形状であり、行によって異なるエキスパートが選択されることが多く、読み取られるエキスパート重みデータの量が増加しました。ドラフターの出力語彙を削減するとドラフターのスループットが4.7〜5.1%向上しましたが、完全な推論的ループを高速化することはできませんでした。この結果はワークロード固有のものであり、Blackwell上のバッチ処理されたQwenデプロイメントでは、異なる条件下で推論的デコーディングが使用されています。

その他の実験には、GPUの起動回数の削減、フェーズ全体のオーバーラップ、より大きなプリフィルタイルの使用、より広範な融合の適用、ルーターの加速、出力射影とトークン選択の結合などが含まれていましたが、完全な推論ループの改善には至りませんでした。

ハードウェアの制限の測定では、メインのプリフィルおよびデコード操作における残りの余裕がほとんどないことも示されました。MoEのGEMMとGEMVは、そのアクセスパターンの最速の持続ウェイト読み取りレートの97.9%と90.3%に達しました。スパースGEMVから算術演算を除去してもスループットの変化はわずか0.2%であり、計算ではなくウェイトの読み取りが制限リソースであることを裏付けています。プリフィルの行列乗算も同様に、孤立した状態では理論上の行列制限の93%、テストされたモデル内では80〜86%に達しました。

エンドツーエンドのパフォーマンス

エンドツーエンドの比較では、両方のエンジンで同一の4ビットチェックポイントバイトをロードし、40コア、128 GBのM5 Max上で一度に1つのリクエストを実行します。各ラウンド内で、バックグラウンドロードやチップ温度の変化によるバイアスを軽減するため、2つのエンジンが交互の順序で実行されます。サーバーではなく、MLX-LMの最も高速な直接生成パスと比較しているため、測定はサービングのオーバーヘッドではなくモデルの実行に焦点を当てています。

このスイープは、256から128Kトークンまでの、プリフィルの10のプロンプト長とデコードの10のコンテキスト長をカバーしています。プリフィルスループットは、エンジンが固定のセットアップコストをより多くのトークンに分散させるにつれて、最初に上昇します。プリフィルは約4Kトークンのプロンプトでピークに達し、その後、プロンプトが大きくなるにつれて10個のフルアテンション層がより多くの作業を実行するため低下します。デコードは短いコンテキストではほぼフラットのままであり、増大するKVキャッシュの読み取りが重要になると低下します。カスタムエンジンは、記録されたすべての長さでより高速です。

特化された実行によって浮動小数点演算の順序が変更される可能性があるため、MLX-LMに対する数値の一貫性も確認しました。ティーチャーフォーシングによる比較では、192箇所のそれぞれで両方のエンジンが同じリファレンスプレフィックスから次のトークンを予測し、以前の違いが後続の入力に影響を与えるのを防ぎました。Lilyのパープレキシティはわずか0.04%高く、テストされた位置の96.35%で同じトップランクのトークンを選択しました。

Qwen3.6-35B-A3B Q4、batch 1、40コア・128 GBのM5 Max 1台における、プロンプト長によるprefillスループットとコンテキスト長によるdecodeスループット。256トークンから128Kトークンまでの10個の長さすべてで、Lilyは記録したすべての地点で高速でした。MLX-LMのprefillスループットの1.13〜1.50倍、decodeスループットの1.26〜1.34倍です。比較にはMLX-LMの最速の直接生成パスを使用しています。両方の横軸は対数スケールで、どちらの縦軸もゼロから始まりません。

ローカルプラットフォーム向けに構築

Appleシリコンは小規模なデータセンター用GPUではありません。独自のハードウェアおよびソフトウェアの特性を備えた完全なローカル推論プラットフォームです。ユニファイドメモリにより、単一のノードは、保持できるモデルと状態の量に関して非常に高い上限を持つことができます。M5ニューラルアクセラレータは、プリフィルにおける密な行列の作業を吸収します。ベクトルALUは、デコードにおける帯域幅バウンドで再利用率の低い残りの部分を処理します。

Qwenはさらなる特化の機会を追加します。エキスパートのルーティングとリカレント状態をGPU上に維持し、不要な中間体を排除し、独立した作業をオーバーラップさせ、共有KVデータを再利用し、カーネルをワークロードの形状に適応させます。

モデルおよびプラットフォーム固有の最適化により、1台のMacで大規模なスパースモデルを効率的に実行できます。今後の作業では、モデル、チップ、およびサービングワークロード全体でのカバレッジを拡大し、1つの構成でここで検証されたメカニズムをより一般的なランタイムポリシーへと発展させます。

より広範な原則は、エンジンの構造をモデルのアーキテクチャとハードウェア固有の計算・メモリパスの両方に合わせることです。最先端のオープンウェイトモデルとハードウェアが進化するにつれて、高性能なローカル推論は、それらの違いを抽象化するものではなく、両方に合わせて調整されたエンジンにますます依存するようになります。

引用

BibTeX
@online{perplexity2026OptimizingOnDeviceInferenceForAppleSilicon,
  author = {{Perplexity} and Yibo Wu and Lequn Chen and Kevin Hu and Phi Hoang and Claire Beamer and Jeremy Yang and Denis Yarats},
  title = {{Optimizing on-device inference for Apple Silicon}},
  date = {2026-09-01},
  url = {https://www.perplexity.ai/hub/blog/optimizing-on-device-inference-for-apple-silicon}
}