「MacBook Air が TFLOPS 単位の計算を?」–信じられないかもしれませんが、これは事実です。ファンレスの M4 MacBook Air が MLX を使った行列積ベンチマークで 2.78TFLOPS を記録。熱やメモリの影響も考慮しつつ、実測値の算出方法や性能の実態をわかりやすく解説します。
<実行環境>
- 機種: M4 Macbook Air
- メモリ: 16GB
- Python 3.10.11
- MLXフレームワーク バージョン 0.28.0
1. 実行時間の測定
実行時間の測定には、シンプルに行列積の演算を用いました。
1.1 測定スクリプト
GitHub Gist に測定スクリプトを公開しています。ご自分の Apple シリコン搭載の Mac で測定してみたい方はどうぞお使いください。Gist からダウンロードしたスクリプトを matmul_benchmark.py という名前で保存してから、ターミナルで以下のコマンドを実行してください。
% python3 -m venv venv
% . venv/bin/activate
% pip install mlx
% python matmul_benchmark.py
1.2 測定結果
行列のサイズを複数選んで、それぞれの実行時間を測定した結果は以下の通りです。平均実行時間は、連続5回の測定の平均です。演算には bfloat16 型を使いました。
| 行列サイズ | 平均実行時間 (秒) | 総演算回数 | 実効性能(TFLOPS) | 1回目 (秒) | 2回目 (秒) | 3回目 (秒) | 4回目 (秒) | 5回目 (秒) |
|---|---|---|---|---|---|---|---|---|
10000x10000 |
0.740 | 2兆回 | 2.70 | 0.738 | 0.738 | 0.742 | 0.740 | 0.743 |
20000x20000 |
5.754 | 16兆回 | 2.78 | 5.667 | 5.698 | 5.750 | 5.810 | 5.847 |
30000x30000 |
21.624 | 54兆回 | 2.50 | 20.341 | 21.076 | 22.252 | 21.897 | 22.555 |
40000x40000 |
75.872 | 128兆回 | 1.69 | 62.925 | 77.502 | 72.921 | 85.509 | 80.505 |
1.3 考察
- ピーク性能: 行列サイズ
20000x20000で 2.78 TFLOPS という最高のパフォーマンスを記録しました。 - サーマルスロットリング:
20000x20000と30000x30000の測定では、回を重ねるごとに実行時間がわずかに長くなる傾向が見られ、熱による性能調整(サーマルスロットリング)が起きている可能性が示唆されます。 - スワップの影響:
40000x40000では実行時間が大幅に長くなり、各回のばらつきも大きくなっています。これはメモリが不足し、低速なSSDへのスワップが頻繁に発生しているためと考えられます。アクティビティモニタで、実行中にスワップ使用領域の増減が確認できました。
2. 総演算回数とTFLOPS性能
TFLOPS(テラフロップス)は、1秒あたりに何兆回の浮動小数点演算を実行できたかを示す性能指標です。 総演算回数と実行時間から求めることができます。
2.1 総演算回数
まず、総演算回数を計算します。行列 \(A\) と \(B\) の行列積 \(C = A \cdot B\) は、次のように表現できます。
$$ \left( \begin{array}{rrr} c_{11} & \dots & c_{1N} \\ \vdots & \ddots & \vdots \\ c_{N1} & \dots & c_{NN} \end{array} \right)= \left( \begin{array}{rrr} a_{11} & \dots & a_{1N} \\ \vdots & \ddots & \vdots \\ a_{N1} & \dots & a_{NN} \end{array} \right)\cdot \left( \begin{array}{rrr} b_{11} & \dots & b_{1N} \\ \vdots & \ddots & \vdots \\ b_{N1} & \dots & b_{NN} \end{array} \right) $$行列 \(C\) の1つの要素 \(c_{ij}\) は、
$$ c_{ij} = \sum_{k=1}^{N} a_{ik}b_{kj} = a_{i1}b_{1j} + a_{i2}b_{2j} + \cdots + a_{iN}b_{Nj} $$と計算できるので、\(N\) 回の乗算と \(N-1\) 回の加算があります。合計で \(2N-1\) 回の計算が必要です。今回の実験では、\(N\) が非常に大きいため、これはほぼ \(2N\) 回の演算と見なせます。
行列全体では \(N^2\) 個の要素があるため、総演算回数は以下のように計算できます。
$$ \text{総演算回数} \approx (2N) \times N^2= 2N^3 $$例えば、\(N=20000\) の場合、
$$ \text{総演算回数} \approx 2 \times 20000^3 [回] = 16 \times 10^{12} [回]= 16兆回 $$となります。
2.2 TFLOPS性能の算出
そして、総演算回数と実行時間を使って、以下の式で計算します。
$$\text{TFLOPS} = \frac{\text{総演算回数}}{\text{実行時間[秒]} \times 10^{12}}$$例えば、\(N=20000\) の場合、
$$\text{TFLOPS} = \frac{16 \times 10^{12}}{5.754 \times 10^{12}} \approx 2.78$$となります。
**
さぁ、TFLOPSの計算回数の大きさが実感できましたか。