Gauche > Archives > 2011/10/27

2011/10/27 11:01:34 UTCkoguro
#
なんとなくイメージとして、例外ってあまり頻繁に投げられるようなものではない感じがするのですが、重くなると目に見える影響ってでますか?
2011/10/27 11:04:25 UTCshiro
#
難しいところです。「例外」なんだから例外時のみ使うべき、っていうのはひとつの正論なんですが、伝統的にLispの例外(toiuka
2011/10/27 11:05:10 UTCko1
#
hi
2011/10/27 11:05:14 UTCshiro
#
(というかコンディション)ってもっと気軽に使われてて、実際Common Lispの既存の処理系だと例外処理は相当軽いんですよ (cf. http://norvig.com/Lisp-retro.html 途中の性能比較表の
#
"exception handling" のところ参照)。
2011/10/27 11:06:26 UTCko1
#
やっぱり port 制限があるところだと見れなかった(今はproxyで対応)
2011/10/27 11:07:25 UTCshiro
#
昔のネイティブコンパイラでは、主要なデータ型のパスをネイティブコードで吐いておいて、それ以外のデータが来たらコンディションが投げられるからそのハンドラで対応する、なんてのもありましたし。
2011/10/27 11:07:43 UTCko1
#
exception に backtrace 付けないで困ることは少ないですか?(Ruby だとついてる)
2011/10/27 11:08:07 UTCkoguro
#
なるほど。思ったのですが、スタックトレースが出て欲しい局面って、「想定外の所でエラーが発生した」みたいなケースなので、<error>のときだけつけるようにするってのはどうかなと。
2011/10/27 11:08:35 UTCshiro
#
あー、それは案外良い手かも> <error>だけ
#
>ko1 exceptionにトレースをつけるかどうかってのは、ハンドラがどこで呼ばれるかってのにも関係してて、
#
Schemeの低レベルハンドラとかCommon Lispの低レベルハンドラってのはスタックを巻き戻す前に呼ばれるので、そこでトレースを取ろうと思えば取れるんです。
#
でも、高レベルハンドラ (Schemeだとguard) になると、guardのあるところまでスタックを巻き戻してからハンドラを呼ぶので、スタック情報が直接は取れなくなる。
#
コンディションを「例外」でないケースで使ってる例としては、Common Lispプログラムで、バッファに書き込んでいってバッファがいっぱいになったらフラッシュする、というコードにおいて、バッファがいっぱいになったらコンディション投げる→上位でそのコンディションつかまえて、バッファをフラッシュして再試行、なんてのを見たことがあります。
2011/10/27 11:13:05 UTCko1
#
ああ,言語レベルで低レベルハンドラ,というものがあるんですね(それとも,実装依存?)
#
Ruby でも,EEOF で例外飛ばすんで,「例外オブジェクトができて重いから EEOF は例外飛ばすなよ」てな議論があります.
#
今日はちょっと伺いことがありまして来たんですが,
2011/10/27 11:14:23 UTCshiro
#
Schemeだとwith-exception-handlerが低レベル、guardが高レベルです (srfi-34)。Common Lispだとhandler-bindとhandler-caseだったかな。
2011/10/27 11:14:29 UTCko1
#
浅学なもので,PLT scheme が Racket という名前に変わっていたのを知りませんでした.
#
で,future とか Place という並列コンストラクタがあると知ったのですが
#
http://docs.racket-lang.org/reference/futures.html
#
http://docs.racket-lang.org/reference/places.html
#
これは,どの程度受け入れられているものでしょうか
#
Scheme 屋さんでは常識だったり,ちょー新しいので誰も知らない,とか
2011/10/27 11:17:09 UTCshiro
#
futureは古いです。私が学生の頃からSchemeにありました。Scheme界の大御所の誰かの博士論文でfutureによる並列計算の実装とセマンティクスを論じたのがあったような。
#
placeはどうなのかな? そのものずばりの発祥はわかりませんが、発想としてはごく自然なもののような。
#
ああ、Marc Feeleyだ。"An Efficient and General Implementation of Futures on Large Scale Shared-Memory Multiprocessors" PhD Thesis, Brandeis University, 1993.
#
Marc Feeleyがfutureを発明したわけじゃないので、futureの概念自体はもっと遡ると思います。
2011/10/27 11:25:32 UTCko1
#
ああ,Future は,日本でも abcl とかでありましたよね.
#
ただ,promise とかと同じで,「並列」であるかどうかはあまり拘ってなかった感じがしたもので.
#
Future を「並列プリミティブです」と言っているのは,実は初めて見た気がしたのでした.
2011/10/27 11:26:54 UTCshiro
#
futureは少なくとも「並行計算」の文脈で出てきたものと思ってました。promiseは単に必要な時まで遅延するだけですが。
2011/10/27 11:27:05 UTCko1
#
なるほど.
#
place はどうでしょうか.
#
今やってる Ruby の MVM が,まんま place で.
#
どーしよー,みたいな.
2011/10/27 11:30:44 UTCshiro
#
placeという名称はPLTで初めて見ました。発想としてはTermiteと同じようなものだと思うのですが、Termiteではspawnというプリミティブになってて、そっちの方が一般的な感じはします。
2011/10/27 11:31:23 UTCko1
#
ちなみに,Racket の Future で言っている「safe operation」がわからないんだけど,スレッドセーフとは関係無いよって言ってるし,結局なんなんだろう?
#
Termiteを知らない....
2011/10/27 11:31:48 UTCshiro
#
ああ、spawnは動詞で新たにisolateされた制御の流れを作るもの、placeは名詞で作られた制御の流れだから指すもの自体は違うのか
2011/10/27 11:32:22 UTCkoguro
#
http://www.cs.utah.edu/plt/publications/dls11-tsffd.pdf
2011/10/27 11:32:40 UTCshiro
#
TermiteはGambit Scheme上に作られたErlang風のshare-nothingな分散並列システムです。 http://code.google.com/p/termite/
2011/10/27 11:32:49 UTCko1
#
koguro: まさにそれです.
2011/10/27 11:32:50 UTCkoguro
#
Placeの論文ってこれかな?
2011/10/27 11:33:05 UTCko1
#
これ見て,似たような話やっててどーしよーって悩んでいた.
#
Erlang だと,そもそも isolate してもしなくても immutable な世界なので, thread-safety が保たれるような気がしますが.
#
Scheme とか mutable な世界の住人は,isolation してあげないと悲しいことに.
#
という感じで Ruby の MVM は主張してます.
#
しかし,評価に NAS-para とか持ってくるのは凄い.
#
ちなみに,Rubyみたいな言語で MVM みたいなのを作るには,Cのグローバル変数をどうにかしないといけないんだけど.
#
Racket も同じ話があった,みたいなことが論文に書いてあって,彼らは CIL とかで解析している.
#
grep and CIL ってのが面白かった.
2011/10/27 11:37:55 UTCshiro
#
futureにおけるsafeというのは今Racketのマニュアル読んで知ったんですが、ちょいと書き方がわかりにくいんで想像混じるけれど、「並列に実行したら組み込み関数や標準ライブラリが仕様外の値を返したりする」ということが無い、ってことだと思います。mutableしていればraceは発生するけれど、#tか#fかを返すはずの関数が0を返したりはしない、ということじゃないかと。
2011/10/27 11:38:43 UTCko1
#
TLS にするとオセー,って問題意識はこちらもあったんですが,open issue で,彼らはアセンブラまで導入してなんとかしていた.
#
それは,Racket のライブラリは future-safe だ,ということでしょうか.それとも,特定の関数は future-safe で,そうでないものもある,ということでしょうか.
2011/10/27 11:40:38 UTCshiro
#
うーん、マニュアルの記述からすると、future-safeである箇所は並列に実行して、future-safeが保証できない箇所についてはシリアライズするみたいに見えます。
2011/10/27 11:40:57 UTCko1
#
あ,確かに.つまり,処理系は
#
どの関数が future-safe で,どれがそうでないか知っている,と.
#
future 導入時に全部見直したのかなあ.
#
論文見た方が良いか.
2011/10/27 11:42:14 UTCkoguro
#
Futureはこれですか。
#
http://www.cs.utah.edu/plt/publications/oopsla10-stdff.pdf
2011/10/27 11:42:24 UTCko1
#
はい.
2011/10/27 11:42:26 UTCshiro
#
placeの論文からはtermite参照されてませんね。
2011/10/27 11:43:06 UTCko1
#
Specifically, we partition the set of possible operations
in a language implementation into safe (for parallelism) and
unsafe categories
2011/10/27 11:44:23 UTCshiro
#
何か本質的に違うのかなあ。placeはisolationを保証してるってことなのかな。
2011/10/27 11:46:17 UTCko1
#
だと思います.
#
あんまり書いてないけど,関数定義とかは各VMで完結するんじゃないかと.
#
Scheme だとあんまりないだろうけど,Ruby だと変な monkey patch とか色々やるから分けたい.
#
あと,親placeの値をどれくらい参照できるのか,書いてない気がした.
#
親 place の定義は参照できるみたいだけど
#
Consequently, our first cut at categorizing operations was to define as 
safe any operation that is implemented directly in JIT-generated code 
(e.g. any operation that can be translated by the JIT compiler      
intomachine instructions which do not include function calls back into 
runtime code), and any other operation was unsafe. This first-cut 
strategy offered a convenient starting point for the incremental process, 
in which we modify performancecritical unsafe operations to make them 
future-safe.
#
JIT compile した(数値計算的な?)コードは safe,それ以外は unsafe,ということでしょうか.
#
組込み手続きとかは,徐々に future-safe にしていく,と
2011/10/27 11:53:15 UTCshiro
#
関数定義とかはSchemeだとモジュール分ければいいだけだからな。グローバルに状態をmutateするようなものについて、どのレベルで対応してるのかわからんけど。
2011/10/27 11:54:05 UTCko1
#
結論としては,place はあんまり知られてない,知見の少ない話,でしょうか.少なくとも mutable な世界では.
#
どの手続きが future から呼ばれるかわからないのだから,全ての unsafe な手続きで,自分が future の中なのか,判断してるんだろうか....
2011/10/27 11:54:53 UTCshiro
#
そうですねー、ちゃんと実装して評価しましたっていうのはあんまり見ないと思います>place
#
futureについては、コンパイル時の解析もやってるみたいな印象を受けましたがどうなんだろ。
#
コンパイル時にわからなければ安全側に倒すって感じで。
2011/10/27 11:55:35 UTCko1
#
してる,みたいなことが 4.2 に書いてありました
#
そうですね.
#
色々ありがとうございました.勉強になりました.
2011/10/27 11:56:12 UTCshiro
#
placeについて、知りたいのはplace-channel-getで待ってる時に相手が死んじゃったらどうなるかってことなんだけど、マニュアルにも書いてないような。
2011/10/27 11:56:50 UTCko1
#
R*RS とかで並列 primitive が入る未来は来たりするんでしょうかね.
2011/10/27 11:57:03 UTCshiro
#
みんな気にしないのかなあ。どうやってるんだろ。分散システム作ってて自分が困るのはどっかでつっかえて止まっちゃったり遅くなったりすることなんだけど。
2011/10/27 11:57:48 UTCko1
#
我々の MVM では,channel(同じ用語を使っていた)は VM(placeに相当)に所属するもの*ではない*ので宙ぶらりんになります.誰も参照しなくなった時点で削除.
2011/10/27 11:57:50 UTCshiro
#
並列計算がメインストリームに入ってくるのは避けがたい未来なのでいずれ来るとは思いますが、色々選択肢があるのでしばらくはsrfiで練るんじゃないかと。
#
そうするとそのchannelで待ってる人は待ちぼうけ?
2011/10/27 11:58:26 UTCko1
#
待ちぼうけ.
2011/10/27 11:58:32 UTCshiro
#
困ることない?
2011/10/27 11:58:40 UTCko1
#
まだ困るまで経験がありません
#
困りそう,とは思っているので
#
VMの状態を監視するための channel を用意する必要があるなぁ,と思っています
#
似たような仕様に,Java の Isolation API ってのがあって,JVM を複数つなげたりするんですが
#
そいつには,VMの状態変化を通知する Channel (Link って名前)があって,そういうのが居るなぁ,と思っています.もしくは,シグナルみたいなので伝えるか.
2011/10/27 12:00:14 UTCshiro
#
サーバで無停止運転してたりすると困るので、止まっちゃってたら全部殺してやりなおすってのはひとつシンプルな手。ただGaucheだとブロックしてるスレッドを殺すのは色々不安なので、チャネル(というか今はqueueしかないけど)の方で対応できるようにしてる。
2011/10/27 12:00:49 UTCko1
#
つまり,queue の端点に thread が登録されている?
2011/10/27 12:01:23 UTCshiro
#
いや、queueにタイムアウト仕掛けられるようになってて、タイムアウトしたらスレッド内で対応。
2011/10/27 12:01:23 UTCko1
#
片方が死んだらそれがもう片方に通知される,みたいな
#
あー.timeout は place のほうにもあるようですね
#
MVMのも,timeout は対応できる
2011/10/27 12:02:35 UTCshiro
#
placeにタイムアウトある? マニュアル見てるんだけど
2011/10/27 12:03:57 UTCko1
#
(sync/timeout timeout evt ...+) でいけるみたいです.
2011/10/27 12:04:00 UTCshiro
#
あ、それともイベントでメッセージがあるかどうか待って、メッセージがあるって分かってからgetしに行くのかな。それならplaceが死んだのはイベント待ちのところで検出できるな
2011/10/27 12:04:40 UTCko1
#
死んだのまでわかる?
2011/10/27 12:04:52 UTCshiro
#
そのようですね。これはメッセージがどんなにでかくなっても一回システムでバッファするってことかな
2011/10/27 12:05:13 UTCko1
#
だと思います.我々もそうやってます.
2011/10/27 12:06:24 UTCshiro
#
死んだのについては、place-dead-evtで死亡検出のイベントが作れるので、それを一緒にsyncで待てばわかるんじゃないでしょうか。
2011/10/27 12:07:00 UTCko1
#
あー,そうやって使うのか.なるほど.つまり,place の状態変化(live->dead)を通知するチャンネル(イベント)があるわけですね.納得しました.
#
Racket の event がイマイチ理解できてなかったんですが,理解.
2011/10/27 12:07:29 UTCshiro
#
バッファするってことは、でかいデータをどんと送りたい時はなんか共有領域に置いてそのハンドルだけを受け渡すってことになるのか。
2011/10/27 12:08:15 UTCko1
#
共有領域っていうか,private でどの place も扱ってない領域を切り出して,そこに置いて,その領域へのハンドルを受け渡すみたい.
#
「private で」は不要でした.
2011/10/27 12:09:08 UTCshiro
#
もひとつ疑問は、producerとconsumerでconsumerが遅い場合、producerがどんどんデータ詰め込んでくと使用メモリが上限なく膨らむんだけど、これについてもイベントで同期取るのかな。書き込めるようになるまで待つ、みたいな感じで。
2011/10/27 12:09:08 UTCko1
#
Ruby で event 的なものはどうやったものかな.
#
sized-queue をどう作るか,ですか.
#
我々はそれに対して検討できていませんでした.
2011/10/27 12:09:55 UTCshiro
#
確かにチャネルに持たせるより別イベントにした方が、「どれかのイベントを待つ」というプリミティブに統合できるから便利なのか。
2011/10/27 12:09:56 UTCko1
#
まー,メモリあるからいいよね,的な
#
Racket の API いいなー
#
POSIX とかも全部こうなればいい
2011/10/27 12:10:30 UTCshiro
#
producer/consumer問題は現実のアプリで当たりました。
2011/10/27 12:11:03 UTCko1
#
queue に格納されているサイズを取る方法があればいいのかなあ
#
producer はそれを見て,大変そうなら自分も手伝ったりする
#
いやはや,大変参考になりました.ありがとうございます.
2011/10/27 12:15:06 UTCshiro
#
いや、こちらも材料が得られてうれしいです。
2011/10/27 12:16:45 UTCko1
#
死んだらこのチャンネルに情報を流して,って登録できるといいのかなぁ.しかし ad-hoc だ.
2011/10/27 12:30:23 UTCshiro
#
死ぬ時ってのはだいたい死ぬと思ってない時に死ぬわけで、本人から情報を流すことはできないですね。待ってる人か、第三者が監視するか、しかないですな。Erlangは監視することが出来ましたよね確か。
#
確かに、死亡をイベントにすれば統一的に扱えるが、ロバストにしたいなら全てのplaceについて死亡を監視する必要があるわけで、それをいちいちsyncに織り込むのもちょいと手間な感じはする。複数のplaceから返事を待ってるとしたら、それと同数の死亡監視イベントも見といて、死んだら対応するチャネルを見つけて後始末して、っての、結構面倒そうな。
2011/10/27 12:37:04 UTCshiro
#
あれ、chaton-twitter bridgeが、twitterのdaily update limitをオーバーしちゃった。以前に比べて厳しくなった?
2011/10/27 12:39:40 UTCkoguro
#
1時間単位のリミットに引っかかった?
2011/10/27 12:41:02 UTCshiro
#
いえ、"User is over daily status update limit" だそうです。
2011/10/27 12:42:38 UTCkoguro
#
1000件/日だから余裕がありそうですけど
2011/10/27 12:43:02 UTCshiro
#
ですよねえ。
2011/10/27 12:45:49 UTCkoguro
#
なんか、hourly limitでも"User is over daily status update limit"が返るみたいですね。
#
http://code.google.com/p/twitter-api/issues/detail?id=1448