+ 作る
図を読み込んでいます…
1 / 15
GPUとLLM:グラフィックボードはなぜAIを動かせるのか / 全5章

なぜGPUが得意なのか:算術強度とルーフライン

発行
かえで
版
第2版
改訂
分量
15コマ・5,079字

GPUはなぜ行列積が得意なのか。算術強度 I=FLOPs÷バイト と、ルーフライン(性能 ≈ min(ピーク, I×帯域))のグラフの上で赤い点を動かしながら、大きな行列積・decode・バッチ・タイリングの違いを見ていきます。『GPUとLLM』第3章。

なぜGPUが得意なのか:算術強度とルーフライン

『GPUとLLM』の第3章です。第1章ではGPUの中身を、第2章ではLLMの計算のほとんどが行列積であることを見ました。この章ではその2つをつなぎます。GPUはなぜ行列積が得意なのか。そして同じ行列積なのに、なぜ速く動く場面と、ほとんど力を出せない場面があるのか、という問いです。

鍵になるのは「算術強度」という1つの比と、それを描いた「ルーフライン」というグラフです。図の青い坂とオレンジの平らな天井、その上の赤い点が、この章の主役です。点がグラフのどこにいるかで、GPUが計算で忙しいのか、データを待っているのかが分かります。

  • 『GPUとLLM』第3章
  • なぜGPUが得意なのか:算術強度とルーフライン
  • 同じデータを何度使い回せるかで、GPUの速さが決まる
  • ↑ 性能
  • メモリ律速
  • 計算律速
  • 算術強度 I →

行列積は、互いに独立な積和の塊

行列積 C = A × B では、出力 C の1マス C[i][j] は、A の i 行目と B の j 列目を端から順に掛けて、足し合わせたものです。図の青い行と紫の列から、オレンジのマス1つが決まります。1マスあたり掛け算と足し算が N 回ずつなので 2N FLOPs、N² マス全体では 2N³ FLOPs になります(第2章の 2mnk で m=n=k=N としたものです)。

大事なのは、どのマスも、ほかのマスの答えを待たずに計算できることです。右上のマスを先に計算しても、左下を先にしても、結果は変わりません。順番に縛られない仕事が大量にあること。これが、GPUが行列積に向いている第一の理由です。

  • 行列積は、互いに独立な積和の塊
  • 行列Bのマス目
  • C[i][j] = Σ A[i][k] × B[k][j]
  • k を 1 から N まで動かして足し合わせる
  • B(重み N×N)
  • マス1つ:掛け算と足し算を N 回ずつ = 2N FLOPs
  • 全体:N² マス × 2N = 2N³ FLOPs
  • A(入力 N×N)
  • (第2章の 2mnk で m=n=k=N)
  • 行列Aのマス目
  • 各マスのスレッドを表す点
  • 出力Cのマス目
  • どのマスも、ほかのマスの答えを待たない → 全部を同時に計算してよい
  • C = A × B(出力)

1マスを、1本のスレッドに任せる

そこで、出力のマス1つを1本のスレッドに任せます。図の黒い点が1本1本のスレッド、色の区切りは、まとめて1つのSMに渡す「ブロック」です。第1章で見たように、SMはブロックをワープ(32スレッド)単位で動かします。

どれくらいの数になるでしょうか。N=4,096 の正方行列なら、マスは 4,096² ≈ 1,678万個あります。代表例として H100(SXM)では SM が132個あり、1つの SM は最大2,048スレッドを同時に抱えられるので、合わせて約27万スレッドが同時に動ける状態になります。1,678万マスも、GPUにとっては次々に流し込める量です。なお実際のカーネルでは、1本のスレッドが複数のマスを受け持つことがよくあります。

  • 1マスを、1本のスレッドに任せる
  • 各マスのスレッドを表す点
  • 出力Cのマス目
  • 1マス = 1本のスレッドの仕事
  • 黒い点がスレッド。色の区切りは、 まとめて1つのSMに渡す「ブロック」
  • N=4,096 なら 4,096² ≈ 1,678万マス
  • H100(SXM):SM 132個 × 最大2,048スレッド → 約27万スレッドを同時に抱えられる
  • (実際のカーネルでは、1スレッドが複数マスを受け持つことも多い)
  • 出力 C(図は 8×8、実際は N×N)

計算するには、まずデータを運ぶ

ただし、演算器はデータがなければ何もできません。A と B は、GPUのメモリである HBM(図の左の青い箱)に置かれていて、計算の前に右の演算器まで運ぶ必要があります。代表例の H100 SXM では、HBM から運べる速さが約 3.35 TB/s、演算器の速さは BF16 の行列演算で約 989 TFLOPS です。

そこで、1つの計算が「どれだけ計算して、どれだけ運ぶか」の比を考えます。これを算術強度 I と呼び、I = 計算量(FLOPs)÷ 運ぶデータ量(バイト)と書きます。言い換えると、1バイト運ぶあいだに何回計算するかです。たとえば長さ n のベクトル2本の内積なら、2n FLOPs に対して BF16 で 4n バイトを運ぶので、I = 0.5 です。

  • 計算するには、まずデータを運ぶ
  • HBM(GPUのメモリ)
  • 演算器(SM × 132)
  • 行列Aのマス目
  • 行列Bのマス目
  • 各マスのスレッドを表す点
  • 出力Cのマス目
  • 運ぶ:約3.35 TB/s
  • A(入力)
  • B(重み)
  • 容量 80GB・演算器からは遠い
  • ピーク 約989 TFLOPS(BF16)
  • 算術強度 I = 計算量(FLOPs)÷ 運ぶデータ量(バイト)
  • = 1バイト運ぶあいだに、何回計算するか
  • 例:長さ n のベクトル2本の内積(BF16) 2n FLOPs ÷ 4n バイト = 0.5 FLOP/バイト

ルーフライン:坂と天井

左の図がルーフラインと呼ばれるグラフです。横軸が算術強度 I、縦軸が実際に出せる性能で、どちらも1目盛りで10倍になる対数目盛りです。前のページで左右にあったHBMと演算器の箱が、青い領域とオレンジの領域に変わりました。

性能の上限は2つあります。1つは演算器の速さで決まる平らな天井(オレンジ、約989 TFLOPS)。もう1つはデータを運ぶ速さで決まる坂(青)で、高さは I × 帯域です。1バイトあたり I 回計算する仕事なら、毎秒3.35兆バイト運べば毎秒 I × 3.35兆回まで計算できる、という意味です。実際に出せる性能は2本のうち低いほうで、式にすると 性能 ≈ min(ピーク, I × 帯域) です。前のページの内積(I=0.5)は赤い点の位置で、ピークの約0.2%しか出せません。

  • ルーフライン:坂と天井
  • ↑ 性能(TFLOPS)
  • 1,000
  • ルーフラインの目盛り線
  • 到達できる性能 ≈ min(ピーク演算性能, I × メモリ帯域)
  • ピーク 約989 TFLOPS
  • 青い坂:性能 = I × 3.35 TB/s → 運ぶ速さで頭打ち(メモリ律速)
  • 100
  • 橙の天井:約989 TFLOPS → 演算器が全力で動いている(計算律速)
  • 10
  • 帯域 3.35 TB/s
  • 2本のうち低いほうが、実際に出せる性能
  • 赤い点:内積(I=0.5) → 0.5 × 3.35 ≈ 1.7 TFLOPS(ピークの約0.2%)
  • 1
  • 内積 I=0.5
  • メモリ律速
  • 計算律速
  • 0.1
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

尾根点:坂と天井が出会う場所

坂と天井が交わる点を尾根点と呼び、その横軸の値を I と書きます。I × 帯域 = ピーク となる I なので、I = ピーク ÷ 帯域 です。H100 SXM の公称値で計算すると、989 TFLOPS ÷ 3.35 TB/s ≈ 295 FLOP/バイト。グラフに現れた灰色の縦線がその位置です。

つまりこのGPUで演算器を使い切るには、HBMから1バイト運ぶあいだに約300回の計算が必要です。縦線より左の仕事は、演算器がいくらあってもデータ待ちになり(メモリ律速)、右の仕事だけが演算器の速さで動けます(計算律速)。なお、ここで使った989 TFLOPSは、疎行列向けの機能を使わない BF16 の公称ピークです。実際の計算で出せる性能は、これより低くなるのが普通です。

  • 尾根点:坂と天井が出会う場所
  • ↑ 性能(TFLOPS)
  • 1,000
  • ルーフラインの目盛り線
  • 到達できる性能 ≈ min(ピーク演算性能, I × メモリ帯域)
  • ピーク 約989 TFLOPS
  • 100
  • 尾根点 I* = ピーク ÷ 帯域
  • = 989 TFLOPS ÷ 3.35 TB/s ≈ 295 FLOP/バイト
  • 10
  • 帯域 3.35 TB/s
  • 1バイト運ぶあいだに約300回計算できないと、 演算器が手持ちぶさたになる
  • 1
  • 内積 I=0.5
  • H100 SXM・BF16密行列の公称ピークで概算。 実際に出せる性能はこれより低め
  • メモリ律速
  • 計算律速
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

正方行列積:I ≈ N/3

では、LLMの中心にある行列積はグラフのどこにいるのでしょうか。N×N の行列どうしの積で考えます。計算量は2ページ目で見たとおり 2N³ FLOPs です。運ぶデータは、A と B を読んで C を書く3枚ぶんで 3N² 個、BF16 なら1個2バイトなので 6N² バイトです。割り算すると I ≈ 2N³ ÷ 6N² = N/3 になります。

ここで効いてくるのがオーダーの違いです。N が2倍になると、計算は N³ なので8倍、運ぶ量は N² なので4倍にしかなりません。行列が大きいほど、1バイトあたりの計算が増えるのです。N=64 なら I ≈ 21 で、赤い点は坂を登りましたが、まだ尾根点の左です(約72 TFLOPS、ピークの約7%)。なお、これは各行列を HBM から1回ずつだけ運べた理想の場合の値です。

  • 正方行列積:I ≈ N/3
  • ↑ 性能(TFLOPS)
  • 1,000
  • ルーフラインの目盛り線
  • I = 2N³ ÷(3N² × 2バイト)≈ N/3
  • ピーク 約989 TFLOPS
  • 計算量:2N³ FLOPs(N³ に比例)
  • 100
  • 運ぶ量:A・B・C の 3N² 個 × 2バイト(N² に比例)
  • N=64
  • N が2倍 → 計算は8倍、運ぶ量は4倍 大きい行列ほど I が上がる
  • 10
  • 帯域 3.35 TB/s
  • N=64:I ≈ 21 → まだ坂の上(約72 TFLOPS、ピークの約7%)
  • 1
  • メモリ律速
  • 計算律速
  • ※ 各行列を HBM から1回ずつだけ運べた理想の場合
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

N を大きくすると、天井に届く

N を 4,096 まで大きくしてみます。I ≈ 4,096 ÷ 3 ≈ 1,365 FLOP/バイトで、尾根点の約295を大きく越えました。赤い点は青い坂を登り切って、オレンジの天井の上に移っています。ここではデータを運ぶ速さはもう問題ではなく、演算器の速さそのものが上限です。これを計算律速と呼びます。

LLMの学習や、プロンプトをまとめて読む prefill(第2章)では、何千ものトークンをまとめて大きな行列積にできるので、この天井の側で動かせます。GPUが「行列積が得意」と言われるのは、まさにこの状態のことです。数千の演算器が休まず働けるだけの計算が、運んだデータ1バイトごとに用意されているわけです。ただし実際に天井近くまで届くかどうかは、データの運び方の工夫しだいで、その話は後半のタイリングで扱います。

  • N を大きくすると、天井に届く
  • ↑ 性能(TFLOPS)
  • N=4,096
  • 1,000
  • ルーフラインの目盛り線
  • I = 2N³ ÷(3N² × 2バイト)≈ N/3
  • ピーク 約989 TFLOPS
  • 計算量:2N³ FLOPs(N³ に比例)
  • 100
  • 運ぶ量:A・B・C の 3N² 個 × 2バイト(N² に比例)
  • N が2倍 → 計算は8倍、運ぶ量は4倍 大きい行列ほど I が上がる
  • 10
  • 帯域 3.35 TB/s
  • N=4,096:I ≈ 1,365 → 尾根点を越えて天井へ(計算律速)
  • 1
  • メモリ律速
  • 計算律速
  • ※ 各行列を HBM から1回ずつだけ運べた理想の場合
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

decode:行列 × ベクトルは I ≈ 1

一方、文章を1トークンずつ生成する decode(第2章)はどうでしょうか。1人分だけを生成しているとき(batch 1)、各層でやっているのは、重みの行列 W にベクトル x を掛ける計算です。右の図のように、紫の大きな行列に対して、青い入力は細い縦1列しかありません。

このとき重みは1個ずつ、たった1回の積和にしか使われません。重み1個(BF16 で2バイト)を運んで、掛け算と足し算の2 FLOPs。つまり I ≈ 1 FLOP/バイトです。赤い点は天井から滑り落ちて、尾根点(約295)のはるか左、坂の下のほうに来ました。出せる性能は約3.35 TFLOPS、ピークの約0.3%です。GPUの演算器のほとんどは、重みが届くのを待っています。

  • decode:行列 × ベクトルは I ≈ 1
  • ↑ 性能(TFLOPS)
  • decode(batch 1):行列 × ベクトル
  • 1,000
  • ルーフラインの目盛り線
  • ピーク 約989 TFLOPS
  • 重み行列Wのマス目
  • 入力は 1人分の1列だけ
  • 100
  • ×
  • =
  • 重み W
  • 入力 x
  • 出力
  • 10
  • 帯域 3.35 TB/s
  • 重み1個(2バイト)を運んで、積和1回(2 FLOPs)
  • I ≈ 2 FLOPs ÷ 2バイト = 1 FLOP/バイト
  • decode B=1
  • 1
  • 性能 ≈ 1 × 3.35 TB/s ≈ 3.35 TFLOPS → ピークの約0.3%。演算器の大半は待ちぼうけ
  • メモリ律速
  • 計算律速
  • ※ 重みの読み込みだけを数えた概算(入力・出力は小さい)
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

decodeの速さは、重みを読む時間で決まる

メモリ律速だと分かると、decode の速さの上限が簡単に見積もれます。1トークン作るたびに、全部の層の重みを HBM から一通り読む必要があるので、上限はおよそ メモリ帯域 ÷ 重みのバイト数 回/秒 です。右の紫の行列が、重み全体の大きさを表すバーに変わりました。

たとえばパラメータ80億(8B)のモデルを BF16 で持つと、重みは 8×10⁹ × 2バイト ≈ 16 GB です。これを 3.35 TB/s で読むと約4.8ミリ秒、1秒に約210回です。つまり batch 1 のとき、H100 1枚でも約200トークン/秒が上限の目安で、演算器をいくら速くしてもこの数字は変わりません。実際には KVキャッシュも読むことや、帯域を公称値どおりには使い切れないことから、これより遅くなります。

  • decodeの速さは、重みを読む時間で決まる
  • ↑ 性能(TFLOPS)
  • decode の速さの上限(batch 1)
  • 1,000
  • ルーフラインの目盛り線
  • ピーク 約989 TFLOPS
  • 重み行列Wのマス目
  • 8Bモデルの重み ≈ 16 GB(BF16)
  • 100
  • 読んだ重みを使うのは 1人分だけ(B=1)
  • 1トークンごとに、この重みを HBM から全部読む
  • 10
  • 帯域 3.35 TB/s
  • 上限 ≈ メモリ帯域 ÷ 重みのバイト数
  • decode B=1
  • = 3.35 TB/s ÷ 16 GB ≈ 210回/秒
  • 1
  • batch 1 なら、H100 1枚でも 約200トークン/秒が上限の目安
  • メモリ律速
  • 計算律速
  • 0.1
  • 尾根点 I*≈295
  • ※ 実際は KVキャッシュも読み、帯域も公称値までは   使い切れないので、これより遅くなる
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

バッチ:B人分をまとめると I ≈ B

そこでサーバーは、たくさんの人のリクエストをまとめて(バッチにして)同時に decode します。B人分のトークンを並べると、HBM から一度読んだ重み1個を B人分の積和に使い回せます。右の紫のバーの下で、オレンジのバーが B=64 人分に伸びたのがその様子です。

重み1個(2バイト)に対して計算は 2B FLOPs なので、I ≈ B です。B=64 なら赤い点は坂を右上へ登り、約214 TFLOPS まで上がります。まだメモリ律速の側なので、1ステップの時間は重みを読む時間とほぼ同じ。ほぼ同じ時間で64人分のトークンが出てくるわけで、これが推論サーバーがリクエストをまとめる一番の理由です。ただし人数分の KVキャッシュも読むので、実際の I はこれより下がります(第5章で扱います)。

  • バッチ:B人分をまとめると I ≈ B
  • ↑ 性能(TFLOPS)
  • バッチ:B人分のトークンをまとめて計算
  • 1,000
  • ルーフラインの目盛り線
  • B=64
  • ピーク 約989 TFLOPS
  • 8Bモデルの重み ≈ 16 GB(BF16)
  • 100
  • 64人分の区切り
  • ×64
  • 一度読んだ重みを B=64 人分に使い回す
  • 重み1個(2バイト)で、積和 B 回(2B FLOPs)
  • 10
  • 帯域 3.35 TB/s
  • I ≈ 2B ÷ 2 = B FLOP/バイト
  • B=1
  • B=64:約214 TFLOPS(B=1 の64倍)
  • 1
  • 1ステップの時間は重みを読む時間とほぼ同じ → 全体のトークン/秒が約64倍に
  • メモリ律速
  • 計算律速
  • ※ B が約300で尾根点に届く計算。実際は人数分の   KVキャッシュも読むので、I はこれより下がる
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

タイリング:運んだデータを近くで使い回す

ここまでの I ≈ N/3 は、行列を HBM から1回ずつだけ運べたときの理想の値でした。素直に1マスずつ計算すると、各スレッドが自分の行と列を毎回 HBM から読むので、積和1回(2 FLOPs)に2つの値(4バイト)が必要になり、I は 0.5 まで落ちてしまいます。

そこで使うのがタイリングです。出力を T×T のタイル(左のオレンジの区画)に分け、その計算に必要な A の帯と B の帯を少しずつ、SM の中にある小さくて速い共有メモリに運びます。第1章のメモリ階層を思い出してください。右の図で、前のページの青とオレンジの領域が、HBM と共有メモリの箱に戻りました。共有メモリに載せた値は、タイルの中の T 個のマスが共通で使えるので、HBM から運ぶ回数が約 T 分の1になり、I はおよそ T/2 まで上がります。

  • タイリング:運んだデータを近くで使い回す
  • 行列Bのマス目
  • レジスタ・Tensor Core ここで積和を計算する
  • B(重み)
  • タイル内で T 回使い回す
  • 行列Aのマス目
  • 出力Cのマス目
  • 共有メモリ(SM の中) 小さいが、近くて速い
  • タイルを1回だけ運ぶ
  • HBM(80GB) 大きいが、演算器からは遠い(約3.35 TB/s)
  • A(入力)
  • C のタイル(T×T)
  • タイルなし:I ≈ 0.5  → タイル1辺 T:I ≈ T/2(T=128 なら約64)

タイリングで、点を右へ動かす

ルーフラインに戻って、タイリングの効果を見ます。タイルを使わない素直な実装は、白い丸の I ≈ 0.5 にいます。同じ行列積なのに、内積と同じくらいメモリ律速です。タイルの1辺を T=128 にすると I ≈ 64 となり、赤い点は坂を大きく登ります。計算の中身は変えていないのに、運び方だけで性能が約100倍変わるわけです。

この T/2 は、共有メモリへの運び込みだけを数えた値です。実際には HBM と SM のあいだに L2 キャッシュもあり、複数の SM が同じタイルを共有できるので、HBM から見た I はさらに上がり、灰色の曲線の先にある理想の N/3 に近づいていきます。行列積ライブラリの cuBLAS や、Attention 用の FlashAttention は、この運び方を究めたカーネルです。

  • タイリングで、点を右へ動かす
  • ↑ 性能(TFLOPS)
  • 理想 N/3
  • 同じ行列積でも、運び方で I が変わる
  • 1,000
  • ルーフラインの目盛り線
  • T=128
  • ピーク 約989 TFLOPS
  • タイルなし:積和1回ごとに2値を HBM から → I ≈ 2 FLOPs ÷ 4バイト = 0.5
  • 100
  • タイル T=128:運んだ値を128回使う → I ≈ T/2 ≈ 64(性能は約100倍)
  • 10
  • 帯域 3.35 TB/s
  • L2 キャッシュで SM どうしがタイルを共有 → HBM から見た I は理想の N/3 に近づく
  • 計算の中身は同じ。変えたのは 「どこに置いて何回使うか」だけ
  • 1
  • タイルなし
  • メモリ律速
  • 計算律速
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • 両軸とも対数目盛り(1目盛りで10倍)

CPUと比べると:並列度と帯域の桁が違う

代表例として、サーバー向けCPUの AMD EPYC 9654(96コア)と H100 SXM を並べました。前のページのグラフの青と橙の領域が、GPUの2本のバーに変わっています。メモリ帯域はCPUが 460.8 GB/s、GPUが約3.35 TB/s で約7倍。同時に抱えられるスレッド数は、CPUの192に対してGPUは約27万で、約1,400倍です。

この差は、どちらの律速かで効き方が変わります。メモリ律速の decode では帯域の差がそのまま速さの差になり、8Bモデル(16 GB)を読む上限はCPUで約29回/秒、GPUで約210回/秒です。計算律速の大きな行列積では、Tensor Core を持つGPUの演算性能が効いて差はさらに広がります(倍率は数値形式や世代で大きく変わるので、ここでは向きだけ)。CPUは分岐の多い複雑な仕事に強く、GPUは同じ計算を大量に流す仕事に振り切った作りです。

  • CPUと比べると:並列度と帯域の桁が違う
  • メモリ帯域(1秒にメモリから運べる量)
  • CPU(EPYC 9654)
  • 460.8 GB/s
  • GPU(H100 SXM)
  • 約3.35 TB/s(CPUの約7倍)
  • 同時に抱えられるスレッド数
  • CPU(EPYC 9654)
  • 192(96コア × 2)
  • GPU(H100 SXM)
  • 約27万(CPUの約1,400倍)
  • CPU:AMD EPYC 9654(96コア/192スレッド、DDR5-4800 × 12ch) GPU:H100 SXM(SM 132個 × 最大2,048スレッド)
  • メモリ律速の decode では、帯域の差がそのまま速さの差に 8Bモデル(16 GB)を読む上限:CPU 約29回/秒、GPU 約210回/秒
  • 大きな行列積(計算律速)では、Tensor Core を持つGPUの演算性能が効いて、差はさらに広がる

まとめ:GPUが得意なのは「使い回せる」計算

この章では、行列積が互いに独立な積和の塊で、何十万ものスレッドに分けられること、そして速さを決めるのは算術強度 I(計算量 ÷ 運ぶデータ量)だということを見ました。ルーフラインの上で、大きな行列積は橙の天井に、batch 1 の decode は青い坂の下のほうにいます。バッチとタイリングは、どちらも「一度運んだデータを何度も使う」ことで点を右へ動かす工夫でした。

GPUが得意なのは、同じ重みを大量のデータに使い回せる行列積です。逆に、使い回しが少ないとメモリが壁になります。次の第4章では、重みのバイト数そのものを減らす量子化と、複数のGPUに分けて載せる並列化を扱います。この章の「帯域 ÷ 重みのバイト数」を覚えておくと、なぜそれが効くのかがすぐに見えてきます。

  • まとめ:GPUが得意なのは「使い回せる」計算
  • ↑ 性能(TFLOPS)
  • 大きな行列積
  • ① 行列積は互いに独立な積和の塊。   マスごとにスレッドへ分けて同時に計算
  • 1,000
  • ルーフラインの目盛り線
  • バッチ B=64
  • ピーク 約989 TFLOPS
  • ② 性能 ≈ min(ピーク, I × 帯域)。   H100 の尾根点は約295 FLOP/バイト
  • 100
  • ③ 大きな行列積は I ≈ N/3 で計算律速。   decode(batch 1)は I ≈ 1 でメモリ律速
  • 10
  • 帯域 3.35 TB/s
  • ④ バッチ(I ≈ B)とタイリングで、   同じデータを使い回して点を右へ
  • decode B=1
  • 1
  • メモリ律速
  • 計算律速
  • 次章:1枚に載らないモデルを動かす 量子化で「重みのバイト数」を減らし、 並列化で複数のGPUに分けて載せる
  • 0.1
  • 尾根点 I*≈295
  • 0.1
  • 1
  • 10
  • 100
  • 1,000
  • 10,000
  • 算術強度 I(FLOP/バイト)→
  • H100 SXM(BF16)の公称値で描いた概算

0 件のコメント

読み込み中…

権利侵害・不適切な内容の連絡: [email protected]