マルチコア・メニーコアプログラミング時代の移植性問題

マルチコア・メニーコアプログラミング原始時代の現代における一番の問題は、移植性の高いプログラムが書けない点だ、という話。



去年は、GPGPUだとか、Larrabeeとかが話題になったと思う。あと、Top500の一番はCellであった。

何年か後には、ブチ切れた開発者達に反乱を起こされ、彼等のほとんどは死滅し、結局x86と、あとどれかひとつ、と、いうような状況になりそうではあるが、死滅するまでは我々はそれに対応しなくてはいけない(いや、そういう仕事をしないようにすればいいんだけど…)。


どれが生き残るかわからない以上、必要なら、彼等の上で移植性のあるプログラムを書く必要が出てくる。
さて、そういった場合に、どうやれば、FireStream, Tesla, Cell, Larrabee, SSE+pthread, SSE+win32thread その他諸々のアーキクテクチャ上で移植性のあるプログラムを書くことができるだろうか?と、考えたときに、それを実現する方法が無いことに気付く。


データ並列に限れば、それぞれ、単体のアーキテクチャ向けのプログラムを書くのは、それほど難しいものではない。
SSEなんて4並列で計算してるだけ、pthreadは適当にmutex入れて、関数ポインタ渡してcreateするだけ、win32threadはpthreadと名前が違うだけ、Cellなんてデータ一箇所に集めてDMAすればあとはSSEと一緒、CUDAもCellと一緒でデータ一箇所に集めてSIMDみたいなことすれば大体動く、と、いった感じ。


なんだけど、これらのアークテクチャ間で移植性のあるプログムを書くとなると、難しいとか簡単とか以前に、そもそも現状ではその方法が存在していない。
プロのプログラマにとっては、面倒な状態である(趣味のプログラマには幸せな状態かもしれんが)。性能を上げるためには、二年後にはゴミになっているかもしれないアーキテクチャ依存のコードを書かないといけない。ちょっと気を抜くと同期の問題と出会うことなどを考えると、まるでアセンブリでプログラミングをしていた時代のようである。


さて、研究レベルでは、並列プログラミングの世界は数十年の歴史を積み重ねているにも関わらず、何故いまだにこの程度の基本の部分も固まっていないのだろうか?


ひとつ考えられる可能性として、これらの世界は、性能が求められるから、というのがあるだろう。
(余談:この話題が書きたかったので、以前、並列化は性能のために存在してるとか書いたのだった。この話はあの話の続きです)


並列アーキテクチャというのは、まず間違いなく、性能向上を目的として導入される。性能向上以外の目的で、CUDAを採用するような変態はいないはず。(スレッドは微妙だけど…とりあえず忘れて)
そのため、移植性や可読性等、他の全てが優れていようとも、性能が悪ければ話にならない。

例えば、「x86上でCUDAが動くようになりました。Teslaの1/100の性能ですが。」というのは存在していても全く意味が無い。
Core i7は既に浮動小数のピーク性能100GFlops、バンド幅25GBを突破している。
GPUの理論性能を考えると、浮動小数性能は理論性能比1/10、バンド幅は理論性能比1/4を下回った時点で、「それってi7でSSE書いたほうがよくね?」と、いう状態である。


これが、GUIフレームワーク等であれば、移植性があるだとか、プログラミングしやすいだとかは、十分に利点にある。性能はそれなりであれば問題無い。
例えば、「wineを使えばWin32アプリがLinuxで動きます。ネイティブの1/100の性能ですが。(実際には1/100よりもずっと良いけど、まあ、とりあえず)」などは、十分に意味がある。


この点で、並列プログラムの移植性、というのは、そこらのフレームワークの移植性とは少し問題が違ってくるのである。皆で会議室に集って、共通APIを決める、というようなやりかたでは移植性を確保できない。


さて、ここで、我々はどうしたらいいのであろうか?
…特にポジティブな結論とかは無い。


僕の予想は最終的にIntelひとり勝ちでSSEだけになって「移植性?何それ?」という世界になるのでは?とかだが。Larrabeeは命令セットだけ残して死亡。