クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

命令を重ねて速く動かす(パイプライン)

このレッスンのあとで: パイプラインがプロセッサを速くする仕組みと、それを止めるものを説明することができる。

55分のレッスンコマンド9件コンパイラとアーキテクチャのラボ:gcc、flex、bison、RISC-V を1台の VM で

5人で1分に1杯のラーメン

小さなラーメン店で、店主が1人で、注文、麺ゆで、盛りつけ、運ぶ、会計をしています。お客は1杯を5分待ちます。

そこで4人を雇い、1人に1つの仕事を任せました。1杯を作るのには、今も5分かかります。けれど、できあがった1杯が1分ごとに出てくるようになりました。プロセッサも、命令について同じことをします。

このレッスンのゴール

メモ

パイプラインがプロセッサを速くする仕組みと、それを止めるものを説明することができる。

キーワード

ことばいみれい
パイプライン複数の命令の段階を、別々の段で同時に進めること
ステージパイプラインの1つの段。1クロックかかるEX
ハザード次の命令が予定どおりに進めなくなる原因
ストールある段が待つだけで、仕事をしない1サイクル
フォワーディング書き戻す前の結果を、次の命令へ直接渡すこと
分岐予測分岐がどちらへ進むかを、決まる前に推測すること

学生が入力するセルは、このプレビューでは空白です。

5つのステージに、5つの命令

基本的な RISC-V のパイプラインには、5つのステージがあります。IF は命令の取り出し、ID はデコードとレジスタの読み出しです。EX は計算、MEM はメモリの読み書き、WB はレジスタへの書き戻しです。

どのステージも1クロックかかります。ある命令が EX にいるあいだ、次の命令は ID に、その次は IF にいます。だから最大5つの命令が同時にプロセッサの中にあります。

例: ハザードのない3つの命令

命令1234567
addi t0, zero, 4IFIDEXMEMWB
addi t1, zero, 5IFIDEXMEMWB
addi t2, zero, 6IFIDEXMEMWB

学生が入力するセルは、このプレビューでは空白です。

アーキテクチャのフォルダへ移る

コマンド
cd ~/arch

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

1つの命令は速くならないのに、速い

1つずつ順に行うと、5サイクルの命令60個に300サイクルかかります。パイプラインでは、最初の1個が5サイクルで終わり、あとは1サイクルごとに1個ずつ終わります。だから60個で 5 + 59、つまり64サイクルです。

1つの命令が始まってから終わるまでは、今も5サイクルです。増えたのは、1サイクルに終わる命令の数です。ただし、それは命令を待たせるものがないあいだだけです。

まだできていない結果

ハザードとは、次の命令が予定どおりに進めない理由です。よくあるのはデータハザードで、前の命令がまだ書き終えていないレジスタを、次の命令が必要とする場合です。

何も工夫しなければ、値が書き戻されるまでパイプラインはストールします。フォワーディングを使うと、EX の答えを次の命令へ直接渡せるので、待ちのほとんどが消えます。ロードは別です。値は MEM のあとでしかできないので、すぐ次の命令は1サイクル待ちます。

例: このモデルのストールの数

前の命令使う命令との距離フォワーディングなしフォワーディングあり
add か addi1つ前20
add か addi2つ前10
lw1つ前21
lw2つ前10
どれでも3つ以上前00

学生が入力するセルは、このプレビューでは空白です。

ロードユース・ハザードのあるプログラムを書く

コマンド
printf '.globl _start\n_start:\n  addi sp, sp, -16\n  li t0, 20\n  sw t0, 8(sp)\n  lw a0, 8(sp)\n  add a0, a0, a0\n  li a7, 93\n  ecall\n' > use.s

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

アセンブルする

コマンド
riscv64-linux-gnu-as use.s -o use.o

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

リンクする

コマンド
riscv64-linux-gnu-ld use.o -o use

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

エミュレータで実行する

コマンド
qemu-riscv64 ./use

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

終了ステータスを読む

コマンド
echo $?

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

機械語を読む

コマンド
riscv64-linux-gnu-objdump -d use

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

「パイプラインにすると、1つ1つの命令が速く終わる」と考える人が多くいます。そうではありません。どの命令も、今も5つのステージを全部通ります。パイプラインは、1サイクルに終わる命令を増やします。ストールはその得を捨てるので、命令の順番が大切になります。

すき間はコンパイラが埋める

コンパイラは、ストールの決まりを知っています。ロードのすぐあとに、その値を使う命令が来るとき、値を使わない別の命令を探して、あいだへ移します。

次の Run は、ラボの loop.c を RISC-V 向けにコンパイルします。列ごとに足すループ .L9 を見て、ロードと、それを使う add のあいだに何があるかを探しましょう。

loop.c を基本の RISC-V にする

コマンド
riscv64-linux-gnu-gcc -O2 -march=rv64gc -S loop.c

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

列ごとに足すループ

コマンド
grep -A 4 'L9:' loop.s

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

分岐の行き先を推測する

分岐はコントロールハザードを起こします。EX で条件が決まるまで、パイプラインは次に何を取り出すか分かりません。分岐のたびに待つと、サイクルが無駄になります。

そこでプロセッサは分岐予測を使います。推測して、そのまま進めるのです。当たれば損はなく、外れれば取り出した仕事を捨ててやり直します。ループの最後の bne はほとんど毎回戻るので、推測しやすい分岐です。

さらに挑戦

次のプログラムがあります。lw t0, 0(a0)、add t2, t0, t0、lw t1, 4(a0)、add t3, t1, t1、addi a0, a0, 8。課題の関数で、フォワーディングありのストールを数えてください。

次に、答えを変えずにストールが0になるよう、5行を並べかえます。addi a0, a0, 8 を前へ動かしてはいけない理由も説明しましょう。

このラボとソースについて: コンパイラとアーキテクチャのラボ:gcc、flex、bison、RISC-V を1台の VM で

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。