Code jp2015 cpuの話

Preview:

Citation preview

CPUとプログラムCode 2015 in 定山渓 発表資料

niiyama.sh

CPUとプログラム• 本日は以下の4つのテーマについてお話しします

• キャッシュ

• パイプライン

• スーパースカラー

• マルチコアとハイパースレッディング

• 過去に発表済みの資料、今後の発表予定資料からの抜粋になります

• http://www.slideshare.net/dorniiyama

1. キャッシュ

1.1 ハードウェア構成• 左図の構成で説明を進めます

• CPUによって実装が異なるので、機種固有の説明は省きます。

• 私なりに考えた「キャッシュの基礎を理解する」ための仮想CPUです。

• 「そこそこ」ワーストケースで考えます。

• L1、L2キャッシュはミスヒット。

• 細かい用語は後ほど。

ChipProcessor

CPU Core

L2 Cache

Mem Ctrl

DRAM

PCIe

HW…

MMU

L1 Cache

1.2 メモリからデータを読み出してみよう

• 例えば、以下のC言語プログラム上は左の赤枠のような命令に置き換えられます。

• ※ARM命令の場合

int hoge = *__bss_start__;

1.3 その前に…レジスタって?

• パソコン初心者向け説明

• CPUはメモリに情報を置く

• メモリに入りきらないときはHDDに退避

CPU

DRAM HDD

実はCPUはメモリに直接アクセスできません

1.4 レジスタ=CPU内部メモリ• CPUはレジスタのデータに対してのみ演算可能。

• メモリの値を直接制御できない。

• データ読み出しはメモリからレジスタに転送し、レジスタを読む。

• データ書き込みはレジスタに書き、レジスタの内容をメモリに転送する。

CPU

DRAM HDD

演算回路

レジスタレジスタ

キャッシュ

1.5 LEVEL 1 CACHE• CPUが最初にアクセスするメモリ領域

• 一番高速&一番サイズが小さいメモリ

• CPUクロックと同一クロックで読み書き可能

• 数k~数100kBytes程度

MMU

物理アドレスLevel 1 Cache

データ物理アドレスデータ物理アドレスデータ物理アドレス

データ物理アドレス

Miss Hit Hit

1.5.1 DETAILS OF CACHE

Level 1 Cache

アドレス00000000000000000 000000000 000000

データ(1 word)00000000 00000000 00000000 00000000

Cache Entry Table

タグ(上位アドレス) データタグ(上位アドレス) データタグ(上位アドレス) データ

タグ(上位アドレス) データ

=?

データ1

1 word (4bytes)

データ2

データ3

データn①

②③

01

511

1.5.2 N-WAY ASSOCIATIVE CACHE

• nウェイアソシアティブ

• キャッシュが複数(n)毎

• 同一インデックスに対して複数エントリを持つことでヒット率向上。

Cache Entry TableCache Entry Table

Cache Entry TableCache Entry Table

タグ(上位アドレス) データタグ(上位アドレス) データタグ(上位アドレス) データ

タグ(上位アドレス) データ

アドレス000000000000000000 000000000 00000

=?Hit or Miss ?

1.5.3 MISS HIT!• キャッシュ内のデータをライトバック

• データを読み込むためのキャッシュエントリを確保するため。

• LRU/ランダム/ラウンドロビン

• L2キャッシュから読み出し

• 読み出し終わるまでCPUはストール(パイプライン完全停止)

L2 Cache

Level 1 Cacheデータ物理アドレスデータ物理アドレスデータ物理アドレス

データ物理アドレス

1.6 LEVEL 2 CACHE

About Level 2 Cache

Processor

CPU Core

L2 Cache

Mem Ctrl

DRAM

PCIe

HW…

MMU

L1 Cache

1.6.1 LEVEL2 CACHESEQUENCE

Address

確定Tag

出力比較

Data出力

確定

Bus ClockL1 Cacheがアドレスを出力

L2 cacheがアドレスを確定

Tag読み出し制御

Tagが出力される

Tag比較 -> Hit !

Data読み出し制御Dataが出力される

L1 Cacheへデータを返す

読み出しに8 Clock必要

1.7 DYNAMICRANDOMACCESS

MEMORYAbout DRAM

Processor

CPU Core

L2 Cache

Mem Ctrl

DRAM

PCIe

HW…

MMU

L1 Cache

1.7.1 外部デバイスアクセス

• DRAMは外部デバイス

• 制御用のHWが必要

• 非常に低速

• CPUクロックの5~10分の1

1.7.2 DDR3-SDRAM READ TIMING参考資料:

http://www.samsung.com/global/business/semiconductor/file/product/ddr3_device_operation_timing_diagram_rev121.pdf

10 Clock@8wordバーストリード(キャッシュ1ラインフィルに相当)

1.7.3 DDR3-SDRAMSTATE CHART

• DDR3-SDRAMの内部状態遷移図

• HW IPとして提供されることが多いのでこれを理解している人は少ないと思います。

• 重要キーワード

• ModeRegister

• プリチャージ

• リフレッシュ

1.7.4 DRAMとキャッシュ• DRAMはキャッシュに接続される前提で機能実装

• ラインフィルに必要なバーストモード

• 全てシングルアクセスすると致命的に遅い

• 要求されたデータから順にリード可能

Single Word Read = 7 Clock/Word

8 Words Burst Read = 1.25 Clock/Word(10 Clock / 8 Words)

DRAMとキャッシュは密接な関係にあります

1.8 ヒット率とアクセス時間に関する考察

Consideration

Processor

CPU Core

L2 Cache

Mem Ctrl

DRAM

PCIe

HW…

MMU

L1 Cache

1.8.1 CPUの待ち時間• 今までのワーストケースで1wordを読み出す時間を計算

• tL1 = 1 Clock• tL2 = 16 Clock (8 × 2CPUの半分のクロックで動作と過程)

• tDDR3 = 28 Clock (7 × 4 CPUバスの半分のクロックで動作と過程)

• tAllMiss = tL1 + tL2 + tDDR3 = 45 [Clock]• CPUやシステムによって上記の値は全然違います。

• 実際の値を適用すると、もっとすごいことになります。• http://www.7-cpu.com/cpu/Cortex-A9.html

1.8.2 キャッシュヒット率を考慮

• キャッシュヒット率(仮定)• L1、L2ともにhit率 = 90.0%と仮定。

• Avarage Access Time = tL1×0.9 + tL2 × (1 - 0.9) + tDDR3 × (1 - 0.9) × 0.9 = 4.22[clock]

• バスクロックが遅いと?• 同一クロックであっても外部バス速度が遅いCPUがあります。

• 例:Core2Duo 667MHz、Celeron 533MHz

• Avarage Access Time = tL1×0.9 + (tL2 × (1 - 0.9) + tDDR3 × (1 - 0.9) × 0.9) × 667/533 = 5.05[clock]

• ざっくり計算です。

キャッシュやメモリ制御回路が大部分を占めます。

1.9 実験Study

Processor

CPU Core

L2 Cache

Mem Ctrl

DRAM

PCIe

HW…

MMU

L1 Cache

• Intel Performance Counter Monitorで実験してみましょう。

• 通常のループ

• 残念なループ

• ブロッキング

• アンローリング

• 行列計算

• フォールスシェアリング

1.9.1 通常のループ• src[row] += dst[row][col]

• dstのサイズ>>キャッシュ

• キャッシュ1ラインのワード数ごとにキャッシュミスヒット。

0

1

dst

9

row0 0

1

src65535

1 0

9 65534

9 65535

row col

キャッシュサイズ

for (unsigned long row = 0; row < ROW_SIZE; row++) { for (unsigned long col = 0; col < COL_SIZE; col++) { *(dst + row) += *(src + row * COL_SIZE + col); } }

1.9.2 残念なループ• rowのインクリメントを先にする。

• インクリメント>>キャッシュ

• 毎回ミスヒットする。

0

1

dst

9

row0 0

1

src65535

1 0

9 65534

9 65535

row col

キャッシュサイズ

for (unsigned long col = 0; col < COL_SIZE; col++) { for (unsigned long row = 0; row < ROW_SIZE; row++) { *(dst + row) += *(src + row * COL_SIZE + col); } }

1.9.3 ブロッキング• キャッシュサイズの範囲内で一通り処理する。

• 終わったら次の領域に移る。

• ミスヒットが格段に減る。for (int Blk = 0; Blk < COL_SIZE; Blk += BLKSIZE) { for (int row = 0; row < ROW_SIZE; row++) { for (int col = Blk; col < Blk + BLKSIZE; col++) { *(dst + row) += *(src + Blk * BLKSIZE + col); } } }

0

1

dst

9

row0 0

1

src65535

1 0

9 65534

9 65535

row col

キャッシュサイズ

ブロックサイズ

1.9.4 ループアンローリング• ループ処理を展開して分岐命令を削減

• 展開しすぎるとプログラムが大きくなり、命令キャッシュミスが増える

for (unsigned long row = 0; row < ROW_SIZE; row++) { for (unsigned long col = 0; col < COL_SIZE;) { *(data_dst + row) += *(data_src + row * COL_SIZE + col++); *(data_dst + row) += *(data_src + row * COL_SIZE + col++); *(data_dst + row) += *(data_src + row * COL_SIZE + col++); …略… *(data_dst + row) += *(data_src + row * COL_SIZE + col++); } }

処理インクリメント分岐判定処理インクリメント分岐判定

処理インクリメント分岐判定

処理インクリメント

処理インクリメント

処理インクリメント

……

実行命令数が減る=処理時間も減る

プログラムサイズは増える

1.9.5 行列計算• 普通にアルゴリズムを書くと、先ほどの「普通のループ」と「残念なループ」の組み合わせになる。

• 片方をわざと行列を入れ替えて定義する

int A[row][col]; int B[col]row];

int A[row][col]; int B[row][col];

1.9.6 フォールスシェアリング• 複数のスレッドが同一キャッシュラインのデータにライトアクセスするときに発生し得る問題。

Core1 Core2

Cache Line Cache Line

DRAM

Core 1とCore2は異なるアドレスにライトする。

アドレスは異なるが、キャッシュラインは同一。

Core1がデータを書き換える。

他コアもキャッシュしているため、DRAMにライトバック。

Core2はDRAMとキャッシュが不一致のため、キャッシュされていたデータは「無効(データ無し)」とする。

Core2がデータを書き換える。

ミスヒットが発生し、DRAMからデータを読み出す。

1.9.7 フォールスシェアリング解決策

• 複数のスレッドで共有する必要の無いデータはアドレスが64バイト以上離れるようにする。

Core1 Core2

Cache Line Cache Line

DRAM

void worker_thread1(void) { for (int i = 0; i < MAX; i++) dstArea[0] += srcArea[i]; }

void worker_thread2(void) { for (int i = 0; i < MAX; i++) dstArea[1] += srcArea[i]; }

void worker_thread3(void) { for (int i = 0; i < MAX; i++) dstArea[64] += srcArea[i]; }

thread1と2はフォールスシェアリングthread1と3は無し

1.9.8 実験結果:ループ• 「残念なループ」はキャッシュヒット率が低く、DRAMアクセスが多い。

• 「ブロッキング」はDRAMアクセスが少ない。

• 簡単なプログラムのため差が出にくかったかも。

• テストプログラム以外のプロセスのカウント値も含まれていると思われます。

時間[S] L1 HIT DRAMREAD

普通 1.68 99.82 5542MB

残念 14.09 89.54 41100MB

ブロッキング

1.63 99.95 283MB

アンローリング

1.62 99.91 5460MB

1.9.9 実験結果:行列計算/シェアリング

• 行列を入れ替えるとキャッシュヒット率が向上しDRAMアクセスが減る。

• フォールスシェアリングを回避することによりDRAMアクセスが半分になっている。

• 「ループ」、「行列計算」、「シェアリング」はそれぞれ異なるテストプログラムを実行しています。

時間[S] L1 HIT DRAMREAD

通常 13.33 92.30 49.8GB

行列入れ替

2.06 99.75 10.7GB

時間[S] L1 HIT DRAMREAD

FALSESHARE 10.54 95.42 926MB

NONESHARED 4.62 98.77 421MB

2. パイプライン並列処理の話をする前に…

2.1 入力と出力• 装置には必ず「入力」、「出力」があり、「入力」から「出力」が得られるまでに「時間」が必要となります。

• CPUも「命令」を入力とし、「データ」を出力します。

装置お金 ジュース

CPU命令データ

データ

2.2 処理時間• 入力してから出力が得られるまでの時間を処理時間と定義します。

• CPUの場合、メモリから命令を読み出し、結果を書き込むまでの時間をクロック数で表現します。

• これをCPI(Clock Per Instruction)と呼びます。

メモリ

CPU

t[clocks]

2.3 CPI値の例CPI

8086 15

80286 6

80486 1.7

Xeon 0.25CPI値は実行するプログラムにもよって異なるので、あくまでも参考値です。(参考文献2と5より)

2.4 処理時間(昔のCPU)

CPU

読み出し

デコード

書き込み

レジスタ

メモリ

実行

ちょーざっくり

一つの命令が終わってから次の命令を読み出す。

一つの命令をCPU内部で複数の命令(マイクロコード)に分

割して実行する。

2.5 無駄な時間(昔のCPU)

CPU

読み出し

デコード

書き込み

レジスタ

メモリ

実行

ちょーざっくり動作中の一カ所を除き、他の回路は何もしていない。

2.6 RISCの登場(ざっくり)

CPU

読み出し

デコード

書き込み

レジスタ

メモリ

実行

動作していないのはもったいない。次の命令を読んじゃえ!

メモリは遅いからキャッシュを付けよう。

マイクロコードはやめてハードで実装しよう

2.7 パイプラインの例• CPUの命令実行部分を機能的に分割したもの

• IF:命令フェッチ

• RF:命令デコード

• EX:命令実行

• MEM:保存先計算

• WR:保存(メモリ/レジスタ)

IF RF EX ME WR

この順で命令を実行 5クロックで1命令を実行

2.8 命令の同時実行

IF RF EX ME WR

IF RF EX ME WR

IF RF EX ME WR

IF RF EX ME WR

IF RF EX ME WR

IF RF EX ME WR

命令1命令2

命令6

同時に5命令を実行可能 毎1クロック毎に1命令実行完了

2.9 パイプラインの限界• パイプラインとキャッシュにより、理論上は最速で1クロックあたり1命令実行。=1.0[IPC]

• IPC = Instruction Per Clock

• どんなに工夫してもIPCは1.0の壁を超えることは不可能。

2.10 IPCを1.0以上にする解決策は?

• 実行回路を複数用意する

• スーパスカラー

• マルチコア

• ハードウェアスレッディング

3. スーパースカラー

実行ユニット並列化

3.1 スーパスカラーの概念

• CPUコア内部にパイプラインを複数用意

• 命令を同時実行することで高速化

• ソフトウェアからは並列実行数不明

IF RF EX ME WR

パイプライン1段

パイプライン2段IF RF EX ME WR

IF RF EX ME WR

RAM(Cache)Register

RAM(Cache)Register

3.2 スーパースカラーの実際1

Inst Decoder

RF EX ME WR

Inst Cache Inst Decoder

Inst QueueInst Inst Inst Inst

RF EX ME WR

Data CacheRegisterRegister

• スーパスカラーの実際のパイプライン• 複数命令を同時に読み出してデコード• 複数命令をキューに入れる• 依存性が無い命令を同時実行

全部が複数あるわけではない

3.3 スーパースカラーの実際2• EXは対称ではない

• SandyBridgeは演算が3way、メモリ制御が3way

• 同時実行する可能性が高い回路のみ複数実装

引用元:http://pc.watch.impress.co.jp/docs/column/kaigai/20130602_601851.html

4. マルチコア複数CPUによる同時実行

4.1 マルチコアにする目的• CPUを複数用意する目的

• 処理の高速化

• スレッドやプロセスを同時実行

• 消費電力を抑える

• 消費電力を押さえつつ高速化

汎用PCで一般的な対象マルチプロセッサ(SMP)について説明します

4.2 ソフトウェアから見た問題• 同期

• 同一のリソース(メモリ領域)に対するアトミックなアクセス

• キャッシュコヒーレンシ

• それぞれのコアがキャッシュを持つため、一貫性を保つ仕組みが必要

4.3 同期の問題• セマフォ等、フラグ状態による排他制御が必須

• シングルプロセッサでは割り込み禁止で実現できる。

• マルチコアはHW支援必須。

• 共有フラグにアクセスするときにHWがLock制御

flag = 0:アクセス可能 flag = 1:アクセス不可

CPU1 CPU2

Memory

Shared Data Flag

4.4 同期問題の解決• Lock信号を用意

• アトミック命令実行時にLock信号をアサート(有効化)する。

• L1キャッシュにアクセスするときはアサートしない。(コヒーレンシ制御で解決)

CPU1 CPU2

Memory

Shared Data Flag

Lock

4.5 キャッシュコヒーレンシの問題

• 同じ領域を複数のコアがキャッシュしている

• 一方のコアがデータをライトすると不整合が発生する。

• リードは問題無い。

• キャッシュコヒーレンシプロトコルにより不整合状態を解決する

CPU1

Memory

Shared Data

L1 cache

Shared Data

L1 cache

Shared Data

CPU2

4.6 コヒーレンシプロトコル• MESI/MOESIプロトコル

• M:Modified• 自分だけがキャッシュ+DRAMと不一致

• O:Owned• 他CPUと同内容をキャッシュ+DRAMと不一致

• E:Exclusive• 自分のみがキャッシュ

• S:Shared• 他CPUと同内容をキャッシュ+DRAMと一致

• I:Invalid• 無効(キャッシュしていない)

MO

E S

I

5. ハードウェアスレッディングスーパスカラーの効率化

5.1 スーパスカラーとマルチコアの問題

• 複数のパイプラインが有効活用されない

• 命令の依存性が高く同時実行が難しい

• 回路規模が大きくなる

• ハードウェアのコスト上昇

• 消費電力上昇

5.2 ハードウェアスレッディング• ソフトウェアから見たハードウェアリソースを複数用意

• ソフトウェアは複数のCPUと認識して処理を行う

• ハードウェアが複数スレッドの命令を交互に実行

• OSが行うプロセスス1ケージューリングをハードウェアが実行するイメージ

CPU

RegIRQ

PIPE LINE

CPU

RegIRQ

PIPE LINE

RegIRQ

5.3 HTのイメージ• OSは複数CPUとみなしてスレッドをスケジュール

• 所定のタイミングで実行するスレッドを切り替える

• レイテンシの長いイベント

• キャッスミスなど

• 一定間隔で交互に

5.4 HTの効果があるパターン• 各スレッドでリソースの競合が発生しない

• 実行ユニット(以下の図ではALUは効果あり)

• メモリ

6. 同時実行のまとめ

それぞれの特徴を整理

6.1 まとめ• 同時実行するための仕組みには複数の実現手段

• 実行ユニット、物理コア、レジスタを複数用意

• 実現手段により特徴が異なる

• それぞれに特徴があり、組み合わせて性能向上を図る

7. 同時実行の実験

同時実行の実験

7.1 FALSE SHARING• 2つのスレッドが異なるメモリを使用しているにも関わらず、キャッシュの構造上、メモリの共有状態にあることを言う

• どちらかのスレッド(CPU)がメモリを書き換えると、もう一方のスレッドのキャッシュが無効化される

• キャッシュコヒーレンシ

Core1 Core2

Cache Line Cache Line

DRAM

異なるアドレスだが、 キャッシュは同一領域管理

7.2 FALSE SHARINGとHT

• 実行する物理コアが異なる

• False Sharingが発生

• 実行する物理コアが同一

• False Sharingは発生しない

Core1 Core2

Cache Line Cache Line

Core1 Core2

Cache Line

7.3 FALSE SHARING実験• 実験

• 2つのスレッドが異なるアドレスにデータを書き続ける

• 隣り合ったアドレス、64バイトずらしたアドレスへの書き込みの違い

• 異なる物理コア、同一物理コア内の異なる論理コア

アドレスオフセット/コア 同一物理コア 異なる物理コア

1バイト 2.5[s] 3.7[s]

64バイト 2.5[s] 1.6[s]

7.4 PRODUCER CONSUMERTHREADING MODEL

• Producer : データ生成

• Consumer : データ使用

• 例:

• P : ファイル読み出し

• C : 動画デコード

P C

P C

P C

P C

P P

C C

P P

C C

Model 1

Model 2

time

Thread 1

Thread 2

Thread 1

Thread 2

7.5 PRODUCER CONSUMER実験

• Model1とModel2の比較

• Model1はキャッシュが同一

• Model2はキャッシュが異なるため、コヒーレンシ制御が多発

MODEL/コア 同一論理 同物理 異論理

異物理

MODEL13.6[s] 2.4[s] 1.9[s]

99.9[%] 99.9[%] 99.9[%]

MODEL23.3[s] 2.4[s] 2.1[s]

99.9[%] 99.9[%] 98.9[%]

7.6 PARALLELISM OF HARDWARE THREADING

• Hyper Threadingは実行ユニットが複数あるときに効果がある

• 例:

• ALUは複数の同時実行可能

• それ以外は1命令のみ

ALUは3つあるが、 Divide(除算)は1つ

7.7 HARDWARE THREADINGとSUPERSCALER実験

• 実験1

• 加算だけを行うスレッドを2つ実行

• 実験2

• 除算だけを行うスレッドを2つ実行

スレッド/コア 同一 論理

同一物理 異論理 異物理

加算 3.4[s] 1.8[s] 1.9[s]

除算 4.2[s] 3.4[s] 2.2[s]

参考文献• アーキテクチャ全般

• 1. David A.Patterson/John L.Hennessy; パターソン&ヘネシー コンピュータの構成と設計 第4版, 日経BP

社, 2011年.

• 2. 中森 章; マイクロプロセッサ・アーキテクチャ入門, CQ出版, 2004年.

• 3. 安藤壽茂; コンピュータアーキテクチャの話, マイナビニュース

• 実例

• 4. Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3A: System Programming Guide, Part 1

• 5. Intel® 64 and IA-32 Architectures Optimization Reference Manual

• 6. Performance Analysis Guide for Intel® Core™ i7 Processor and Intel® Xeon™ 5500 processors

Recommended