この記事の出発点は、かなりシンプルです。
著者の Horace He さんは、GPU向けの高速matmul実装である CUTLASS を試していました。
8192×8192×8192 の大きな行列積をベンチマークすると、最初は CUTLASS が CuBLAS より速いように見えたそうです。これは「お、すごい」と思いますよね。私もここでちょっとテンションが上がります。
でも、Python から同じ CUTLASS を呼び出して比較すると、その差が消えてしまう。
さらに調べると、入力行列の中身が違うだけで性能が変わることに気づきます。
たとえば、

という具合です。
ここがかなり不思議です。
普通、行列積は「同じサイズなら、どんな値でも同じ計算量」です。掛け算の回数も、メモリの読み方も、基本は変わらない。
なので、値の中身で速度が変わるなんておかしい、というのが最初の自然な感覚だと思います。
結論からいうと、犯人は dynamic/switching power でした。
GPUはただ計算しているだけではなく、内部の無数のトランジスタが高速に ON/OFF を繰り返しています。
この「切り替わる回数」が多いほど電力を食います。これが switching power、つまり動的電力です。
一方で、何もしなくても消える電力もあります。これは static/leakage power と呼ばれます。
ざっくり言えば、
みたいなものです。
GPUには電力上限があり、そこに達すると GPU は clock speed(動作周波数)を下げて消費電力を抑えます。
この状態が throttling です。つまり、高い性能を出したくても、電力が足りなければ勝手にスピードを落とされるわけです。
そこで重要になるのが、入力データの「予測しやすさ」です。
その結果、ゼロのような“おとなしいデータ”のほうが電力を食わず、クロックが落ちにくいので速くなる、というわけです。
率直に言うと、これはかなり気持ちいい発見です。
「計算量は同じなのに速さが違う」というのは、最初はバグっぽい。でも、電力という別の軸を持ち込むと一気に腑に落ちる。ハードウェアってこういう“見えない制約”が本当に効くんですよね。

著者はさまざまなデータ分布でも試しています。たとえば:
Zeros: 全部 0Twos: 全部 2All Pies: 全部 πOne Bit: 各値の1ビットだけが立っているTernary: 1, -1, 0 のみSparse: 75% をマスクした疎なデータCheckerboard: チェッカーボード状に 0 を混ぜたものRandn: 正規分布の乱数Rand: 一様分布の乱数ざっくりした傾向としては、
という流れです。
著者の推測では、ゼロや定数ばかりの入力では、演算結果や内部状態の変化が少なくなり、トランジスタのスイッチングも減るのだろう、とのこと。
これはあくまで推測も含みますが、実験結果とはかなり整合しています。

個人的には、ここで「unstructured sparsity isn’t efficient with tensor cores?」と冗談っぽく言っているのが好きです。
普通は「疎なデータは効率が悪いこともある」とか、逆に「疎なら速い」とか、文脈次第で話がややこしいのですが、少なくとも**“ゼロが多いと電力的に有利”**というのは、かなり直感に反していて面白いです。
この記事のもう一つの重要なポイントは、power limit を変えると差がどう変わるか、です。
著者は、予測しやすい入力(zeros)と予測しにくい入力(randn)を比べています。
すると、power limit を 330W から 100W に下げるにつれて、zeros の有利さが増すことが分かります。
これは理屈として自然です。
さらに興味深いのは、かなり低い電力制限では、逆に傾向が崩れる場面もあることです。
著者は「GPUがあまりにも電力制約を受けていて、ゼロでもまだ電力を使いすぎるのでは」と推測しています。
ここは完全に断定ではないものの、かなりありそうな話だと思います。電力はほんとうに容赦ないですね。

著者はさらに、GPUの clock speed を固定して、zeros と randn の差を見ています。
すると、
という結果になります。
これもすごく大事です。
つまり、性能差は「アルゴリズムの違い」ではなく、電力制約とクロック制御の結果として生まれているわけです。
このへんは、GPUを単なる「計算機」として見ると見落としやすい。
でも実際には、GPUは“計算する石”であると同時に、“電力と熱に縛られた機械”なんですよね。
私はこの手の話を見るたびに、ハードウェア性能って最終的には物理法則に負けるんだな、としみじみ思います。
記事の後半では、Nvidiaが広告や仕様表で出している FLOPS と、実際に持続できる性能の差にも触れています。
Nvidiaが示す理論上の FLOPS は、だいたい次のような式で表されます。
FLOPS = Tensor Cores数 × Max Clock Speed × 1 instructionあたりの演算量
たとえば H100 では、Tensor Core の数や最大クロックから計算して、約 989 TFLOPS という数字になる、と著者は説明しています。
ただしこれは、その最大クロックをずっと維持できる前提です。
でも実際には、電力制限のせいでそこまで維持できない。
そのため、実運用での性能は理論値より低くなります。
ここが実務的にはかなり重要です。
ベンチマークやスペック表を見るとき、つい「このGPUは○○ TFLOPS か!」と思いがちですが、現実には
で、実効性能はかなり変わります。
著者は、H100 は理論上 A100 の3倍近い FLOPS を持っていても、実際には電力制約のせいで「体感的には 2倍くらい」に見えることが多い、と述べています。
これも断言というより観察に基づく話ですが、現場感としてはかなり納得感があります。
この話の面白さは、単に「ゼロのほうが速い」という珍現象ではありません。
本質は、GPUの速度は演算器の性能だけでは決まらないという点にあります。
多くの人は、GPU性能を「Tensor Core が何個あるか」「理論 FLOPS がいくつか」で見がちです。
でも実際には、
みたいな、かなり泥くさい要素が効いてくる。
私はこのあたり、ハードウェアのロマンを感じます。
ソフトウェアの世界では「同じ計算なら同じ結果」が基本ですが、ハードウェアは「同じ計算でも、物理的な振る舞いは全然同じではない」。
その差が性能として表に出るわけです。
この記事が教えてくれるのは、次の一言に尽きます。
GPUの matmul は、計算量だけでなく、データの“おとなしさ”で速さが変わることがある。
理由は、入力値によってトランジスタの切り替わり方が変わり、それが動的電力に影響し、結果として power limit と throttling に効いてくるからです。

技術者目線で見ると、
という、かなり重要な教訓が詰まっています。
そして何より、「matmul の速さがデータの値で変わる」という事実は、やっぱりちょっとワクワクします。
コンピュータは論理で動いているようで、最後はちゃんと物理なんだな、と思わされる記事でした。
参考: Strangely, Matrix Multiplications on GPUs Run Faster When Given "Predictable" Data! [short]