Pentium4再考・速くなる理由が違う!?





では、Hyper-Threadingテクノロジを導入した次期 Pentium4での処理を時系列で追ってみよう。

スレッド・ブルー
実行ユニット1 命令12 命令4
実行ユニット2 命令11 命令6 命令3
実行ユニット3 命令9 命令5 命令2
実行ユニット4 命令10 命令7
実行ユニット5
実行ユニット6 命令8 命令1


スレッド・グリーン
実行ユニット1 命令11 命令3
実行ユニット2 命令10 命令6
実行ユニット3 命令8
実行ユニット4 命令12 命令5 命令1
実行ユニット5 命令9 命令7
実行ユニット6 命令4 命令2


第1サイクル
命令のトレースキャッシュからの読み込みを行う。命令は1サイクルで3μOPS読み込まれるわけであるから、 スレッド・ブルーの命令1,2,3がトレースキャッシュから読み込まれる。 命令1と2は同時実行可能であるが、3は 依存関係により不可能なので、リザーブされても命令1,2とはステートが違う。 ここでは、命令発行部に近い位置に記入されている命令が、より発行に近いステートに ある事を表現していると考えていただきたい。
ステージ リザーブ リザーブ 発行
実行ユニット1
実行ユニット2 命令3
実行ユニット3 命令2
実行ユニット4
実行ユニット5
実行ユニット6 命令1


第2サイクル
スレッド・グリーンの命令が3つトレースキャッシュから読み込まれる。同時に、発行準備が整った スレッド・ブルーに属する命令1,2が発行され、実行ユニットに送られる。
ステージ リザーブ リザーブ 発行
実行ユニット1 命令3
実行ユニット2 命令3
実行ユニット3 命令2
実行ユニット4 命令1
実行ユニット5
実行ユニット6 命令2 命令1


第3サイクル
スレッド・ブルーの命令3とスレッド・グリーンの命令1,2が 発行可能となり、実行ユニットに送られる。同時にスレッド・ブルーの 命令4,5,6がトレースキャッシュからの読み込まれる。
ステージ リザーブ リザーブ リザーブ 発行
実行ユニット1 命令4 命令3
実行ユニット2 命令6 命令3
実行ユニット3 命令5
実行ユニット4 命令1
実行ユニット5
実行ユニット6 命令2


第4サイクル
以下、同様の処理を次々と命令が無くなるまで行う。
ステージ リザーブ リザーブ リザーブ 発行
実行ユニット1 命令4 命令3
実行ユニット2 命令6
実行ユニット3 命令6 命令5
実行ユニット4 命令5
実行ユニット5
実行ユニット6 命令4


第5サイクル
ステージ リザーブ リザーブ リザーブ 発行
実行ユニット1 命令4
実行ユニット2 命令6
実行ユニット3 命令9 命令6
実行ユニット4 命令7 命令5
実行ユニット5
実行ユニット6 命令8 命令4


第6サイクル
ステージ リザーブ リザーブ リザーブ 発行
実行ユニット1
実行ユニット2 命令8 命令6
実行ユニット3 命令9 命令6
実行ユニット4 命令7 命令5
実行ユニット5 命令9 命令7
実行ユニット6 命令8


第7サイクル
ステージ リザーブ リザーブ リザーブ 発行
実行ユニット1 命令12
実行ユニット2 命令11 命令8 命令6
実行ユニット3 命令9
実行ユニット4 命令10 命令7
実行ユニット5 命令9 命令7
実行ユニット6 命令8


第8サイクル
トレースキャッシュからの読み込み作業はすべて終わったので、 あとはリザベーションユニット中に残っている命令を、 ステート順に実行してゆくだけだ。 残っているのは4サイクル分である。
ステージ リザーブ リザーブ リザーブ リザーブ 発行
実行ユニット1 命令11 命令12
実行ユニット2 命令10 命令11 命令8
実行ユニット3 命令9
実行ユニット4 命令12 命令10
実行ユニット5 命令9 命令7
実行ユニット6 命令8


というわけで、処理には12サイクル必要だった。 キャッシュからの読み込み時間は無視する約束だったので、 1サイクル差し引いて、計11サイクルである。

発効された命令を時系列で並べると、前回掲載した次期Pentium4の表になる。

次期Pentium4の場合(推測)
実行ユニット1 命令11 命令12 命令4 命令3
実行ユニット2 命令10 命令11 命令6 命令3
実行ユニット3 命令8 命令9 命令6 命令5 命令2
実行ユニット4 命令12 命令10 命令7 命令5 命令1
実行ユニット5 命令9 命令7
実行ユニット6 命令9 命令4 命令2 命令1


理想状態と比較するとあまりにも効率の悪い状態である。 なぜこのような事になったのであろうか?

たるさんが推測する理由はこうである。 命令のデコード能力(Pentium4ではトレースキャッシュの読み込み能力)と 実行ユニットの処理能力の関係を考えていただきたい。 両者はリザーベーションユニットで隔てられており、 Out-of-Order機構がその中から同時実行可能な命令を抽出する。

では、トレースキャッシュからの読み込み能力と、 実行ユニットでの発行能力は、どのような関係が最適なのであろうか。

まず、同時実行命令数を高めるためにはリザーベーションユニットに 多数の命令が蓄えられている事が重要だ。 この中の命令は同時実行予備軍だから、並列実行の候補は多い程良い。 (ちなみに、Pentium4ではリオーダーバッファ数は126個である。)

だから、Pentium4ではトレースキャッシュからの 命令読み込み能力が重要となる。 読み込み能力が低ければ、バッファ内の命令を使い切ってしまって、 同時実行の候補を探せなくなってしまうからである。

かといって、読み込み能力だけが突出しても、命令がバッファから 溢れてムダになってしまう。 たるさんが考える最適な比率とは、平均的にパイプラインが破棄される までの命令数を実行する間に、リオーダーバッファに 十分な命令を溜めることができる範囲での、最低限の 命令供給能力がベストであろう。

このため、現行のPentium4では平均2.1μOPS/サイクルの 実行ユニット処理能力に対し、トレースキャッシュは3μOPS/サイクルを 供給できる体制を整えている。 この辺りの比率が、一番効率がよいと読んでの事だろう。

ところが、Hyper-Threadingテクノロジが導入されると、 このバランスが一気に崩れてしまう。 異なるスレッド間の命令は無条件で同時実行できるため、 平均同時実行命令数の増大により、 実行ユニットの処理能力だけが増えてしまうのである。 命令の読み込み能力は増えない (あくまで予想だけど...)のに、である。

Hyper-Threadingテクノロジ導入による性能向上は、メーカー発表によると 30%だそうだ。この場合、平均並列命令実行数は2.1μOPS/サイクル×1.3倍= 2.73μOPS/サイクルとなる。 これはトレースキャッシュの命令読み込み能力(3μOPS/サイクル)と ほぼコンパラで、これではリオーダーバッファに命令が溜まるはずがない。

この場合、新たに読み込まれた命令は、 ただその日暮らしに並列化されることなくそのまま実行されてしまう。 実行ユニットはOut-of-Orderユニットから十分な並列性 を引き出してもらえないが故に、ヒマを持て余すのである。 これが、上記の状態である。

このようにして、現状のNetBurstアーキテクチャでは、 パイプラインの実行ユニットの稼働率を高めるという手法では それほど能力が向上しないと、たるさんは予想するわけである。

考えてもみていただきたい。 もし、実行ユニットに命令を効率的に詰めることがHyper-Threadingテクノロジの原理ならば、その潜在能力の上限は、 トレースキャッシュの読み込み能力である3μOPS/サイクルを、 平均実行命令数2.1μOPS/サイクルで割った値、 すなわち43%UP以上にはならない。 もし仮に2スレッド同時実行で実行ユニットの処理能力が2倍 (4.2μOPS/サイクル)になってとなっても、 デコード(トレースキャッシュの命令読み込み)が追いつかない。 つまり、原理上これ以上高速化できないのである。

もしこの部分のボトルネックを解消しようと思ったら、 次期Pentium4ではトレースキャッシュからの命令読み込み能力を 強化しなければならないだろう。 現状でマルチスレッド処理能力(パイプラインの実行ユニットの稼働率を高めるという手法)だけを与えても、効果は薄いのではあるまいか?

実際、上記のテストでは能力向上は1サイクル(8.3%)しかなかった。 しかし、 投機的マルチスレッドの衝撃、その1で述べた方法では、能力向上は29.5%に達したのである。

以前このサイトでたるさんがUPした高速化手法は下記の方法による。
1.分岐予測のミスなどでパイプラインの内容が破棄される場合に 1スレッド当たりの破棄ステージ数を減らす。
2.キャッシュミスでの待ち時間を減らしたりする。
(1スレッドから見た場合の擬似的な待ち時間だが...)

従って、トレースキャッシュからの命令読み込み能力がボトルネックになる 可能性はずっと低いのである。 この場合は、命令読み込み能力の制約から逃れられるので、潜在能力は 6命令同時発行を平均実行命令数2.1で割った値、すなわち186%にもなる。

Pentium4は他のCPUよりも、分岐予測ミスやキャッシュミスのペナルティーが でかい上に、トレースキャッシュの容量が12KμOPS (通常の1次キャッシュ換算で9.6KBと推測)と少ない。 このため、他のCPUよりも分岐予測ミスやキャッシュミスのペナルティー減の 効果が大きく効くと予想される。

と言うわけで、雑誌説明とは異なり、Hyper-Threadingテクノロジの本質は キャッシュミスや分岐予測ミスのペナルティー減にあると考えるのである。 もし、雑誌記事が本当に正しいならば次期Pentium4のトレースキャッシュ 読み込み能力は必ず強化されていることだろう。

ただし注意して欲しいのは、両者の技術手法は決して排他的ではないということだ。 今後の改良によって、技術的には融合し、いずれ発展的に解消すると考えられる。 現状では、上記の通りデコード能力の関係で、同時実行命令数を増やす 事による高速化効果は少ないと予想するのであるが、 新コアとなってはじめからこのボトルネックを解消させたCPUでは、 この問題は発生しないだろう。

最後に、もし十分な数の命令がリオーダーバッファに蓄えられており、 また十分な命令デコード能力があると仮定したら、 どのように命令が実行されるか、上記と同様の手順を践んで計算してみた。 まず、デコード能力は平均並列命令実行数2.1μOPS/サイクル を2倍(2スレッドだから)した値 (4.2μOPS/サイクル)よりもある程度大きい必要がある。 従って、ここではトレースキャッシュの読み込み能力を5μOPS/サイクル に強化したと仮定し、 またこれにより、すべての命令がリオーダーバッファに蓄えられてから 発行されると仮定して、命令の実行状況をモニタした。 その結果が、下の表である。

十分な命令がリザーブされている状態での実行

実行ユニット1 命令11 命令12 命令3 命令4
実行ユニット2 命令11 命令10 命令6 命令6 命令3
実行ユニット3 命令8 命令9 命令5 命令2
実行ユニット4 命令12 命令10 命令5 命令7 命令1
実行ユニット5 命令9 命令7
実行ユニット6 命令8 命令4 命令2 命令1

前回述べた理想状態図とは少し違うが、やはり8サイクルで処理を終了できる。 これが命令デコード能力強化の威力である。 (ただし、Pentium4の場合、命令デコード能力強化はトレースキャッシュの 読み込み能力強化に相当する。) 処理能力UPは50%も達すると推測される。 常に最適な状態で実行できるとは限らないが、 (今回は幸いにも完全に最適化されたが)少なくともリザーブされた命令が ほとんど無い状態での、その日暮らし発行よりは何倍もマシである。