MLX 実行中の Mac をカーネルパニックから守る。
MetalGuard は、Apple Silicon 上の MLX 向け GPU セーフティレイヤーです。MLX モデルを動かすと、Apple の IOGPUFamily GPU ドライバーにあるバグが引き起こされ、プロセスが単に終了するのではなく Mac 全体がカーネルパニックして再起動します。MetalGuard はそのバグを誘発する条件をカーネルに達する前に捕捉します。
pip install metal-guard · 依存ゼロ · macOS / Apple Silicon · MIT
現在のバージョン:v1.1.0 — リリース履歴は CHANGELOG.md を参照してください。
MLX モデルを動かしていたら Mac が突然再起動した。それはハードウェアの故障でも、あなたのミスでもありません — Apple の GPU ドライバーにある既知のバグです。対処法を最初から最後まで説明します:
1. Terminal を開く。 ⌘ + Space を押して Terminal と入力し、Enter を押します。
2. metal-guard をインストールする — 次の 1 行をコピーして Terminal に貼り付け、Enter を押します:
pip install metal-guard依存ゼロなので数秒でインストールでき、パッケージ不足エラーになることはありません。
3. 実行する — 次を入力して Enter を押します:
metal-guardmetal-guard は Mac が書き込んだパニックレポートを読み取り、何が起きたかを平易な言葉で説明し、再発防止のためのワンライン保護をインストールするかどうか尋ねます。y と答えてください。
以上です。 次に MLX モデルが Mac をパニックさせようとしたとき、metal-guard は説明を表示してそれを止めます。
pipがない?pipは Python に付属しています。pip install metal-guardで command not found と表示される場合は、まず python.org から Python をインストールして再試行してください。pipxも使えます:pipx install metal-guard。
- パニックを診断する。 macOS のパニックレポートを読み取り、どの Apple ドライバーバグが原因かを特定し、カーネルログを解読しなくても分かる平易な言葉で説明します。
- 次のパニックを防ぐ。 可逆的なシェルガードがリスクの高い MLX の実行をクールダウンチェックに通し、パニックを起こすことが知られているモデルはロード前にフラグを立てられます。
- ダメージを封じ込める。 MLX を隔離されたサブプロセスで実行し、バグを誘発するレースウィンドウを狭め、再起動後にパニックループへ直行することを拒否します。
- 邪魔をしない。 依存ゼロ、デフォルトは advisory モード、すべてのゲートにオフスイッチがあります。
MetalGuard は ワークアラウンドであり、根本的な修正ではありません — バグは Apple のドライバー内部にあり、修正できるのは Apple だけです。MetalGuard が行うのは、Mac を 「警告なしに再起動する」 状態から 「説明を表示して一時停止する」 状態へと変えることです。
Apple Silicon の Metal GPU ドライバーにはバグがあり、GPU メモリ管理が失敗したとき、プロセスをきれいに終了する代わりに カーネルがマシン全体をパニックさせます。
panic(cpu 4 caller 0xfffffe0032a550f8):
"completeMemory() prepare count underflow" @IOGPUMemory.cpp:492
MLX モデルをシーケンシャルにロード・アンロードするワークフローはすべてこれを踏む可能性があります — ドライバー内部の参照カウントがアンダーフローしてマシンが再起動します。あなたのコードのせいではありません。 ドライバーレベルのバグで、修正の見通しもありません。ml-explore/mlx-lm#883 を参照してください。
| ワークロード | リスク | 理由 |
|---|---|---|
| 単一モデルサーバー(LM Studio) | 低 | 1 つのモデルのみ、切り替えなし |
| マルチモデルパイプライン | 高 | load/unload の遷移ごとに panic の可能性 |
長時間稼働サーバー(mlx_lm.server) |
高 | KV cache が無制限に膨張、Metal バッファが蓄積 |
| エージェントフレームワーク + tool calling | 高 | 会話ごとに 50〜100 回の短い generate() |
| 24/7 daemon | 重大 | 日をまたいでメモリドリフト、自然なクリーンアップ地点がない |
これらのエラー文字列を検索してここに来ましたか?あなたは正しい場所にいます。
MLX の実行中に Mac が panic / 再起動しており、以下のいずれかを検索した方のために MetalGuard は作られました:
IOGPUMemory.cpp:492 completeMemory() prepare count underflow · IOGPUMemory.cpp:550 kernel panic · kIOGPUCommandBufferCallbackErrorOutOfMemory · mlx::core::gpu::check_error → std::terminate → abort (SIGABRT) · mlx::core::metal::GPUMemoryAllocator / fPendingMemorySet · IOGPUGroupMemory.cpp:219 pending memory set panic · IOGPUGroupMemory::remove_memory_object memory object not found · mlx_lm.generate crashes mid-inference · mlx_lm.server OOM kernel panic / Mac reboot · com.apple.iokit.IOGPUFamily in a panic report · AGX_RELAX_CDM_CTXSTORE_TIMEOUT · GPU watchdog killing MLX on MacBook · M1 / M2 / M3 / M4 (Max / Ultra / Pro) kernel panic · long-context (≥ 65k) prefill triggers reboot · back-to-back MLX model loads cause IOGPU underflow panic.
pip install metal-guardこれで metal-guard と mlx-safe-python のコマンドラインツールが手に入ります。他の Python パッケージと隔離したい場合は pipx を使ってください:pipx install metal-guard。
pip install metal-guard で metal_guard Python パッケージもインストールされます:
import metal_guard as mg
verdict = mg.evaluate_panic_cooldown()
print(verdict.exit_code, verdict.reason)git clone https://github.com/Harperbot/metal-guard.git
cd metal-guard
pip install -e ".[test]"
pytest -q$ metal-guard panic-gate
🟢 PROCEED no recent IOGPU panics
24h=0 72h=0
$ metal-guard status
metal-guard 1.1.0 🟢 OK
mode defensive — defensive mode (default)
panics 0 in last 72hインストール後に metal-guard が見つからない場合、pip --user の bin ディレクトリが PATH に含まれていない可能性があります — python3 -m metal_guard_cli panic-gate がフォールバックとして使えます。
| コマンド | 機能 |
|---|---|
metal-guard |
初回ウィザード:最近のパニックをスキャンし説明し、保護を提案する |
metal-guard diagnose |
最近のカーネルパニックをスキャンして説明する(変更なし) |
metal-guard guard install |
可逆的なシェルガードをインストールする(下記参照) |
metal-guard guard uninstall / status |
シェルガードを削除 / 状態を報告する |
metal-guard panic-gate |
クールダウン判定 — launchd / CI スクリプト向け |
metal-guard status |
フルステータススナップショット |
metal-guard postmortem <dir> |
panic 後の診断バンドルを収集する |
metal-guard guard install はシェルの rc ファイル(~/.zshrc または ~/.bashrc)に区切り付きのブロックを 1 つ追加し、対話シェルの python / python3 を mlx-safe-python 経由にします。パニッククールダウンが有効な間は MLX の実行が自動的に一時停止され、そうでなければそのまま通過します。完全に可逆です — metal-guard guard uninstall でブロックをきれいに削除できます — また対話ターミナル(Terminal、iTerm、VS Code)のみに適用され、launchd ジョブやスクリプトには影響しません。アンインストールせず無効にするには:export METALGUARD_SHELL_GUARD_DISABLED=1。
from metal_guard import metal_guard, require_cadence_clear, CircuitBreaker
# 連続ロードを拒否し、panic クラスター後の新規 worker も拒否する
require_cadence_clear("mlx-community/gemma-4-26b-a4b-it-4bit")
CircuitBreaker().check()
# GPU バウンドなスレッドを登録してクリーンアップが完了を待てるようにする
metal_guard.register_thread(thread)
metal_guard.wait_for_threads()
# 安全なアンロード、OOM 保護付き推論、ロード前のヘッドルームチェック
metal_guard.safe_cleanup() # gc + flush GPU + cooldown
result = metal_guard.oom_protected(generate, model, tokenizer, prompt=p)
metal_guard.ensure_headroom(model_name="my-model-8bit")ハードウェア対応のデフォルトを 1 行で:
config = MetalGuard.recommended_config()
metal_guard.start_watchdog(warn_pct=config["watchdog_warn_pct"],
critical_pct=config["watchdog_critical_pct"])すべての API は下記のリファレンスに一覧されています。
MLX ベースのアプリ、サーバー、バックエンドを配布している場合、metal-guard を組み込むと、ユーザーは 自分で何もインストール・設定しなくても カーネルパニックから保護されます — 安全ツールを自力で見つけることのないユーザーに届く、最も確実な方法です。
1. 依存として追加する。 metal-guard はサードパーティのランタイム依存を一切持たないため、追加しても依存の衝突やビルドの破壊は起きません:
# pyproject.toml
dependencies = ["metal-guard>=1.1,<2"]2. パニックしやすい遷移を守る。 上記の API でモデルのロード、アンロード、連続推論を囲みます — 最低でも、ロード前に require_cadence_clear()、アンロード後に metal_guard.safe_cleanup() を呼びます。
3. 大声で壊れず、安全に失敗する。 metal-guard のゲートはパニックでマシンを再起動させる代わりに型付き例外(例:SpawnRefused、MLXLockConflict)を送出します — それを捕捉して、API モデルへのフォールバックなど、優雅に縮退してください。
4.(任意)ユーザーにパニックを説明する。 再起動後、metal_guard.parse_panic_reports() を呼び、CLI と同じ平易な説明をユーザーに表示できます — 原因不明のクラッシュを、理解され処理されたイベントへと変えられます。
metal-guard はセマンティックバージョニングに従います。互換範囲を固定してください。
Apple Silicon Mac でカーネルパニックを引き起こす MLX モデルのコミュニティ共同リスト — ハードウェア文脈、根本原因の仮説、検証済みワークアラウンド付き。
Apple のドライバーバグには修正の見通しがありません。しかし どのモデルがどのワークロードでトリガーされるかはコミュニティが知り得ます — ただし現在は GitHub issue、LM Studio バグ報告、Discord スクリーンショット、誰も公開していない panic-full-*.panic ファイルに散在しています。MetalGuard はその知識のための構造化された置き場を提供します:
from metal_guard import check_known_panic_model, warn_if_known_panic_model
advisory = check_known_panic_model("mlx-community/gemma-4-31b-it-8bit")
if advisory is not None:
print(advisory["recommendation"])
# → "metal-guard narrows the race window but does NOT eliminate panic on
# this model. Switch backend (Ollama / llama.cpp) or pivot to an MoE variant."
warn_if_known_panic_model(model_id) # fire-and-forget, per-process dedup各エントリには panic_signature(一致させる正確な IOGPUMemory.cpp:NNN 行)、reproductions(ハードウェア / RAM / panic までの時間 / ワークロード)、community クロスリファレンス、実行可能な recommendation、upstream issue リンクが含まれます。
metal-guard が完全に有効な状態で特定のモデルで panic が発生した? あなたのデータポイントは価値があります — Known Panic Model report を開いてください。レジストリは意図的に保守的です:エントリには確認済みの再現または明確な upstream issue が必要なので、正常なモデルが誤って blacklist されることはありません。
レジストリは 既知の panic モデルを記録しています — まだ誰も報告していないモデルは記録できませんし、各エントリはある時点までの観測を反映しています。レジストリにモデルが載っていないことは安全証明ではありません — 単にここで報告されていないというだけです。リストにないローカルモデルを動かしたい場合は、まず自分のハードウェアとワークロードでテストしてください。パニックした場合は 報告してください。
panic の状況は逆方向にも変動します。root バグは upstream にあり、upstream は静止していません — 最近の MLX リリースにはすでに mitigation(例:mlx#3348、スレッドローカルな CommandEncoder)がマージされており、将来の MLX または macOS リリースでバグが完全に修正される可能性もあります。その際、レジストリエントリの「バックエンドを切り替えて」というアドバイスは不要になります — metal-guard の check_version_advisories() と observer モード(METALGUARD_MODE=observer、修正済み MLX ランタイムがインストールされたあとに防御層を緩和する)がそれを追跡する手段です。レジストリとこれらのアドバイザリは 時点スナップショットであり、永続的な判断ではない と捉えてください — 実際に動かす MLX と macOS のバージョンに対して再確認してください。
MetalGuard は 防御レイヤー(L1〜L13) として構成されています — 多層防御のオニオン構造:L1〜L8 は実行中のレースウィンドウを狭め、L9 + L11 はカーネルレベルの abort 直前に短絡し、L10 + L12 は panic + 再起動後の回復を扱い、L13 はすべてを JSON スナップショットとして公開します。各レイヤーがいつ追加され、どの事例が動機だったかは CHANGELOG.md を参照してください。
Metal を触るスレッドを登録しておき、mx.clear_cache() を呼ぶ前に GPU 作業の完了を待てるようにします。
| API | 機能 |
|---|---|
metal_guard.register_thread(thread) |
GPU バウンドスレッドをレジストリに追加する |
metal_guard.wait_for_threads(timeout=None) -> int |
登録済みスレッドが終わるまでブロック;残存数を返す |
「メインスレッドが解放した buffer をワーカースレッドがまだ使っている」という元祖 panic 根因の競合を避ける、順序付きクリーンアップ。
| API | 機能 |
|---|---|
metal_guard.flush_gpu() |
mx.eval(sync) + mx.clear_cache() — wait_for_threads() の後でのみ安全 |
metal_guard.safe_cleanup() |
完全シーケンス:wait → gc.collect → flush → cooldown |
metal_guard.guarded_cleanup() |
終了時に safe_cleanup() を実行するコンテキストマネージャ |
kv_cache_clear_on_pressure(available_gb, growth_rate_gb_per_min) |
KV モニタ向けの既製 on_pressure コールバック |
生の C++ Metal OOM を、自動クリーンアップと任意のリトライ付きで catch 可能な Python 例外に変換します。
| API | 機能 |
|---|---|
metal_guard.oom_protected(fn, *args, max_retries=1, **kwargs) |
OOM catch → cleanup → retry で実行する |
metal_guard.oom_protected_context() |
コンテキストマネージャ版 |
metal_guard.is_metal_oom(exc) -> bool |
任意の例外を分類する |
MetalOOMError |
MemoryStats 付きの catch 可能な例外 |
収まらないロードを拒否し、HF model ID からモデルサイズを推定します。
| API | 機能 |
|---|---|
metal_guard.can_fit(model_size_gb, overhead_gb=2.0) -> bool |
例外を投げないチェック |
metal_guard.require_fit(model_size_gb, model_name, overhead_gb=2.0) |
クリーンアップしてもまだ入らなければ MemoryError を raise |
MetalGuard.estimate_model_size_from_name(name) (static) |
名前からパラメータ数 + 量子化を解析して GB 推定 |
mlx_lm.server、エージェントフレームワーク、24/7 daemon 向け。
| API | 機能 |
|---|---|
metal_guard.memory_stats() -> MemoryStats |
スナップショット(active / peak / limit / available / pct) |
metal_guard.is_pressure_high(threshold_pct=67.0) -> bool |
簡易圧力チェック |
metal_guard.ensure_headroom(model_name, threshold_pct=67.0) |
圧力が高ければクリーンアップ、そうでなければ no-op |
metal_guard.start_watchdog(interval_secs, warn_pct, critical_pct, on_critical) |
エスカレーション応答付きのドリフト watchdog |
metal_guard.start_kv_cache_monitor(interval_secs, headroom_gb, growth_rate_warn, on_pressure) |
KV 成長モニタ、OOM の前に発火 |
bench_scoped_load(model_id, ...) |
連続ベンチマーク用コンテキストマネージャ — 次のロード前にアンロードを保証 |
上流の mitigation を A/B テストするためにコード変更なしで defensive / observer を切り替え可能。
| API | 機能 |
|---|---|
current_mode() -> str |
"defensive"(デフォルト)または "observer" |
is_defensive() / is_observer() -> bool |
便利な判定述語 |
describe_mode() -> dict |
モード名、説明、環境変数 |
新しい multiprocessing 子プロセスで MLX を実行し、カーネルレベルの abort が親プロセスを殺せないようにします。
| API | 機能 |
|---|---|
MLXSubprocessRunner(model_id, ...) |
永続 worker サブプロセス、クラッシュ時は再生成 |
call_model_isolated(model_id, prompt, ...) |
単発ヘルパー:spawn → generate → シャットダウン |
shutdown_all_workers() |
終了時に追跡中の全 runner を強制停止 |
SubprocessCrashError / SubprocessTimeoutError |
呼び出し側向けの型付き失敗 |
SpawnRefused |
モデルの advisory tier が panic のとき runner 構築時に raise(上書き:METALGUARD_LOCAL_PANIC_MODEL_BLOCK_DISABLED=1) |
MLX_LOCK_PATH 下のファイルロックで、bench / server / pipeline が同一マシン上で同時に Metal を初期化しないようにします。
| API | 機能 |
|---|---|
acquire_mlx_lock(label, force=False) |
保有中なら MLXLockConflict を raise;force=True は保有者に SIGTERM + タイムアウト + cooldown |
release_mlx_lock() -> bool |
このプロセスが保有していれば解放 |
read_mlx_lock() -> dict | None |
ノンブロッキング検査;stale + zombie を自動修復 |
mlx_exclusive_lock(label) |
コンテキストマネージャ:enter で取得、exit で解放 |
前 8 レイヤーの後の最終防衛線 — SIGABRT レイヤーの 下にあったカーネルパニックへの対応として書かれました:Python が何かを目にする前にマシンはすでに再起動していました。唯一の対策は最初からトリガーを避けることです。
| API | 機能 |
|---|---|
CadenceGuard(path=None, *, min_interval_sec=180) |
永続化されたモデル別ロードタイムスタンプストア |
require_cadence_clear(model_id, *, min_interval_sec=180) |
アトミックな check + mark;最近のロードがあれば CadenceViolation を raise |
parse_panic_reports(directory=None, *, since_ts=None) |
macOS パニックレポートをスキャン(/Library/Logs/DiagnosticReports、/var/db/PanicReporter、~/Library/...;.panic + .ips)して分類 |
ingest_panics_jsonl(*, report_dir=None, jsonl_path=None) -> int |
~/.cache/metal-guard/panics.jsonl に重複排除して追記 |
CircuitBreaker(*, window_sec=3600, panic_threshold=2, cooldown_sec=3600) |
panic クラスター後に新規 worker を拒否 |
detect_panic_signature(text) -> (name, explanation) |
panic ログを分類:prepare_count_underflow / pending_memory_set / remove_memory_object / ctxstore_timeout / metal_oom |
カーネルパニック + 再起動後、launchd は約 14 分後に plist を自動 respawn します — そして次の MLX ワークロードがすぐに同じバグを再トリガーする可能性があります。L10 は macOS のパニックレポートを読み取り、階段状の cooldown を適用します(1 panic → 2h;24h 以内に ≥2 または 72h 以内に ≥3 → 明示的な ack が必要な lockout)。
| API | 機能 |
|---|---|
evaluate_panic_cooldown() -> CooldownVerdict |
stdlib のみの評価;verdict.exit_code ∈ {0=進行, 2=cooldown, ≥3=gate 故障} |
scan_recent_panics(hours=72.0) -> list[PanicRecord] |
AND パターン IOGPU panic スキャン |
ack_panic_lockout() |
アクティブな lockout を解除 |
metal-guard panic-gate / metal-guard ack |
launchd スクリプト向け CLI ラッパー |
環境変数:METALGUARD_PANIC_COOLDOWN_STAGE1_H / _LOCKOUT_24H_N / _LOCKOUT_72H_N / _LOCKOUT_MAX_H / _GATE_DISABLED=1。
パニック前シグナル:SUBPROC_PRE ブレッドクラムに対応する SUBPROC_POST が 90 秒後もない場合、Metal がスタックしている強い示唆です — カーネルより先に worker を kill します。
| API | 機能 |
|---|---|
scan_orphan_subproc_pre(threshold_sec=90.0) -> list[OrphanPre] |
ブレッドクラムテールの FIFO ペアリングによる PRE↔POST スキャン |
metal-guard orphan-scan [--threshold-sec N] |
CLI ラッパー |
panic + 再起動後、診断バンドルを 1 つのディレクトリに収集します:panic ファイル(上限あり)、ブレッドクラムログのテール、panics.jsonl 履歴、mx.metal 統計、index.md サマリ — そして L10 がパニックレポートのローテーション後も実行を遅延させるようにセンティネルクールダウンを書き込みます。
| API | 機能 |
|---|---|
run_postmortem(output_dir) -> dict |
フルオーケストレーション;パス + panic 数を返す |
metal-guard postmortem <output_dir> |
CLI ラッパー(kill-switch:METALGUARD_POSTMORTEM_DISABLED=1) |
metal_guard を直接 import すべきでないクロスプロセス消費者(メニューバーアプリ、ダッシュボード、ssh インスペクション)向けのバージョン管理 JSON スナップショット。
| API | 機能 |
|---|---|
get_status_snapshot(*, include_panics=True, breadcrumb_lines=20) -> dict |
メモリ / KV モニタ / panics / lock 保有者 / mode / L10 verdict を集約 |
write_status_snapshot(out_path=None) |
~/.cache/metal-guard/status.json へアトミック書き込み |
metal-guard status-write [--once | --interval 30] |
CLI / daemon ラッパー |
| API | 機能 |
|---|---|
MetalGuard.detect_hardware() -> dict (static) |
チップ、GPU メモリ、推奨ワーキングセット、tier、IOGPUFamily kext バージョン |
MetalGuard.recommended_config() -> dict (classmethod) |
検出されたハードウェアに対するすべてのレイヤーの安全デフォルト |
check_version_advisories(packages=None) -> list[dict] |
インストール済みの (mlx, mlx-lm, mlx-vlm, transformers) バージョンが既知のアドバイザリに該当すれば警告 |
install_upstream_defensive_patches(force=False) -> dict[str, bool] |
Idempotent、バージョンゲート付きの upstream 回帰に対する monkey-patch |
audit_wired_limit() -> dict |
危険な iogpu.wired_limit_mb オーバーライドをフラグ立て(mlx-lm#1047) |
read_gpu_driver_version() -> str | None |
IOGPUFamily kext バージョン(mlx#3186) |
| API | 機能 |
|---|---|
lookup_dims(model_id) / estimate_prefill_peak_alloc_gb(...) / require_prefill_fit(...) |
GQA 対応 prefill 上限 — 30 GB 単発確保 panic の前に拒否 |
recommend_chunk_size(...) / describe_prefill_plan(...) |
アドバイザリ的な prefill チャンク分割 |
KVGrowthTracker(...) |
リクエスト別累積 KV ガード — グローバルモニタが見逃す暴走リクエストを捕捉 |
detect_process_mode() -> ProcessMode |
"server" / "embedded" / "notebook" / "cli" / "subprocess_worker" |
format_panic_for_apple_feedback(forensics, ...) |
Apple Feedback Assistant にそのまま貼り付けられるレポート |
metal_guard.breadcrumb(msg) |
fsync 済みのブレッドクラムログに書き込む |
L9 のすべての成果物は ~/.cache/metal-guard/ 配下です:cadence.json(CadenceGuard)、panics.jsonl(panic アーカイブ)、breaker.json(CircuitBreaker)、status.json(L13 スナップショット)。ブレッドクラムログのデフォルトは logs/metal_breadcrumb.log;MetalGuard(breadcrumb_path=...) で上書き可能。
┌─────────────────────────────────────────────────┐
│ Your Application Code │
│ Agent loop / Server / Pipeline / Daemon │
└──────────────────┬──────────────────────────────┘
┌──────────────────▼──────────────────────────────┐
│ MetalGuard │
│ L9 Cadence + CircuitBreaker refuse bad loads │
│ L8 Process lock cross-process │
│ L7 Subprocess isolation panic-isolated │
│ L5 Watchdogs drift alerts │
│ L3 OOM recovery catch + retry │
│ L2 Safe cleanup gc + flush │
│ L1 Thread registry wait before free │
│ L10–L13 cooldown / postmortem / status │
└──────────────────┬──────────────────────────────┘
┌──────────────────▼──────────────────────────────┐
│ MLX + Metal Driver │
│ ⚠️ Driver bug: panics instead of OOM │
└─────────────────────────────────────────────────┘
すべての防御を有効にしても同じモデルで repeat panic が続く場合、レースウィンドウは userspace レイヤーで狭められる以上に広いです。投資対効果順に 2 つのエスケープハッチ:
- バックエンドを切り替える。 Ollama と
llama.cppは内部で Metal を使いますが、persistent-worker アーキテクチャなのでサブプロセス teardown の競合を丸ごと回避します。失うのは生スループット;得るのは「マシンを panic させない」こと。 - MoE モデルに pivot する。 Mixture-of-Experts 変種(例:
mlx-community/gemma-4-26b-a4b-it-4bit)は 1 回の forward あたり active パラメータが小さく、KV トレジェクトリも狭いです。コミュニティの報告は「同じエコシステム内で最も確実な回避策は MoE」で一致しています。
MetalGuard は両方と補完的です — CadenceGuard はモデルをホットスワップする限り依然として有効です。
経験で学んだ SOP の注意点。 torch、mlx、mlx_lm、mlx_vlm、sentence_transformers、transformers、diffusers、accelerate のいずれかを import するものは Metal バックエンドを初期化し、同じカーネルバグを踏む可能性があります — 対話的なバージョン確認コマンドでさえも。アクティブなクールダウン中は pip show <pkg> または python -c "import importlib.metadata as m; print(m.version('<pkg>'))"を使い;絶対に python -c "import <ml-package>; print(<ml-package>.__version__)" を実行しないでください。
root バグは Apple の IOGPUFamily kext(mlx#3186)内部にあり、Python からはパッチできません。MetalGuard が行うのは トリガー率の低減(既知のトリガー経路を回避)、爆発半径の封じ込め(サブプロセス隔離)、再起動後カスケードの防止(CircuitBreaker)です。パニックを排除するものではありません — 特に捕捉できない completion-handler abort(mlx#3390)は Python のシグナルハンドラが発火する前に起きます。あるプロダクションマシンでは L9 導入後 24 時間で約 1.4 panics/day からゼロになりましたが、それはリスク低減であり、排除ではありません。Apple が修正済みの kext を出荷するまで、これが Python サイドのレイヤーで達成できる上限です。
| Issue | 問題 | レイヤー |
|---|---|---|
| mlx#3186 | IOGPUFamily kernel panic(標準) | L1/L2/L8/L9 |
| mlx#3346 | fPendingMemorySet 第二シグネチャ |
detect_panic_signature + L9 |
| mlx#3348 | CommandEncoder thread-local(マージ済み) | アドバイザリゲートによる observer モード |
| mlx#3390 | 捕捉不能な completion-handler abort | L7 サブプロセス隔離 |
| mlx-lm#883 | KV cache 成長によるカーネルパニック | L1 thread + L2 safe cleanup |
| mlx-lm#854 | サーバー OOM クラッシュ | L3 oom_protected + L5 |
| mlx-lm#1047 | wired_limit と panic の相関 |
audit_wired_limit |
MIT