$30 off During Our Annual Pro Sale. View Details »

メモリボトルネックの概要とその影響について - CADDi STUDDi

[email protected]
December 10, 2021
1.4k

メモリボトルネックの概要とその影響について - CADDi STUDDi

[email protected]

December 10, 2021
Tweet

Transcript

  1. メモリボトルネックの概要と
    その影響について

    View Slide

  2. 今日話すこと
    ● 自己紹介
    ● CPUの性能とメモリ性能の関係
    ● 行列行列積に見るCPUキャッシュ最適化の例

    View Slide

  3. 今日のゴール
    ● 高いCPUを買っても何もしなければアプリケー
    ションは速くならないという実感を持つ
    ● キャッシュヒット率の重要性を理解する

    View Slide

  4. 大学院時代はスパコンで機械学習の訓練を高速化する研究をしていました
    ● 機械学習の訓練データを共有の並列ファイルシステムに置いて計算ノードからアクセスするとlatencyが高い
    ● 計算ノードのローカルストレージは低latencyだがコピーに時間がかるため少ない計算ノードだとペイしにくい
    https://dl.acm.org/doi/10.1145/3365109.3368768
    というトレードオフの「いいとこどり」をする手法を提案し、Chainerで実装して訓練にかかる時間を評価

    View Slide

  5. 一方でスパコンといえば計算能力に関する研究が主流
    ● スパコン分野の研究でよく出てくるネタ
    ○ 分散処理
    ○ GPU/FPGAを使った行列計算の高速化
    ○ 高速な連立一次方程式の解法
    ○ 高速な固有値問題の解法
    こんな感じなので、研究室内の輪講でもこれらの話題につ
    いて学びました。
    今日はその中でも面白かった「CPU性能の評価」に関する
    話をご紹介します。

    View Slide

  6. CPUの理論性能と実効性能(1/2)
    ● 理論性能
    ○ def; CPUのspecから求められる理論上出せる最高性能
    ○ 倍精度Flop/sで表記するのが一般的
    ○ 計算方法の一例
    ■ clock * (FMA演算器の個数 x 2) * core数 * (最大SIMD幅
    /64)
    ○ Intel Xeon Gold 6126 (2.6GHz/12core) の例
    ■ 1 coreあたり: 2.6 GHz * (2 * 2) * (512/64) = 83.2 GFlop/s
    ■ 1 socketあたり: 83.2 GFLOPS/core * 12 core = 998.4
    GFlop/s
    (ガチ勢向け)AVX使用時はクロックがベースクロックよりも下がりますが本スライドでは同じと仮定します

    View Slide

  7. CPUの理論性能と実効性能(2/2)
    ● 実効性能
    ○ def; 実際にapplicationを動かして計測された性能
    ○ こちらも倍精度Flop/sで表現するのが一般的
    ○ 計算方法の一例
    ■ 2 GFlopsの計算を行うapplicationの実行に10秒
    かかった
    ● 2 GFlops / 10 sec = 0.2 GFlop/s

    View Slide

  8. 残念なお知らせ(1/2)
    ● CPUの理論性能は基本的には出せない
    https://www.top500.org/lists/top500/2021/06/
    性能効率 (Rmax / Rpeak)
    [%]
    82.2 %
    74.0
    %
    75.3 %

    View Slide

  9. 残念なお知らせ(2/2)
    ● CPUの性能を阻害する多くのボトルネックが存
    在する
    ○ ネットワーク latency
    ○ ストレージI/O latency
    ○ メモリI/O latency
    ○ 分岐予測ミス
    ○ パイプラインストール etc..
    <- 今日はここの話をします

    View Slide

  10. 計算回数とメモリI/O回数の比率を考える(1/2)
    ● 計算するにはメモリからデータを読み書きしな
    ければならない
    double a = a + b; // 2回読み込み 1回書き
    込み
    上記のコードの場合、1回の加算に対して3回
    (8 x 3 = 24 Byte) のメモリI/Oが発生している

    View Slide

  11. 計算回数とメモリI/O回数の比率を考える(2/2)
    ● この時
    ○ メモリを24 Byte読み書きしないと1 Flop計算できな

    ● 言い換えると
    ○ メモリを24 Byte読み書きするスピードの方が1 Flop計
    算するよりも遅かったら、メモリI/Oがボトルネックに
    なる
    ○ 逆に、メモリを24 Byte読み書きするスピードの方が1
    Flop計算するよりも速かったら、CPUが1 Flop計算す

    View Slide

  12. わんこそばを食べる人とわんこそばを供給する人を考える
    (1/4)
    ● わんこそば(以下WS)で例えてみる
    ● WSを5杯/sec食べられる人が
    いるとする
    ● この時WS消費速度のボトルネ
    ックになるのは
    ○ WSを食べる人か?
    ○ WSを供給する店員か?
    5杯/secでWSを食べる人
    n杯/secでWSを供給する

    View Slide

  13. わんこそばを食べる人とわんこそばを供給する人を考える
    (2/4)
    ● 店員がボトルネックになるケース
    ● 店員が3杯/secのスピードで供
    給すると、3杯/secしか達成で
    きない
    ● WSを食べる人は1秒で5杯食べ
    る能力があるのに、1秒あたり
    2杯分無駄にしてしまう
    5杯/secでWSを食べる人
    3杯/secでWSを供給する

    はよ持ってこんかい!

    View Slide

  14. わんこそばを食べる人とわんこそばを供給する人を考える
    (3/4)
    ● WSを食べる人がボトルネックになるケース
    ● 店員が10杯/secのスピードで
    供給しても、5杯/secしか達成
    できない
    ● 店員は1秒あたりさらに5杯供
    給できるが持て余してしまう
    5杯/secでWSを食べる人
    10杯/secでWSを供給する

    はよ食えや!

    View Slide

  15. わんこそばを食べる人とわんこそばを供給する人を考える
    (4/4)
    ● WSの実効消費速度の推移をグラフにしてみる
    0
    1
    5
    WS消費速度 / WS供給速度 (WS強度)
    実効WS
    消費性能
    WS消費速度 > WS供給速度
    WS消費速度 < WS供給速度
    はよWS食えやゾ
    ーン
    はよWS持ってこい
    ゾーン
    実効WS消費性能 = min(理論WS消費速度, 理論WS供給速度 * WS強
    度)
    1秒間に5杯持ってき
    て5杯食える
    Higher

    View Slide

  16. これはそのままCPUとメモリの関係になる
    ● CPUとメモリの関係に置き換える
    0 ?
    理論性能
    Flops per
    Byte (計算
    強度)
    実効性能
    [GFlops]
    CPU計算速度 > メモリI/Oバンド

    CPU計算速度 < メモリI/Oバンド幅
    はよ計算しろやゾ
    ーン
    はよデータ持ってこい
    ゾーン
    実効性能 = min(理論性能, 理論メモリI/O速度 * 計算強度)
    ここを知れば理論
    性能を出すために
    必要な計算強度が
    わかる
    Higher

    View Slide

  17. Intel Xeon Gold 6126の理論性能からバランスする計算強度を計算す

    ● CPU理論性能
    ○ 1 coreあたり: 83.2 GFlop/s
    ○ 1 socketあたり: 998.4 GFlop/s
    ● メモリI/O理論バンド幅
    ○ 2666 MHz x 8 Byte x 6 Channel = 128 GB/s
    ● CPU理論性能/メモリI/O理論バンド幅
    ○ 998.4 GFlop/s / 128 GB/s = 7.8 [Flop/Byte]
    ○ ※一般的にはByte/Flopsで表現する
    ■ B/F比率 = 1 / 7.8 = 0.128 [Byte/Flop]

    View Slide

  18. これはそのままCPUとメモリの関係になる
    ● CPUとメモリの関係に置き換える
    0
    998.4
    Flops per
    Byte (計算
    強度)
    実効性能
    [GFlops]
    はよ計算しろやゾ
    ーン
    はよデータ持ってこい
    ゾーン
    実効性能 = min(理論性能, 理論メモリI/O速度 * 計算強度)
    7.8
    「計算強度7.8の
    applicationを動
    かせば理論性能が
    出せる」とわかっ

    Higher
    CPU計算速度 > メモリI/Oバンド

    CPU計算速度 < メモリI/Oバンド幅

    View Slide

  19. ちょっと待て、計算強度7.8だと?
    ● 計算強度7.8のコードを書くのはめちゃくちゃ大変
    double a = a + b; // 2回読み込み 1回書き込み
    ● このコードだと計算強度は1 Flop / (8 * 3) Byte =
    0.04167
    ● 理論性能を出すために必要な計算強度の5.3%でしかなく
    全然性能を出せない。
    ● 計算強度7.8以上を達成するには↓みたいなコードじゃな
    いと無理(1回ロードしたbはレジスタに格納される想定)
    double a = b * … * b; // (合計125回bをかけ
    る)

    View Slide

  20. どうしてこうなった?
    ● 現代はCPUに比べてメモリが相対的に遅い時代
    https://www.extremetech.com/extreme/188776-how-l1-and-l2-cpu-caches-work-and-why-
    theyre-an-essential-part-of-modern-chips

    View Slide

  21. じゃあどうする?
    ● 色々あります解決策
    ○ 1 cycleあたりの計算量を増やしてスループットを上
    げる
    ■ 並列化してマルチコアを活用する
    ■ SIMD命令を活用する
    ○ メモリボトルネックを真っ当に解消する
    ■ CPUキャッシュを使ってバンド幅を向上させる
    ■ いいメモリを使ってバンド幅を向上させる

    View Slide

  22. CPUキャッシュはメモリの10倍から100倍高速
    ● 例えばスパコン富岳は高バンド幅なメモリとcacheを兼ね備えている
    https://www.hpci-
    Intel Xeon Gold 6126のBF ratioは
    0.128なので富岳のメモリ方がBF ratio
    が高い

    View Slide

  23. 簡単な実験: キャッシュヒット率を上げるとどのぐらい早くなるか(1/2)
    ● 正方行列 * 正方行列をnaiveに実装してみる
    for (i = 0; i < 1024; ++i)
    for (j = 0; j < 1024; ++j)
    for (k = 0; k < 1024; ++k)
    M3[i][j] += M1[i][k] * M2[k][j];
    elapsed time = 6.079248 sec, 0.353248 GFLOPS
    https://github.com/serihiro/optimization_experiments
    コンパイルオプション: -O0 -std=c11 -Wall -Wextra

    View Slide

  24. 簡単な実験: キャッシュヒット率を上げるとどのぐらい早くなるか(2/2)
    ● 正方行列 * 正方行列をキャッシュヒット率を
    高めるように実装してみる
    for (i = 0; i < 1024; ++i)
    for (k = 0; k < 1024; ++k)
    for (j = 0; j < 1024; ++j)
    M3[i][j] += M1[i][k] * M2[k
    elapsed time = 2.274633 sec, 0.944101 GFLOPS
    https://github.com/serihiro/optimization_experiments
    naiveに実装した時の3倍になった!
    for (i = 0; i < 1024; ++i)
    for (j = 0; j < 1024; ++j)
    for (k = 0; k < 1024; ++k)
    M3[i][j] += M1[i][k] *
    M2[k][j];
    elapsed time = 6.079248 sec, 0.353248
    GFLOPS
    コンパイルオプション: -O0 -std=c11 -Wall -Wextra

    View Slide

  25. 簡単な実験: (参考)手元の環境で一番はやくなったケース
    ● 正方行列 * 正方行列をblock化してキャッシュヒッ
    ト率を高めつつAVX2命令(256bit)を使用する
    block_size = 16;
    for (i = 0; i < 1024; i += block_size) {
    for (j = 0; j < 1024; j += block_size) {
    for (k = 0; k < 1024; k += block_size)
    {
    for (ii = i; ii < i + block_size; ++ii) {
    for (jj = j; jj < j + block_size; ++jj)
    {
    for (kk = k; kk < k + block_size;
    ++kk) {
    elapsed time = 0.172988 sec, 12.414061 GFLOPS
    naive実装の約35倍を達成した!(コンパイルオプションが違うので直接比較はできないけど)
    コンパイルオプション: -O3 -mavx2 -std=c11 -Wall -Wextra

    View Slide

  26. まとめ
    ● 現代はメモリよりもCPUがはるかに高速な時代
    ● 高いCPUに買い換えるだけでは性能は出ない
    ● CPUの性能を引き出すにはキャッシュヒット率
    を高めるコードを書くなどの人手による工夫が
    必要

    View Slide

  27. 併せて読みたい(CPU性能やコンピュータアーキテクチャに関する本)
    ● Samuel Williams, Andrew Waterman, and David Patterson. 2009. Roofline: an insightful visual performance model for
    multicore architectures. Commun. ACM 52, 4 (April 2009), 65–76. DOI:https://doi.org/10.1145/1498765.1498785
    ● Software Engineering Advice from Building Large-Scale Distributed Systems
    http://static.googleusercontent.com/media/research.google.com/en/us/people/jeff/stanford-295-talk.pdf
    ● コンピュータアーキテクチャ技術入門 https://gihyo.jp/book/2014/978-4-7741-6426-7
    ● パタヘネ5版 https://www.amazon.co.jp/dp/4822298426/
    ● スーパーコンピュータ (岩波講座 計算科学 別巻) https://www.amazon.co.jp/dp/4000113070/
    ● High Performance Computing: Modern Systems and Practices https://www.amazon.co.jp/dp/B077NZ4SW3/

    View Slide

  28. appendix 1
    ● 行列積の実験をしたCPUのspec
    ○ machdep.cpu.brand_string: Intel(R) Core(TM) i7-9750H CPU
    @ 2.60GHz
    ○ machdep.cpu.core_count: 6
    ○ machdep.cpu.cache.L2_associativity: 4
    ○ machdep.cpu.cache.linesize: 64
    ○ machdep.cpu.cache.size: 256

    View Slide