原稿 mps-arxiv-v2.tex の内容 ・ 2026-09-21 時点(作業中)
大きすぎる計算は、
黙ってまちがえる。
Mac の GPU で PyTorch を使うとき、要素が 232(約 43 億)個を超える行列のかけ算は、エラーも警告も出さずに間違った答えを返す。この論文は、それが「いつ・どう」起きるかを測った記録。
1 ・ 何が起きるのか
43 億個を超えると、数え方が一周して 0 に戻る
0正しい
1正しい
…
65535正しい
655360 番の答え
655371 番の答え
車の距離計が 99999 の次に 00000 に戻るのと同じ。壁(232 要素)の先のデータは、先頭のデータから計算した値になる。
対象は torch.bmm(バッチ行列積)。matmul と、Transformer の標準的な(eager)attention もこれを通る。PyTorch 2.4.1〜2.14.0 の 11 版すべてで起きる。誤差は 100% を超える大きさで、丸め誤差ではない。
2 ・ いつ起きるのか
3 つの規則で、全部の結果を説明できる
① 出力が壁を超える+転置した入力順番に適用。これが最優先
全部まちがい(転置を無視して読む)
② 転置・切り出しの入力が 231 以上
エラーで止まる(これは安全)
③ ふつうの入力が壁を超える
壁の手前は正しい壁の先だけまちがい
乱数入力の 1376 件すべてが、この 3 つの規則どおりだった。
こわいのは「少し大きくしただけ」で変わること
B = 65535正しい
B = 65536エラーで止まる
B = 65537黙ってまちがう
入力も出力も同時に壁を超える場合、壁の 2 倍(約 86 億要素)の近く、の両方でも同じ規則のまま。大きなメモリの奥に置いた小さなデータ(104 件)は全部正しかった。
3 ・ 学習への影響
答えは合っているのに、学習の材料だけ壊れる
✗ 逆方向
勾配(gradient)は壁の先でまちがい
推論は正しく見えるので気づけない。でもそのモデルは、まちがった勾配で学習している。エラーも NaN も出ない。
backward の走査 604 件。新しい規則は不要で、同じ 3 つの規則を勾配の計算(2 つの行列積)に当てはめると 592 件すべて一致。
4 ・ たまたまではないのか
機械を変えても、OS を変えても、最後の 1 桁まで同じ
Mac Studio / M2 Ultra / macOS 27=
MacBook Pro / M2 Max / macOS 26=
同じ MacBook Pro / macOS 27
6156 / 6156
共通の測定が全項目で一致(まちがった値そのものも同じ)
1464 / 1464
同じ走査を NVIDIA A100 で実行 → 全部正しい。つまり Mac 側(MPS)固有の問題
チップだけ違う組と、OS だけ違う組の両方があるので、どちらの要因でもないと言える。正解の基準は常に CPU の倍精度(float64)。A100 の対照は現在、最新のコードで測り直し中(backward と拡張系列も追加)で、この段落の数字は更新予定。
5 ・ 実際のモデルでは
感情分類モデルで、3 分の 1 の答えが壊れた
1〜1365 件目:正しい
残り約 1/3:壊れる
1 件目attention の点数が 232 要素を超える位置2048 件目
公開モデル(RoBERTa、3 クラス)に 2048 件を 1 回で流すと、壊れた分はほぼ 1 つのクラスに偏る。全体の正解率は 7 ポイントしか下がらないので、集計値だけ見ていると気づかない。
どの文が壊れるかは、内容ではなくバッチの中の位置で決まる。256 件ずつに分けて流せば全部正しい。
6 ・ どうすればいいか
ルールは 1 つ:232 個以上のテンソルを GPU に作らない・読ませない
481 / 481
11 版の記録に当てはめると、黙ってまちがう実行を全部止められる。壁より小さい実行で黙ってまちがうものは 0
×1.00
大きな attention での速度低下(小さい学習ループでは ×1.73)
差し込むだけの見張り役(guard)を公開している。「黙ってまちがう」を「エラーで止まる」に変える。大きなバッチは GPU に載せる前に分割する。
backward の失敗も防げる(出力が先に止まるため)。代償として、正しく動く大きな実行の一部も止める(630 / 4095 件)。
7 ・ 言えること・言えないこと
外から測った記録であって、原因の解析ではない
- 中身(実装)は見ていない。入力と出力だけから判断した(black-box)。
- 測ったのは M2 世代の 2 台、macOS 26.6.2 と 27.0。macOS 14・15 は未測定(次の版で追加予定)。
- 系統的に測ったのは bmm だけ。ほかの演算は 26 件の簡易テストで「失敗がある」ことまで。
- 実モデルの例は 1 つ。ほかのモデルでは壊れ方が違うかもしれない。
- CUDA も万能ではない:torch.arange は CUDA でも 232 の先が黙って 0 になる(報告済み、修正の提案あり)。
ことば
- テンソル
- 数字をぎっしり並べた箱。要素の数 = 箱の中の数字の個数。
- MPS
- PyTorch が Apple の GPU を使うためのしくみ。
- bmm
- たくさんの行列のかけ算をまとめて行う命令。attention の中心。
- 転置(view)
- データを並べ替えずに「縦横を入れ替えて読む」指定。これを無視されると全部ずれる。
- 静かな失敗
- エラーも警告もなく、まちがった値が返ること。いちばん見つけにくい。
- 勾配
- 学習でモデルを直す方向を決める数値。壊れると学習が壊れる。
公開先:github.com/jniimi/mps-silent-failures(コード、測定の生データ、guard)。PyTorch への報告:Issue #197636。