カジュアル並列プログラミングの世界へようこそ(という妄想)

movdquが遅いというのはひじょーに困る。カジュアル並列プログラミングの世界がまた一歩遠ざかってしまう。

並列化というのは、うまくやらないと遅くなる可能性があって、まあ、うまくやるといっても、そんなに大変ではないのだが、しかし、「遅くなるかも」という可能性が1%でもあるとき、作業を無駄にするリスクを背負わないといけない。これが精神に与えるダメージがでかい。この精神に与えるダメージが小さいとき、それをカジュアル並列プログラミングと呼ぶ(呼ばない)。

SSEは、CPUにくっついてる都合上、このリスクがかなり低く、カジュアルだと思っていたが、movdquがスループット6とかで辛い。


並列処理にも手軽度があって、SSEはかなり手軽な部類だ。末端のプログラムの末端の処理に、ちょこっと追加するみたいなことができる。例えば、

int a[16];
/* 初期化 */
for (int i=0; i<16; i++) {
   a[i] = 0;
}

暇なときにこういうのを書きかえるとかできる。


レイテンシがでかいとそうはいかない。いくつかの関数にまたがって処理を直さないといけない場合がある。例えば、x86だとコア間の通信が…えーと…忘れたのでどうでもいいや。



この点を踏まえて、AMDの提唱するFusionについて考えてみよう。
AMDのFusionはヘテロジニアスコンピューティングと呼ばれている仕組みであるが、実際出てみると、単にGPUくっつけただけでしたズコー。となることが予定されているCPUで、妄想するなら発表されていない今のうちしかないというものである。


さて、このFusionで搭載されるAPUがどうなってると嬉しいか。

今のSSEとかAVXは、ベクタ長が決まっているので、これが、ソフト、ハードを硬直させ気味である。
個人的には、これがなんとかなってくれると嬉しいと思う(いや、ほんまに嬉しいか…?)。すなわち、ソフトウェア的にはSIMDのベクタ長が可変長に見えて、それをうまくコプロセッサがなんとかする的な感じである。

    cpmov   counter, eax   # cpmov コプロ(=APU)mov
    cpmov   ptr0, ecx
    cpmov   ptr1, edx
    cpmov   ptr2, ebx
    cpmov   command, ADD
    cpsync                 # 終了まで待機

というような感じで、ベクタマシンを横にくっつけたみたいな感じにする。カウンタ値が大きいとキャッシュバイパスして、メモリバンド幅理論値近く出るみたいになってると理想。(Phenomとかはメモリバンド幅が理論値と比較して小さすぎて悲しいので)
んで、APUとの通信レイテンシは、数千cycleぐらいだと嬉しい。そのぐらいなら気軽に使えるという気がする。


さて、cpsyncした時に、OS的にコンテキストスイッチして、他のプロセスがAPUを使ったらどうなるだろうか。まあ、ここは妄想の世界なので特に考えない。(ポインタとカウンタぐらいなら退避復元できる気がするが)


しかし、実際これが欲しいか?というと微妙。SIMDSIMDとは言うが、実際SIMDが欲しいと言ったときに、狭義のSIMD(Single Instsruction Multiple Data)だけが欲しい場合はレアケースで、実際はみんなshuffleとかpextrwとかhaddとかしまくってんだろ?CUDAがHigh Performance Fortran(及びそれに類似するアレとかコレとか)みたいな美しい形をとらないで、大量のスレッドがそれぞれ動いちゃうみたいな仕組みになったのは、みんなそれが欲しかったからだろォ…

というように考えると、上で示したように、ポインタとカウンタとコマンドを設定してGoみたいな形では表現できず、コプロセッサ側にもそれなりに強力なフロー制御の仕組みが必要になって、命令カウンタと命令キャッシュを詰んで、ISAが定義され、ほげほげして、複雑になってしまって、CPUと距離がとられレイテンシがでかくなり、カジュアル並列プログラミングはさらに妄想の世界の奥深くへと旅立っていくのだった。

特にまとめとかは無い。