The Problem Statement: it's not "atomic-vs-lock" but instead it's "where do we put atomic/lock?"

Randall R Schulz

Azul Systemsのブログで以下のようなコメントを見つけた(http://blogs.azulsystems.com/cliff/2008/05/javaone.html):
Cliff Click wrote:

STMの性能はユーザから見て透過的ではない。STMのランタイムはアボートと再実行をしなければならないからだ。その仕組みは複雑怪奇で、負荷が高い状況でSTMの振る舞いは予測不能だ。実際の製品で使える代物ではない。

これについて何かコメントは反証はあるかい?

Raoul Duke

Rich Hickey wrote:

明示的にロックを使えばそういう予測不能な事態はなくなるのか?私にはそうは思えない。

要するに負荷が高い状況ではいずれにせよ振る舞いは複雑になる、と言いたいらしい。

うーん、でもロックを使えばある意味そういう複雑な事態は起きないと思う。何が原因でロールバックが起きたのかを調べるのがSTMでは難しい(どのSTMシステムを仮定するかにもよるけど)のに比べて、少なくともロックを使えばどのロックで90%のスレッドが寝ているのかをすぐに調べることはできる。STMでは、オーバーラップしているトランザクションのベン図の中のどの変数が再実行の原因となったのか分かるかい?

もっともClojureはそれを見つけるための仕組みを持ってるとRichは言ってたけどね!http://groups.google.com/group/clojure/browse_thread/thread/2f73b80fd

Cliff Click

そのとおり。負荷が高い状況ではSTMの性能は予測不能だ。

ロックを使えばどのロックで衝突が発生しているかがわかるし、衝突の理由も普通はわかるし、対策も考えられる(ロックを分割したり、クリティカルセクションを短くしたり、java.util.concurrentの中のデータ構造を使ったり)。

STMではそういうことは不可能だ(少なくとも今のところは)。STMを普通の論文で使われているよりも大規模なケースで試したことのある人と何人か話したことがあるけど、結果は全くひどいものだ。自分が使っているSTMランタイムの専門家にでもならない限りは(ここで言う専門家とは単に使えるだけではなくて自分で作って改造できる、ということ)、十分に性能が上がることはない。これは研究レベルで未解決問題だし、解決されそうな兆候もない。

Rich Hickey

人間が手でロックを書いたシステムはたいていどこか間違っているものなんだから、その振る舞いは(そしてもちろんその性能も)予測不能だ。ひどい開発者の手によるロックの使われ方を見て私が得た経験がそれだよ。STMがどういった性能の振る舞いを示すのか理解するのは難しいけど、人間が手で書いた並列プログラムの挙動を理解するのも同じくらい難しい。しかし少なくともSTMでは動作の正しさはシステムが保障してくれるし、問題に対して各アプリケーションが個別に対応するのではなく同じSTMシステムを使うユーザはみな知識を(そしてバグフィックスも性能改善も)共有できる。そしてSTMの性能がお気に召さなかった時はいつでもトランザクションを用いずに手でロックを書くこともできるのだ。STMを使っている限りはシステムの複雑性を劇的に減らすことが出来る。

並列性の話と性能の話をごちゃ混ぜにすべきではないと私は思う。並列なプログラムはなによりもまず正しく動かなければならないのだ。この点について、手でロックを書くのは複雑で全くよろしくない。スケーラビリティ性能を誰もが問題にしているわけではないのだ。数千もの同時接続を処理しなければならないシステムもあるだろうが、ほとんどのシステムはそうではない。数百個のCPUを一つのアプリケーションで使い切る必要のある人もいるだろうが、ほとんどの人はそうではない。しかし複数のコアを利用するあらゆるアプリケーションはなによりもまず正しく動作しなければならないのだ。

やろうと思えば、メモリへのどの参照で衝突が起きたかを正確に知るためにClojure STMを改造してフォールトカウンタを付けることもできる。どこで衝突しているかがわかれば、解決策はSTMだろうがロックだろうが似たようなものだ。書き換わる可能性のあるデータはなるべく共有しない、長いトランザクションと短いトランザクションに同じデータをアクセスさせない、トランザクションが成功するための条件をなるべく早くチェックする、などなど。



STM designs differ from one another quite a bit, so any general statements are difficult to assess. I think the level of granularity of the STM comes into play. Most of the STM papers I've read concentrate on creating lots of transactional cells with which they envision constructing concurrent data structures like the ones in java.util.concurrent. I don't think that's a good idea at all.