並カン行ってきました。

mootoh さん(Twitter)のセッション

並列処理が自然で、逐次処理はむしろイレギュラーなんだなーっていう理解。
そんな風になってくると楽しそうだなぁ。

wraith13 さん(Twitter)のセッション

並列プログラミングは怖いなーという理解。
ただなんかそれって並列プログラミングが未来的すぎて時代が追いついてないだけというかそんな感じがしていて、その内ものっそい便利なプロファイラとかデバッガとか出てきて並列プログラミングの怖いところや難しいところを魔法のように一気に解決してくれたりするんじゃないかなーとか楽観視。
いやまあ今どうするのかって言われると頑張りましょうとしか言えないわけですが。

goyoki さん(Twitter)のセッション

VHDL とかよく知らなかったんだけど、とりあえずリアルタイム性を求められるプログラムはほんと大変なんだなーという理解。
クロックによって同期を取るって恐ろしい世界だなーとか思ったり。

hayamiz さん(Twitter)のセッション

STM は Lock-free アルゴリズムみたいなものなのかなーという理解。
何か最近の主流ってみんな楽観的ロックになってるイメージがあるなぁ。

syoyo さん(Twitter)のセッション

MUDA 言語は便利な DSL なんだなっていう理解。
自分も C++ に yield 構文追加したような言語作ってそれを C++ に変換するようなプログラムが書きたいけど構文解析の時点で無理がありすぎる。

yamasa さん(Twitter)のセッション

C++0xer な自分としては一番期待のセッション。
compare_exchange_weak と compare_exchange_strong の違いを聞けたので、それだけでもう満足。
Lock-free アルゴリズムでオブジェクトをいつ破棄するのかっていう問題は面白かった。
最終的に GC 的なものに頼るのが一番っていう結論はなんか悔しかったので、TLS で参照カウントを持つようにして、その TLS の参照カウントが 0 になったら大本のオブジェクトの参照カウントを減らす、つまり共有するオブジェクトを各スレッドが所有していて、その各スレッドが所有しているオブジェクトを関数なり何なりで所有させるみたいなものを考えたんだけど、TLS な参照カウントオブジェクトを作るコストが高すぎたり例外のことを考えたりすると使えないよねとか思ったり。
でも Windows の COM とかも似たような感じで、プロセス間でやりとりする場合は各プロセス毎に参照カウントを持っていて、あるプロセスでの参照カウントが 0 になった場合はプロセス間通信を行うみたいな仕組みになっていたはずなので、ロックがほんとにめちゃめちゃ重い処理なら考えられなくも無いかも?
TLS な参照カウントオブジェクトは TLS なアロケータがあれば排他制御する必要な無いだろうし・・・でもそこまでやるなら Hazard pointer 方式の方が楽な気がする・・・うーん・・・。

shelarcy さん(Twitter)のセッション

Haskell って頑張ってるんだなーって理解。
正直難しくてよく分からなかったです。
まあこういう言語は並列化しやすそうだから今後もっと使われていきそうな気がする。


懇親会

とりあえず「並列の世界ってそんなに広くないよね」的な発言をしたら Dis られまくった。
並列プログラミングが簡単だとか、ちゃんと理解するのが簡単だとか言いたいわけではなくて、なんかうまく答えられなかった。
とりあえず自分の頭の中身を適当に羅列していくとこんな感じ。

  • 並列プログラミングって最終的な出口ってある程度決まってる感じで、その目的のためにいろいろな研究とかしている訳だから、動機はわかりやすい(同期は難しいけどね!)。
  • 自分が最初にマルチスレッドをちゃんと勉強したのが結城先生のマルチスレッドデザインパターン本で、正直普通のデザインパターン本より全然理解しやすかった。これは共有するオブジェクトをどうやってやりとりするかって問題ばっかりだったからなのか共有する部分は結果的にかなり小さくなるからなのかそれとも自分の頭が最初から並列脳(笑)だったからなのかよく分からないですが。
  • まあ当然自分でいざ使ってみようとすると「デッドロック余裕でした^^」とかなったり、CAS 操作や Lock-free アルゴリズムで頭がぐにゃぐにゃになったりしたわけですが。やっぱり並列プログラミングって難しいよね。


あと async の話も少しあったので書いてみる。C++0x で追加される std::async 関数はデフォルトだと同期になったり非同期になったりというのが切り替わるようになってる。std::async の実装は多分コア数とか見てある一定の数以上になったら同期処理に切り替えるとか、スレッドプール的なのを作ってそこに処理を放り込んだりとかするはず。
で、そうなるとスレッド数とか気にしなくて良くなるので、N2889 にあるように、

int parallel_sum(int* data, int size)
{
  int sum = 0;
  if ( size < 1000 )
    for ( int i = 0; i < size; ++i )
      sum += data[i];
  else {
    auto handle = std::async(parallel_sum, data+size/2, size-size/2);
    sum += parallel_sum(data, size/2);
    sum += handle.get();
  }
  return sum;
}

こんな風に size がいくつだろうととりあえず std::async 呼べばいいでしょ的な感じに。多分毎回必ずスレッド作るような実装だとこうはいかないはず。std::async 便利です。


それから y-hamigaki さんにすごくいいお土産を頂きました。ありがとうございます。