いわゆるマルチスレッド対応した言語が使いものにならないと思う理由
個人的には、マルチスレッド対応とか並行処理対応とか銘打ってる言語の機能は使いものにならないと思っている。
Javaは、登場当時、マルチスレッド対応を謳っていた。が、登場時の目玉機能であったモニタは、オブジェクトとロックが関連付けられてしまうのと、モニタしかロックする方法が無いという二点で設計に失敗した結果、今はまともにマルチスレッドするなら、java.util.concurrentというライブラリを使いましょう、ということになっており、もはや言語レベルでのマルチスレッド対応は、「volatileがC/C++よりまとも」という点ぐらいになってしまった。
マルチスレッド対応とか、並列対応とかに騙されてはいけない。あれらは全て使いものにならない。以下にそう思う理由を書く。
(以下はCPU性能の為のマルチスレッドの話で、イベントとかIO処理のためのマルチスレッドについては考えてない)
メモリ問題に非対応
昨日書いたように、僕はマルチスレッドの一番の問題は、メモリの問題だと思っている。
しかし、残念ながら、大半の並列対応言語は、この問題に対して、何の解決も示していない。
一番重要な問題が解決されていない、という点で、並列言語というものに必要性を感じない。
シングルスレッド性能がC/C++より低い
現代(Core2以降)では大半の用途でCPU性能は十分満足できるレベルになっている。
その結果、CPUに対する性能要求は、以下のふたつに二極化が進んでいる
- 性能なんかどうでもいい
- 速ければ速いほどよい
「性能なんかどうでもいい」プログラムでは、そもそもマルチスレッドで書く必要は無い。
「速ければ速いほどよい」場合は、CPU性能をフルに使っても全然足りない。こういうところでは、アセンブリで書いても、それで性能が上がるならば価値があると認められる。手動でスレッドスケジュールを考えなおすし、SIMDも使う。
今の時代、マルチスレッド性能が要求されるアプリケーションの大半は、そういうプログラムである。そういうプログラムでは、C/C++より遅いプログラム言語は、全く存在価値が無い。ここで、C/C++より遅い、というのは、shootoutのランクの話ではない。SIMD intrinsicを使い、コンパイラのスケジューリングの癖を把握して書いたC/C++のプログラムより遅い、という意味である。
現代のCPUにおいては、SIMD intrinsicがまともにスケジュールされないコンパイラは、最適化コンパイラではない。PentiumDのころから考えると、コア数は2倍にしかなってないが、SIMD長はSandy Bridgeで4倍になる。今のところはコア数の増加速度よりも、SIMD長の増加速度のほうが早い。並列化という意味では、マルチコアよりもSIMDのほうが重要なのである。SIMDに対応しない言語は並列言語ではないのだ。
必要なのはスケーラビリティでなくて絶対性能だ。チューニングしたC/C++よりも速くできない言語では並列化機能は全く必要ではない。
わざわざC/C++から書き換えが必要なほど機能が追加されていない
いわゆる並列言語が持っている機能は、大体以下のみっつである
- スレッドが簡単に書ける
- データ並列が簡単に書ける
- forが簡単に並列化できる
いずれも、わざわざ新たな言語を持ち出してくるほどのものではない。
「スレッドが簡単に書ける」というのは、C++ならライブラリで十分対応できる。例えばTBBを使えば、おそらくそこらの並列言語よりちょっと多いくらいの記述量で、大体同じことができる。現状、classを書かないといけないのが面倒であるが、これはC++0xでラムダが入れば、より改善されるはず。
次に、「データ並列が簡単に書ける」というのは、「データ並列が書けるほど綺麗なデータ構造を作るほうが面倒」という点で、実際には役に立たない。
昨日書いたのと似た話で、データ並列で難しいのは、「リンクリストを配列に置きかえる」という作業である。この作業に比べれば、スレッドを作るとか、SIMD命令を書くとかは、全然大した作業ではない。データ構造を作りかえた時点で、作業は95%ぐらい完了しており、残りの5%で楽をしたところで、作業量はほとんど変わらない。それならば、残りの5%も全力を尽くして、CPU性能を極限まで使いきるプログラムを書くべきだ。
186行が42行になるだって?そこまでの苦労を考えたら、一個の関数が144行増えるだけなんて全然大したことないよ!!
さらにいうと、データ並列が綺麗に書けるようなループは、今のFortranコンパイラなら自動で並列化してくれるレベルである。
Cだとちょっと難しいのだが、何故難しいのかというと、ポインタがあるからだ。そう考えると、データ並列言語は本質的には「ポインタは安全です」ということを示すフラグでしかないわけだ。たった1bitを指定するためだけに、新しい言語でプログラムを書き直せというのか?
「データ並列が簡単に書ける」というのは、ほとんどメリットが無い。データ並列言語を3つ学ぶぐらいならば、x86とARMとPPCのSIMDを勉強したほうがいい。
「forが簡単に並列化できる」 -- OpenMP使え
Javaの登場当時
マルチスレッド対応、セキュリティ対応、ネットワーク対応、組み込み対応…言ったもん勝ちの時代だったな…
まあ、いずれも現代でも重要だと言われていることを考えると、流行キーワードを見抜くセンスは素晴らしかったのかもしれない。