ただ、問題は「本当にこんなに大量のデータをコア間で通信する事がありえるか」という話である。勿論、親プロセスに巨大バッファを確保し、これを複数Threadでとっかえひっかえ加工するなんてパターンはありえるのだろうが、逆に複数のプログラムが同時に動くというケースでは、コア間で大量のデータ通信が行われるケースは稀だろう。このあたりを、もう少し細かく調べてみる事にした。
今回、Util35というプログラムを作成してみた。ソースはこちら(Util35.cpp)で、
- 親プロセスはバッファエリアとクリティカルセクションを1個作成する
- 子プロセスはクリティカルセクションの中で親プロセスのバッファを書き換える
という単純なものだ。ここでバッファサイズを256Bytes~64KBの範囲に可変し、スレッド数を1~8の範囲で増やしながら、1スレッドあたり合計で1,024,000,000回の書き換えを行う様にして、全スレッドの書き換えが終わるまでの所要時間を求めた。実行プログラムとアセンブラソースはこちら(Util35.zip)である。
さてまず単純にコア別のスコアをまとめたのがグラフ60~62である。一般論として、一回に書き換えるサイズが小さいほど煩雑にThreadの切り替えが発生するから、オーバーヘッドが大きくなる。なので、グラフは書き換えサイズが小さいほど傾きが大きくなるのは正しい。それを念頭において見てみると、グラフ61では512Bytesまで、グラフ62では1KBまで妙にグラフが凸凹しているのがわかる。グラフ61、つまりCore 2 Quadの場合、2 Thread目が恐らく異なるダイのコアに割り当てられ、ここでグンと成績が悪化している。たいして3 Thread目ではどちらかのThreadと同一のコアに割り当てられ、ここではThread間の通信の増分が相対的に少ないから傾きが緩やかになり、しかし4 Thread目はまた異なるダイのコアに割り当てられるので再び増加する、というあたりだろう。グラフ62、つまりAthlon 64の場合はそもそもが2コアなので、3 Thread以上になると必然的にContext Switchingが発生する。これが激しくなるのが4 Thread目以降というわけだ。
こうした傾向を念頭において、今度は256KB/4KB/64KBの結果を異なるCPU同士で比較してみたのがグラフ63~65だ。通信サイズが256Bytesと小さい場合(グラフ63)、PhenomはThreadが増加しても処理時間は均一に増える。この傾向はAthlon 64 X2でも同じだが、2 Coreしかない分、3 Thread目以降の負荷が急速に増えていることからこれが判る。ではCore 2 Quadは? というと、やはりFSB経由でのContext Switchingが多い分処理負荷が掛かるようで、Athlon 64 X2ほどではないにせよ、Phenomよりも40%以上余分に時間が掛かっている。もっともこの差は4KB(グラフ64)では急速に縮まり、64KB(グラフ65)ともなるとむしろCore 2 Quadが最速になっているから、CPUの処理が遅い訳ではない。強いて言えば、Core 2 QuadはContext Switchingの負荷が軽い時には高速に動作するが、負荷が掛かったときに性能が急速に劣化しやすい傾向にあり、逆にPhenomは負荷が軽いときでもそれほど高速になるわけではないが、負荷が掛かっても性能が悪化しにくいと言える。このあたりは根本的な設計思想の問題なので良い悪いという話ではないのだが、Mobile出身のCore 2 Quadとサーバー向けのPhenomという対比が非常にはっきり読み取れる結果であった。