ジャンプ(スコープをまたぐジャンプ)関係を全部片づける。思いつく限りの対応をしたけど、まだ残ってるんだろうなあ。
というわけで、YARV でこんなプログラム動くかオラオラ、という例募集。
[ruby-dev:26657] は、YARV ではきちんと動いた。よかった。
i = 0 ary = (1..100).to_a class Array def map i = 0 ret = [] while i<self.size ret << yield(self[i]) i+=1 end ret end end while i<30000 i+=1 ary.map{|x| x * 1} end #=> ruby 7.500000 0.032000 7.532000 ( 7.568000) # ruby 版 map yarv 1.329000 0.016000 1.345000 ( 1.343000) # ruby 版 map ruby 2.688000 0.015000 2.703000 ( 2.692000) # C 版 map yarv 1.141000 0.015000 1.156000 ( 1.138000) # C 版 map
やっぱりまだ C 版のほうがちょっと速いか。どこを削れば速くなるかな。
YARVCore 0.3.0 rev: 217 (2005-07-30) [direct threaded code] [optimize basic operation] [stack caching] [operands unif ication] [instructions unification] [inline method cache] == disasm: <ISeq:main@../test.rb>======================================= == catch table |type: 07, st: 0020, ed: 0027, sp: 0000, cont: 0020 |type: 09, st: 0017, ed: 0033, sp: 0000, cont: 0033 |type: 13, st: 0017, ed: 0033, sp: 0000, cont: 0027 |type: 11, st: 0017, ed: 0033, sp: 0000, cont: 0017 |------------------------------------------------------------------------ local scope table (size: 3, argc: 0) [ 3] i [ 2] ary 0000 UNIFIED_putobject_OP_INT2FIX_O_0_C__setlocal_OP_3_SC_xx_xx ( 10) 0001 UNIFIED_putobject_OP_INT2FIX_O_1_C__putobject_SC_xx_ab100 ( 11) 0003 newrange_SC_ab_ax0 0005 send_OP__WC__0_Qfalse_0__WC__SC_ax_ax:to_a, <ic> 0008 setlocal_OP_2_SC_ax_xx 0009 putnil_SC_xx_ax 0010 putnil_SC_ax_ab 0011 classdef_SC_ab_ax:Array_, <ISeq:<class:Array_>@../test.rb> ( 13) 0014 popcref_SC_ax_ax 0015 jump_SC_xx_xx 27 ( 25) 0017 UNIFIED_getlocal_OP_3_putobject_OP_INT2FIX_O_1_C__SC_xx_ab ( 26) 0018 opt_plus_SC_ab_ax 0019 setlocal_OP_3_SC_ax_xx 0020 getlocal_OP_2_SC_xx_ax ( 27) 0021 send_SC_ax_ax :map, 0, <ISeq:block in main@../test.rb>, 0, <ic> 0027 UNIFIED_getlocal_OP_3_putobject_SC_xx_ab30000 ( 25) 0029 opt_lt_SC_ab_ax 0030 if_SC_ax_xx 17 0032 putnil_SC_xx_ax 0033 end_SC_ax_ax == disasm: <ISeq:<class:Array_>@../test.rb>============================= local scope table (size: 1, argc: 0) 0000 methoddef_SC_xx_xx:map, <ISeq:map@../test.rb> ( 14) 0003 putnil_SC_xx_ax 0004 end_SC_ax_ax == disasm: <ISeq:map@../test.rb>======================================== == catch table |type: 09, st: 0006, ed: 0025, sp: 0000, cont: 0025 |type: 13, st: 0006, ed: 0025, sp: 0000, cont: 0017 |type: 11, st: 0006, ed: 0025, sp: 0000, cont: 0006 |------------------------------------------------------------------------ local scope table (size: 3, argc: 0) [ 3] i [ 2] ret 0000 UNIFIED_putobject_OP_INT2FIX_O_0_C__setlocal_OP_3_SC_xx_xx ( 15) 0001 newarray_SC_xx_ax0 ( 16) 0003 setlocal_OP_2_SC_ax_xx 0004 jump_SC_xx_xx 17 ( 17) 0006 getlocal_OP_2_SC_xx_ax ( 18) 0007 putself_SC_ax_ab 0008 getlocal_OP_3_SC_ab_ba 0009 opt_aref_SC_ba_ax 0010 yield_SC_ax_ax 1, 0 0013 opt_ltlt_SC_ax_ax 0014 UNIFIED_getlocal_OP_3_putobject_OP_INT2FIX_O_1_C__SC_xx_ab ( 19) 0015 opt_plus_SC_ab_ax 0016 setlocal_OP_3_SC_ax_xx 0017 getlocal_OP_3_SC_xx_ax ( 17) 0018 putself_SC_ax_ab 0019 send_OP__WC__0_Qfalse_0__WC__SC_ab_ax:size, <ic> 0022 opt_lt_SC_ax_ax 0023 if_SC_ax_xx 6 0025 getlocal_OP_2_SC_xx_ax ( 21) 0026 end_SC_ax_ax == disasm: <ISeq:block in main@../test.rb>============================== == catch table |type: 11, st: 0000, ed: 0003, sp: 0000, cont: 0000 |type: 13, st: 0000, ed: 0003, sp: 0000, cont: 0003 |------------------------------------------------------------------------ local scope table (size: 1, argc: 1) 0000 getdynamic_OP_1_0_SC_xx_ax ( 27) 0001 putobject_OP_INT2FIX_O_1_C__SC_ax_ab 0002 opt_mult_SC_ab_ax 0003 end_SC_ax_ax -----------------------------------------------------------------------------
そういえば、length にすれば速くなる。
ruby 7.500000 0.032000 7.532000 ( 7.568000) # ruby 版 map yarv 1.329000 0.016000 1.345000 ( 1.343000) # ruby 版 map ruby 2.688000 0.015000 2.703000 ( 2.692000) # C 版 map yarv 1.141000 0.015000 1.156000 ( 1.138000) # C 版 map ruby 7.531000 0.000000 7.531000 ( 7.580000) # ruby 版 map with length yarv 1.094000 0.015000 1.109000 ( 1.100000) # ruby 版 map with length
おお、C 版 map よりも速くなったぞ。
== disasm: <ISeq:map@../test.rb>======================================== == catch table |type: 09, st: 0006, ed: 0023, sp: 0000, cont: 0023 |type: 13, st: 0006, ed: 0023, sp: 0000, cont: 0017 |type: 11, st: 0006, ed: 0023, sp: 0000, cont: 0006 |------------------------------------------------------------------------ local scope table (size: 3, argc: 0) [ 3] i [ 2] ret 0000 UNIFIED_putobject_OP_INT2FIX_O_0_C__setlocal_OP_3_SC_xx_xx ( 15) 0001 newarray_SC_xx_ax0 ( 16) 0003 setlocal_OP_2_SC_ax_xx 0004 jump_SC_xx_xx 17 ( 17) 0006 getlocal_OP_2_SC_xx_ax ( 18) 0007 putself_SC_ax_ab 0008 getlocal_OP_3_SC_ab_ba 0009 opt_aref_SC_ba_ax 0010 yield_SC_ax_ax 1, 0 0013 opt_ltlt_SC_ax_ax 0014 UNIFIED_getlocal_OP_3_putobject_OP_INT2FIX_O_1_C__SC_xx_ab ( 19) 0015 opt_plus_SC_ab_ax 0016 setlocal_OP_3_SC_ax_xx 0017 getlocal_OP_3_SC_xx_ax ( 17) 0018 putself_SC_ax_ab 0019 opt_length_SC_ab_ab 0020 opt_lt_SC_ab_ax 0021 if_SC_ax_xx 6 0023 getlocal_OP_2_SC_xx_ax ( 21) 0024 end_SC_ax_ax
def proc &pr pr end def m a = 10 proc{ p a return } end m.call #=> ruby 1.9.0 (2005-01-23) [i386-mswin32] 10 Exception `ThreadError' at t.rb:9 - return can't jump across threads t.rb:9:in `m': return can't jump across threads (ThreadError) from t.rb:7:in `call' from t.rb:13
これ、エラーメッセージ間違ってると思う。
ko1@atdot:~$ ruby18 -vde ' > def proc &pr > pr > end > > def m > a = 10 > proc{ > p a > return > } > end > > m.call > ' ruby 1.8.3 (2005-05-25) [i686-linux] 10 Exception `LocalJumpError' at -e:10 - unexpected return -e:10:in `m': unexpected return (LocalJumpError) from -e:8:in `call' from -e:14
こっちが正しいのかな。
ko1@atdot:~$ ruby18 -vde ' > def proc &pr > pr > end > > def m > a = 10 > lambda{ > proc{ > return a > }.call > } > end > > p m.call > ' ruby 1.8.3 (2005-05-25) [i686-linux] Exception `LocalJumpError' at -e:10 - unexpected return -e:10:in `m': unexpected return (LocalJumpError) from -e:9:in `call' from -e:9:in `m' from -e:8:in `call' from -e:15
lambda のことを考えると、これはエラーになってはいけないんじゃなかろうか。lambda から return は lambda を抜ける、というルールは実装するのが大変そうだなぁ...
a = [] 3.times{|e| begin next ensure C end a << :error }
こんなプログラムが動かない。(C が実行されない)どうしたもんか。
next じゃなくて break も同じだな。
a = i = 0 while i < 1 i+=1 begin break ensure a += 1 end end
要するに、ローカルなジャンプで実装している中で、ensure があった場合、それを無視してしまう。えーと、無視しないためにはどうすればいいだか。
ensure をコピーすることで解決。
a = [] i = 0 while i<2 i+=1 begin raise rescue break end a << :ng end p a
今度はこれがコンパイルできない。はてどうしたものか orz これは非対応です、じゃ、駄目かしらん。
... 駄目だろうなあ。
クラス文中で break したら、そのクラス文から抜ける、というのはどうだろうか。
class C ... break #=> (A) へジャンプ ... end (A)
現状だったらどうなるだろう、と思ってやってみました。
class Array def match num case num when 0 if self.empty? self else false end when 2 if self.empty? false else return self[0], self[1..-1] end else raise end end end def reverse ary case when ary.match(0) [] when x, xs = ary.match(2) reverse(xs) << x else raise end end p reverse((1..10).to_a)
うーむ。
if(x, xs = *[1, 2]) p 1 else p 2 end' ruby 1.8.3 (2005-05-25) [i686-linux] -e:6: multiple assignment in conditional
SyntaxError とも表示されないのはそういうもんでしょうか。
別に Syntax のエラーではない(意味的エラー)のか。
あれ、でもエラーを拾ってみたらSyntaxErrorだなぁ。
case when (a, b = *[1, 2]) p [a, b] end
こいつは常に(多重代入の右辺がなんであれ)条件は真(配列になるから)ですが、いいんでしょうか。multiple assignment in conditional だと思うのですが。
とりあえず、末尾メソッド呼び出しの最適化をしようと思ったら、詰まった。どこで末尾呼び出し用命令に変換すればいいのか。
コンパイラの構造の問題なんだけど、ちょっと根が深い。はてさて。
とりあえず、ちょっとやってみたけど、あまり実りが多くなさげなので、ペンディング。
あ、tail call recursion の最適化はどうかな。ちょっとやってみよう。
def m n if n == 0 # else m n-1 end end i = 0 while i<1000 # benchmark loop 3 i+=1 m 5000 end #=> Ruby : 30.9 YARV : 2.86 YARV 1: 2.51 (末尾呼び出しの最適化) YARV 2: 2.36 (末尾再帰の最適化)
各種最適化は切ってあるので、かなりこの数値は信頼できない。
んー、純然たるスタックを積むためのコストだから、最適化をきちんとかけた状態では結構いいスコア出すのかな。
if(x){ t = x_t; goto calc; } else if(y){ t = y_t; goto calc; } ... else if(0){ calc: ... } else{ ... }
という書き方は如何なものか。
今日は PHPカンファレンス2005 だったのか。
そういえば、ヒトクイマジカル読了。もうさっぱりわけわからん。
そういえば、博多飲み会の件はどうなったんだろう?
先日、行きの電車で乗り換えの情報を知りたくて携帯電話でウェブを見て探してみたんだけど、全然見つからない。
見つかっても、有料だったり JavaScript 必須だったり。
そのときは、ちょっと急いでいて、少しでも早く目的地に着きたかったので、困った。誰かに電話なりメールなりして調べてもらうという最終手段はあるというものの。
デスクトップでは何も考えずに検索できてしまうため、いつもは気にならないのだけれど。
なんかいいサービスありませんかね。メールで検索結果を返すプロキシシステムでも、ちょっと作ろうかしらん。
あら、なんではねられてるんだろう。
ML 作りましょうか ruby-enkai-kyusyu-2005-summer at quickml.atdot.net で、CC は ko1 at atdot.net で。遊んでくれる人ご参加ください。
予定としては、
こんな感じなんで、8/5 夜〜8/6 昼あいてます。微妙に 8/2 の昼も開いてたり。
田村さんにはお会いしたかったんだけどなぁ。残念です。
そして、発表資料いつ作ろう orz
ML のパターンマッチの話を聞いたので、Ruby だとどうなるのか考えてみる。
def fact n | 0 => 1 | otherwise => n * fact(n-1) end
これは果たしてうれしいのか。
def fact n case n when 0 1 else n * fact(n-1) end end
def reverse list | [] => [] | [x, xs] => reverse(xs) << x | otherwise => raise end #=> def reverse list if Array === list if list.empty? [] else x = list.shift xs = list reverse(xs) << x end else raise end end
こんなふうに変換されるんだろうか。
def reverse list unless list.cdr [] else x = list.car xs = list.cdr reverse(xs) << x end end
微妙だなあ。型が無いと、どう頑張っても効率的なコードは出来そうにない。
I'm writing backtrace functions. If you have any idea of it, please teach me.
飲み会の件のメールがはねられたので,こちらに辿ってきたら丁度書き込みが.(^_^; 空き時間等はどうなってますか? できれば後はメールで打ち合わせをしたいと思ってます
パターンマッチは単一の値だと面白くないんじゃないすか。構造をdestructuringして、そのうちの一部を即値や型とマッチさせて他を変数にバインドする、みたいな場合は、パターンマッチだと一発ですが手で条件を記述すると大変。
Gaucheのutil.matchが生成するコードもそんなもんですよ。でも手で書いたってどうせ同じ操作をかかなくちゃならないので、効率が悪いということはないと思います。単純な例なら(手書きなら省けるかもしれない)ローカル変数束縛フレームが入ることで若干性能が悪くなる可能性はありますが。
たとえば以下はGaucheのcompile.scmでquasiquoteをトラバースしてる部分の骨格ですが、この条件マッチを手書きで書くのは結構面倒です。
(define (quasi obj level) (match obj (('quasiquote x) .......) (('unquote x) .....) ((x 'unquote-splicing y) ;; `(x . ,@y) .......) ((('unquote-splicing x)) ;; `(,@x) .......) ((('unquote-splicing x) . y) ;; `(,@x . rest) .......) ((x 'unquote y) ;; `(x . ,y) .......) ((x . y) ;; general case of pair .......) ((? vector?) .....) ((? identifier?) ......) (else ......)))
やっとコミった。7月中はマージしたかったんだけど、スタック構造変えるので20日かかったのか... orz 途中でいろいろあったけど。
バージョン管理システムが使えないのが一番辛かった。いや、使うべきだったんだとおもいますが、どうやったらうまくできるのかわからなかったので、無しで無理やり。
AMD64 で全然動かないなあ。明日学校に行って仕上げてしまおう。
理由がわかった orz
file1.c: VALUE hoge(){...} file2.c: ... VALUE v = hoge(); ...
hoge のプロトタイプ宣言してなかった orz
青木さんの本と咳さんの本を注文。
ぐぅ、勘違い。
si と di を変数に割り付けることができた。
しかし、あんまり速くなってない orz
どうしたもんかな、これは。
投票更新。
http://www.namikilab.tuat.ac.jp/~sasada/diary/vote.cgi
Ruby2.0BlockParameterNotation に、利用例を入れてみた。
頭が悪いので、実際に書いてみないとわからん。
というわけで、スタックを分けることにしたんだけど、遅くなった。
コントロールフレームポインタ用の cfp と、プログラムカウンタ用の pc をレジスタに割り付けようとしたら、gcc にお断りされてしまったため。cfp がレジスタに割り当てられた。
今までのように pc がレジスタにわりあたっていないため、遅い。
でも、メソッド起動だけを勘定すると、結構速くなったので、いいか。
loop のような、単純な操作が遅くなった。それに伴い、ackermann とかの単純な例が遅くなった。
まぁ、いいか。メソッド起動を早くするのが重要なんだから。でも、速くなったといっても、ちょっとだけだなぁ。
AMD64 の上で 32bit windows を動かして、その上で VMWare かなんかで 64bit な OS は動くんだろうか。モードを良く知らない。
とうとう寝坊してしまった。でも、今日はリアルタイムの話らしいので、あんまり興味が無い。午後はまた違うのかな。
GC のテストってどうやって書いたもんかなぁ・・・。
def proc(&pr) pr end def m a = 1 m2{ a } end def m2 b = 2 proc{ [yield, b] } # m に渡された block も proc 化される (1) 100000.times{|x| "#{x}" } # ここで、(1) の proc が GC される yield # 存在しない proc (block) を呼ぼうとして死ぬ end m
32bit Winは動きますが、vmwareは32bitアプリケーションで、64bitOSは動きません
なるほど、ありがとうございます。となると、やるなら 64 bit OS 上で VMWare 動かして・・・なんだろうか。
はい、vmwareは64bitOS上(Windows/Linux)で正常に動く32bitアプリケーションです。vmwareそのものは64bitネイティブではありません。
mixi にエントリ作れないけど、若者なら若手の会に行くだろ。
今日も英語がわからず大変悲しい思いをした。
yarv のビルドの時間が30秒弱から1分にふくれてしまった。どうしたもんだか。
眠いよー。全然終わんないよー。
Java に「カレントディレクトリ」ってないんですかね?
本郷キャンパスは2度目だったんだけど、ほんとに歴史を感じる建物が多いんですね。なんか木が鬱蒼としていたところもあったし。
そして予想通り迷って、3分前くらいに到着。席は一杯。しょうがないので一番前に座った。
レクチャー自体は英語がわからず半分も理解できなかったんだけど、なんとなく面白かった。
Vista は NT のバージョン何になるのか聞いたら、知らない、とのこと。
スタバで2時間粘ってやっとのことでコンパイルを通した。でも、本当にそれだけ。
System.getProperty("user.dir")で得ることはできます。変更する機能については、「マルチスレッド環境でcurrent directoryが何を意味すべきか、という議論の結果、割愛された」と記憶しています。
いつもありがとうございます。まさに、マルチスレッド環境において、カレントディレクトリをどう対処しているのか知りたくて探してました。なるほど、Java はそうなのか。
本郷は、でもずいぶん旧い建物を建て替えちゃったんじゃないかなあ。
新しい建物もたくさんありましたね。
昨日は ML の勉強ができて大変有意義だった。
# (1, 2);; - : int * int = (1, 2)
となって、(1, 2) の型が int * int なのは、やっぱりよくわからないなぁ。理屈はわかったけど、あえて (int, int) と書かなかった理由がわからない。
# ((1, 2), 3);; - : (int * int) * int = ((1, 2), 3)
となって、((1, 2), 3) の型は (int * int) * int と、結局括弧を使うんだから(でも、デリミタは * か)。何か深い理由があるんだろうか。
地震は怖かった。
田中さんは面と向かって人に文句が言えるのが凄いと思う。
第38回 情報科学若手の会。是非ご参加をご検討ください。
星のダンスを見においで 読了。
明日は東大。
def getproc &pr pr end pr = getproc{ p $SAFE } $SAFE = 1 pr.call 1.times(&pr)
スタックフレームを作るために 8 word 積めばいいなぁ、と思っていたら、どう考えても 10 word 必要っぽい。いや、1 word は無くても今はいいんだけど、scheme 作ることとか考えると必要っぽい(base pointer)。
というわけで、困ってしまったんだが、困らないでさっさと 10 word で作ってしまったほうがいいような気もする。
さっさと動かしてから考えたほうが、と。
頑張ればあと一個くらい減るんだけど。
理由になるかわかりませんが、(int, int)は
type ('a, 'b) fuga = 'a -> 'b list;; type hoge = (int, int) fuga;;
みたいなとき使います(型のタプル?)
haskellでは (Int, Int)みたいに書くし、単なる慣習という気がします。意味が直積なので int * int というのは素直だと思いますけれど。
「*」は二項演算子に見えるのに、実際には「int*int*int」は「(int*int)*int」とも「int*(int*int)」とも異なっているのが、なんだか奇妙に感じました。
"直積だから" という理屈はわかるんですが、(,) でもいいのに * にしたという理由がわからない、という意味です。
いや、直積ならば (,) よりも * で表現する方が自然でしょう。
ふーむ。
(,) は内積。
参考までに:「どうして ocaml って list 'a と書かないの?」「Milnerにきいてくれ by Xavier Leroy」
そ、そーなのか……
camlp4r を使うと list 'a って書けるんですけどね。→拙訳 http://www.jmuk.org/~mukai/camlp4tut.html#label-63 あたりを参考に。それでもタプルは*のままですが……。
未踏ユースとおったらしい。あれは通るよねぇ。ふふふ。
エンダーのゲーム読了。大体オチは読めるんだけど、最後の最後、ゲームの風景の再現は良かったなぁ。
たのしみですねえ。
Java はテストコードを書くのが面倒でいやだね。
class Te{ static void main(String args[]){ int i = 10; String str = "" + i; } }
static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: new #2; //class StringBuffer 6: dup 7: invokespecial #3; //Method java/lang/StringBuffer."<init>":()V 10: ldc #4; //String 12: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer; 15: iload_1 16: invokevirtual #6; //Method java/lang/StringBuffer.append:(I)Ljava/lang/StringBuffer; 19: invokevirtual #7; //Method java/lang/StringBuffer.toString:()Ljava/lang/String; 22: astore_2 23: return
StringBuffer#append(I) というのがあるのね。なるほど。
arton さんおすすめの String.valueOf。
class Te{ static void main(String args[]){ int i = 10; String str = String.valueOf(i); } }
static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: iload_1 4: invokestatic #2; //Method java/lang/String.valueOf:(I)Ljava/lang/String; 7: astore_2 8: return
なるほど、少ない。
でも、多分(速度を気にしなければいけないところじゃないと)私は ""+i を使いつづけるんだろうなあ。
参考
class Te{ static void main(String args[]){ int i = 10; String str = "abc" + String.valueOf(i); } }
Compiled from "te.java" class Te extends java.lang.Object{ Te(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."<init>":()V 4: return static void main(java.lang.String[]); Code: 0: bipush 10 2: istore_1 3: new #2; //class StringBuffer 6: dup 7: invokespecial #3; //Method java/lang/StringBuffer."<init>":()V 10: ldc #4; //String abc 12: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer; 15: iload_1 16: invokestatic #6; //Method java/lang/String.valueOf:(I)Ljava/lang/String; 19: invokevirtual #5; //Method java/lang/StringBuffer.append:(Ljava/lang/String;)Ljava/lang/StringBuffer; 22: invokevirtual #7; //Method java/lang/StringBuffer.toString:()Ljava/lang/String; 25: astore_2 26: return }
まぁ、自明ですが。
テストコードが書きづらいなんていっておきながら、自分でやる java の作業なんて(バイトじゃなければ)main の中身を書く -> コンパイルする -> javap でバイトコードを見る、なんだから、main 中身を書いた時点でてきとーにクラス作ってコンパイルして javap する何かを作ればいいんだよな。
ただの怠慢だった。
ルパンってこんなハリウッドっぽかったっけ?
型に重きをおく言語で、がんばれば HTML とかのサニタイズの問題は解決する?
PTT。浅学で、はじめてスタッキングファイルシステムというのをきちんと認識した。
しかし、Ruby でも << じゃなくて += で文字列結合することって多いよね。
...もしかして、俺だけ?
いや、もちろん性能を気にするときには考えますが。
うーん、でも、見た目から効率はあんまり判断できないよなー。
そういえば、Java のコードで、toString 書くの面倒で、"" + 1 とか書いてたんだけど、これはどうなんだろう。
エスケープ済とそうでないのとを別の型にしてれば(実際意味的には別だし)コンパイラがチェックしてくれるかな。
そうそう。そんな感じ。で、どこまできれいなシステムができるんだろう。
いかにも Haskell な人が作りそうな……
っていうか、それはString.valueOf(1)がお勧め。Rubyだとto_sだからかな。ちなみにnew Integer(1).toString() は却下。
なんか、時が移るのは早いね、という感想が多いな。
なんか、今回はレスポンスが多いなあ。先月と何が違うんだろう。
indirect threaded code の意味を間違えていた。気づけてよかった。
Rubyist のための他言語探訪 【第 1 回】 Python を読んで混乱した話。
イミュータブルな文字列
Python では文字列を書き換えることはできません。効率を考えるとうれしくないのですが、オブジェクトの書き換えは面倒を引き起こすこともありますから、うれしくないことばかりでもありません。
効率を考えたら immutable な文字列のほうが効率的だよなぁ、と思ったら、うささんに「bang なメソッドが使えるからより効率的」と言われた。
うーん。
http://www7.ocn.ne.jp/~cabinas/ とりあえず、ここが安そうなので、初めてのカプセルホテルに挑戦。
はじめまして。博多で一泊ですか? もしお時間があれば,
こちらで飲み会を企画して、YARVの話をしてもらうかわりに、宿泊費カンパを募るというのはどうでしょう?
bangなメソッドと、部分文字列の共有と、どっちが嬉しいかしらん。
十全とはいきませんが、宿泊費くらいはなんとか。ただ、できれば安い宿を教えていただけると ^^; 話すのはなんでもいくらでも・・・。その辺どうしましょう>たむらさん
どうなんでしょうねぇ>共有 scheme は immutable でしたよね。
そうでもなかった>scheme
今、R6RSでunicode supportをどうするかで紛糾してるんですが(srfi-75)、「immutableにするか、length changing mutationをサポートしないと意味ないよー」と控えめに主張してます。
あ、申し遅れましたが、むかし未踏に参加していた新井といいます。 安い宿は楽天トラベルあたりで探すと良いかとおもいます。 プラザホテルなどは割と安く、場所が便利なのでよいですね。
話していただけると嬉しいです。 福岡のrubyistが喜ぶとおもいます。
http://www.moodindigo.org/blog/
immutableな文字列に関しては、当然実行するプログラムによって優劣が変化するのだと思うのですが、それはともかくとして、一般論としてこの優劣について検証した事例はあるんでしょうかね(私は研究者じゃないので論文が読みたいわけじゃなくて結論が知りたいだけですが)。
Java
文字列のmutabilityと優劣: 問題に激しく依存するでしょうね。あと、マルチスレッドかどうかとか。ただ、mutableな言語でもコピーしてる場合が多そうだから、共有できると効率は上がるかも?
あ、忘れてた>8/5 おまけに奥さんの実家に行ってていないし。 とりあえず関係者にメールして 8/5の予定聞いときますね。
Ruby は共有出来るところはしてますね。オブジェクト(ID)は全部違うけど。
旅費振込み完了。
あと、福岡の宿一泊分探さないと。
Universal Studio Japan みたいなのがブラジルにあったら USB になるんだろうか。
Rubyist Magazine 0008 is Released!!
毎月結構大変なんですが、リリースするときはいつも嬉しいものであります。
でも、ネット上での共同作業なので、さぁ打ち上げだ、ということが出来ず、ちょっと残念。
今回のやーまには direct thraeded code の解説だったんだけど、なんというか、重箱の隅というか。
るびま、読んでもらって何ぼなので、何卒宣伝のほど、よろしくお願いします。
昨日は懇親会、2次会といろんな話を聞いた。
しかし、2年後本当に何してるんだろうね、俺は。
サイコロジカル読了。
実は、Gauche の gauche.parameter、parameterize が全然理解できていなかったんですが、やっと理解できました。
不思議だったのが、
(define a (make-parameter 1)) (a) ;=> 1 (define (f1) (a)) (f1) ;=> 1 (define (f2) (parameterize ((a 10)) (f1))) (f2) ;=> 10
と、dynamic scope みたいなことが何故出来るのかなぁ、ということだったんですが、
(define (f3) (let ((a (make-parameter 100)) (parameterize ((a 10)) (f1))))) (f3) ;=> 1
となって納得。
thread-specific, thread-specific-set! は key を与えられないのね。与えられたほうが色々と楽だと思うんですが。
thread-specificはsrfi-18でそう定義されてるからですが、たぶん意図としては「alistでもhashtableでも好きなのを入れといてね」ってことなんだと思います。Scheme界ではそのへん、アプリ製作者の裁量に任せちゃうことが多いので、不親切っていえば不親切ですね。
はい。意図は理解できますが、たとえば、別作者による複数の module 内で使いまわすのは無理そうですね。
そーなんですよねー。ただkeyとvalueのペアを持てる、というふうにsrfiで決めちゃうと、今度は「keyは何にする? symbolのみ、それとも任意のオブジェクト?」「任意のオブジェクトの場合、何で比較する? eq? eqv? equal?」「全てのキーの一覧を取るAPIは?」等々、細かい議論が噴出して、本来の議論(srfi-18で言えばmultithreading)が霞んでしまうのがScheme 界の常。たぶんこういう「一個だけ値を持てるスロット」の使い方に関するsrfiを別に作る、という方向がScheme的なのでしょうなあ。
なるほどねぇ。まぁ、gauche 内では specific じゃなくて parameter を使えということなんでしょうけど。
まだスライドが出来ていない。
無事発表終わり。
質問がなくてさびしかった。
BioRuby + ChemRuby の話がすげぇ楽しかった。
で,日曜日,17日に未踏のキックオフがあるんですが,懇親会が4750円らしい.orz
とりあえずスライド作らないとなぁ.
8/5 の宿を探さなければ。
今回のインタビューは長いよー。とても長い。
今日、家に帰るかどうか悩む。
電車で行けば帰れるんだろうけど。どうせ明日も通学しないといけないしなぁ(だめな発想)。
これは昨日だけど,グインサーガ100巻読んだ.やっと追いついた,と思ったらもう101,102が出ている orz
忙しいのがとりあえず通り過ぎたらなんとも怠けきっている。なんとかしないと。
def tag_encoding str ret = '' begin ret += Iconv.iconv("UTF-8", "Shift_JIS", str).join rescue Iconv::IllegalSequence => e ret += e.success.join + '?=iconv_error=?' str = e.failed[1..-1].join retry end ret end
こんなふうに逃げてみた。もっとスマートな解決方法があるんだろうけれども。
ちなみに、駄目だったのはShiftJIS(のどれか)のIIIとかII。
一日るびまの記事を書く。スタバで缶詰でいいとおもったら、うるさすぎ。結局、ショッピングモールみたいなののテーブルとベンチで6時間くらい書く。バッテリーもつ T4 万歳。
2005-07-17: 未踏17キックオフセミナー@東京]。あるそうです。
ところで、今日、というかさっきタイムテーブルが届いたんですが、このウェブの掲示は 7/8 らしい。
ここ数日、RSSの生成ができてないようですよ。この日記。
あ、ほんとだ。どうしたんだろう。
iconv でエラー吐いてた。iconv をてきとーにするってどうやるんだっけ。
"Shift_JIS"の代わりに"CP932"を指定すれば、Iconvの実装にもよりますが、多少よくなるかと。
Iconv.conv("UTF-8", "Shift_JIS", str)
「変換できない文字はブロックに渡して処理」とかも考えてはみたものの…。
Iconv.conv は Iconv.iconv(...).join の省略形じゃないんですか?>Rubyリファレンスマニュアル - Iconv
sydney ってなんだろう、また新しいのが出てきたのかよ、とか思ったら機能追加なのね。
自宅がB-Fletsになった。今までADSLルータだったのが、無くなったのでファイルサーバを急遽ルータとして使えるようにした。
PPPoE とか DHCP とか、
ちなみに、外向けのNICが10Mのやつしかなかったので、外向きの回線速度は大変遅い。でも、今までのADSLよりちょっと速いくらい。
問題なく使えそうなので、このままでいいや。
セントラルホテル武雄というところが適当なのかなぁ.でも,一日6000円か.前泊しようとすると18000円.うーむ.
誰かエクストラベッドに寝かせてくれる人はいませんか orz
[swopp-announce:06377] 特別講義のご案内
うおー,これは行かなくては.こういうのができるから東大は凄いよなぁ.
やっと TODO が無くなった.あとはひたすらチェックするだけ.あと7時間.7時間もやりたくないけどな.
そういえば,まつもとさんの集中講義があるんだっけ.もぐりに行くのは無理そうなんで行かないですが,誰かレポート希望.
実装の話を 聞きたい 教えてもらいたい.YARVを49倍速くする方法.
言語のデザインの話は,面倒だからいいや.
あと5時間.あと5時間たてば,YARVでやりたかった実装に手をつけることが出来る.でも,その前に寝るかな.
Scheme は実装が沢山あって,メインストリームになるのはとても困難だと思うが,Ruby はちょっとしか無いから楽だよな.
出した.
そしたら,回答文のところに論文をアップロードしてしまったらしく,回答文は再アップロードできない.
なんてこった.とりあえず,メールしてゴメンナサイしてみる.
しかし,論文をアップロード,の欄に入れたはずなんだがなぁ.寝ぼけてたのかなあ.
僕は武雄温泉近くの旅館だけど、それでも6,000円/泊くらい。
ネットができるビジネスホテルは無さそうですねえ.ところで,会場はネットワーク引いてるんですか?
ログ見たら寝てないようですけど大丈夫ですか?
会場には無線LANを設置すると思います。けど、使う人数が人数なので、あまり期待しない方が。
駄目です.ところで何のログだろう.
なるほど.まぁ,メールくらいはたまにチェックできそうですね.
マシン構成を考えると夢広がる。夢だけ。
で、
みたいにずらそうかな、とか。そうなると、Cel 1.4GHz が余るな。Socket 370 のちっちゃい箱を買ってきて、家族用マシンにするか。
しかし、探してみるとC3ってもうあまり売ってないのね。Erza というのが欲しかったんだけど。
VIA EPIA-ML8000A を買うというのも手かもしれんが、入れるのは ATX の箱だからなぁ。
うぅ、Socket370 のマザー(MicroATX)、高いのしかもう売ってないのな。どうしよ。
http://www.jetway.com.tw/evisn/product/socket370/625EMP/625EMP.htm これを買ってしまおうかなあとか考え中。
へー。hash に乱数が使われるようになったのはセキュリティが理由だったんだ。
from 天泣記
hash の何に乱数を使ってるんですか?
次の RHG は ML 処理系.HSP, なでしこから ML という流れが素敵だと思うんだがどうか.
Ruby勉強会@関西のように,もっと Ruby でわかりやすい話題を取り扱ったほうがいいんだろうか.やったほうがいいんだろうなぁ.でもまぁそれはRHGじゃないよな.
別枠でそういう機会を設けられるかというと,難しいかも....
Ruby 初心者・初級者講習の需要ってどれくらいあるものなんですかね.そういうのってどこで聞けばいいんだろう.
そういえば,北海道はどうだったのかな.
シミュレータというのは便利なんだけど,時々はまる.
ボトルネックがわからなくて,パラメータを増やしても,結果が変わらない.で,結局あげていたパラメータとは別のところがボトルネックだったという.
今のシミュレータの使い勝手がダメダメってのもあるんだけれど.しかし,どうしたもんかな.自分が作っていない,メンテしていないソフトは,やっぱり難しい.さぼっていたツケが回ってきただけとも言うが....
少なくとも,シミュレータのパラメータを変えるのにいちいち再コンパイルが必要なのが駄目.
論文のネタが,評価結果について,どうにも自分の主張と違っているんじゃないかと思い始めて.もうこれは論文取り下げにするか,とまで悩む.
他の視点で評価を取り直して,どうやらこの主張はとくに間違っていなかったようだ,というこを確認する.よかったぁ....
あとは,もうひとつの不思議を説明するだけなんだが,これがまた,どうやったもんだか.
こんなもんかな.
SWoPP,佐賀空港経由だと到着が12:30,福岡空港経由だと11:30.当日の朝から行くには,前泊しないといけないが,どうしようかなぁ.
あ,福岡空港経由なら朝の5時に出れば10:30には行けそうだ.途中の電車賃高いけど.
調べるととても金額が高い時期なんだなぁ>SWoPP.うぅ,学生に優しくない.
http://developers.slashdot.org/comments.pl?sid=155225&cid=13013341 笑った。
spam fileter を導入したい気がするんだけど、怖くて導入できないんだよね。
TB でジャンクメールと判断したら、自動的に迷惑メールフォルダに移動してもらいたいんだけど、できないなあ。
googleで「メソッド」を検索.世界で一番のメソッド.
I updated vote entry. Please select one.
しこしこと,論文にきた,大量の採録条件(本当に大量で,回答書だけで10ページ越えるんじゃないか)の回答方法を考えているんだけど.
考えるのは楽しいし,プログラムで検証するのもそんなに苦じゃないんだが,文書にしてまとめて回答書にしたり論文に書き加えたりするのがどうにも辛くて辛くて.なんとなく,息を止めて走りきる感覚.それは,いつものことか.
まぁ,考えるだけだったら自慰行為に過ぎないので,しょうがないんだけど.
「平方行列」とか書いてたんだけど,ぐぐったらちょっとひっかかるな.
ふと,moeclipse という言葉が脳裏に浮かんだ.まだぐぐっても関係ないのが一件しかひっかからない.チャンスですよ!
なんとなく,mr (rucheme 用対話環境) を思い出して,思いついた.
自宅のサーバマシンを低消費電力マシンに置き換えたいなぁ,ということで,物色.C3 にするか,Geode NX にするか.マシンパワーは要らない(今は Celeron 433で,それで満足)ので,トータルで安くて熱くならなくて電気代食わない奴がいい.
control stack frame と stack を分けたんで,せっかくなんで stack gc でやりたいなぁ,などと思う最近.でも,どう考えてもうまく行かない罠.
などと考えて論文がさっぱり進まない罠.やりたいことは,Proc のためにスタックに置いてある環境を追い出すタイミングを出来るだけ遅らせたいってことだったんだけど(スタックGCのタイミングまで遅らせれば一番いい),うまく行かない.
実は,組み合わせるべきはスタックGCじゃなくてスレッドローカルGCなんだろうか.
あれー,なんか変なこと書いた気がするな.まぁいつもの事か.
stack gc と環境の話は別ぽい.
ライトバリアで引っかかったときにはじめてコピー,がいいのかなぁ.ライトバリアがますます重くなるな.
if(ヒープにある){ if(procである){ if(はじめてのライトバリアである){ スタックをコピー } } ライトバリア }
家族が数万円かけてExcel講習を受けるといいやがった。絶対無駄だ、と言っても行くといいはる。うーむ。
しかし、久々に雨でびしょびしょになった。数年ぶり。
朝日新聞夕刊の一面に、「裾野広げるなでしこ」と大見出しがあってびっくりした。
そういえば,高橋さんご馳走様でした。あれ楽しみにしています。
■-fno-reorder-blocks の評価
評価環境は gcc version 3.4.4 (cygming special).
評価プログラム:
#define LIKELY(x) (__builtin_expect(x, 1)) #define UNLIKELY(x) (__builtin_expect(x, 0)) #define amsg(msg) asm volatile ("; # " msg) int main(){ volatile int v = 0, w; if(UNLIKELY(v)){ w = 1; amsg("true"); } else{ w = 2; amsg("false"); } }
一般に,条件分岐は,あたりそうなほうを先に持ってくると有利と gcc は x86 において判断するらしい.
gcc -O2 におけるコンパイル結果:
_main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp call __alloca call ___main movl $0, -4(%ebp) movl -4(%ebp), %eax testl %eax, %eax je L5 movl $2, -8(%ebp) /APP ; # false /NO_APP leave ret L5: movl $1, -8(%ebp) /APP ; # true /NO_APP leave ret
LIKELY(v) == 0 というのは,偽になりやすい,と判断し,else 節が前に来てい る(false,true).
そこで,-fno-reorder-blocks を追加してコンパイルしてみる.
_main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp call __alloca call ___main movl $0, -4(%ebp) movl -4(%ebp), %eax testl %eax, %eax jne L2 movl $1, -8(%ebp) /APP ; # true /NO_APP jmp L3 .p2align 4,,7 L2: movl $2, -8(%ebp) /APP ; # false /NO_APP L3: leave ret
ベーシックブロックの順番が,プログラムどおり(true,false)であることが わかる.ret のコピーも無い.
一般に,分岐されやすい基本ブロックを手前に持ってくるのはどういう理由なん だろう.考えられるのは次のとおり.
ちなみに,YARVの経験では,分岐されにくいほうの基本ブロックはあさっての場 所に行っている気がする.
繰り返しについてどうなるのかも調べてみる.
#define amsg(msg) asm volatile ("; # " msg) int main(){ volatile int i; for(i=0; i<10; i++){ amsg("loopbody"); } return 0; }
gcc -O2 でのコンパイル結果:
_main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp call __alloca call ___main movl $0, -4(%ebp) jmp L8 .p2align 4,,7 L10: /APP ; # loopbody /NO_APP movl -4(%ebp), %eax incl %eax movl %eax, -4(%ebp) L8: movl -4(%ebp), %eax cmpl $9, %eax jle L10 leave xorl %eax, %eax ret
そして,-fno-reorder-blocks:
_main: pushl %ebp movl $16, %eax movl %esp, %ebp subl $8, %esp andl $-16, %esp call __alloca call ___main movl $0, -4(%ebp) .p2align 4,,15 L8: movl -4(%ebp), %eax cmpl $9, %eax jg L7 /APP ; # loopbody /NO_APP movl -4(%ebp), %eax incl %eax movl %eax, -4(%ebp) jmp L8 .p2align 4,,7 L7: leave xorl %eax, %eax ret
なかなか効率の悪そうなコードを吐いてくださる.
コンパイラにほしい機能として,「こっからここまではこの最適化オプション」というのが指定できるといいのになぁ.
関数単位でもいいし,プログラムのある範囲で指定できたらもっといい.
でも,そんな要求はほとんどナサゲ.
super() はブロックをパスする.これは,よくないと思うんだけど,どうなんでしょうか.
たとえば,こんなときとか.
class H < Hash def initialize @nanika = yield super() # 別に渡したいわけじゃない end end h = H.new{ # } p Marshal.dump(h)
インテル® Pentium® 4 プロセッサおよびインテル® Xeon™ プロセッサ最適化リファレンス・マニュアル より引用.
静的予測
BTB (「分岐予測」の節を参照) 内に履歴がない分岐は、静的予測アルゴリズムを使って予測される。Pentium 4 プロセッサ、Pentium III プロセッサ、Pentium Kプロセッサは、以下のような同じ静的予測アルゴリズムを使用する。
うーん.flag という変数名は良く使うなあ.
#include <ruby.h> volatile __thread int gt; volatile int g; VALUE test_te(){ gt = 10; return 0; } __attribute__ ((noinline)) void inc_gt(){ gt++; } __attribute__ ((noinline)) void inc_g(){ g++; } VALUE test1(VALUE self, VALUE x){ int i; int n = FIX2INT(x); for(i=0; i<n; i++){ inc_gt(); } return 0; } VALUE test2(VALUE self, VALUE x){ int i; int n = FIX2INT(x); for(i=0; i<n; i++){ inc_g(); } return 0; } void Init_te(){ rb_define_global_function("test1", test1, 1); rb_define_global_function("test2", test2, 1); }
を作ってみた.dll な TLS の評価.
TLS : real 0m2.180s Global: real 0m0.938s
うげえ,おせえ.
どうしたもんかなぁ.
DLL なやつは,Ruby を使う奴は ruby 用の領域を撮っておいてもらおうかなあ.
AMD64 with Linux amd64 2.6.8-1.521
TLS : real 0m13.460s Global: real 0m3.373s
遅すぎ.
どうしよう.
pthread をリンクしてないからなだけかも.
pthread_getspecific とかでやってみようとしたらアボート.
文字コードの話はさっぱりわからんのう.
YARV: Yet Another Ruby VM のページをやっとアップデート.0.2.1 は,とても地味(利用者的には何も変わらない)だけど,結構沢山変更した.
a と a() でメソッドネーゾエラーを変えるのは実は地味に面倒なんですが,どうしたもんですかね.
で,考えたのが,行番号とかの情報に混ぜる.
YARV では,命令列 A B C ... とあったとき,それに対応する行番号情報 Al Bl Cl の列を生成しています(それでスタックトレースを生成する.ここ,かなりバグってるけど).
そういうわけなので,そこに,その命令についての注釈みたいな,どうでもいいような情報を入れればいいんじゃなかろうか,と.しかし,うまくいくのかなあ.うまく行くと,今より正確な情報が出せるんだけど.
で,それを利用すると,もっと色んな情報を命令列から外に追い出すことは可能になる,かもしんない.
Multi-VM にしたとき,rb_cObject とかどうするの,という地味で破滅的な問題に思い至った.API を増やして,「今後はそれを使ってください」でいいんだけど,全部書き直しが必要になるわけで.
うーむ.
#define rb_cObject (GET_VM_INSTANCE())->basic_classes[idx_of_cObject]
なんか,Ruby が随分と遅くなりそうだなぁ...
Subversion であるファイルをバージョンコントロール下からはずすにはどうすればいいのかな.svn rm しか無いかな.リポジトリに直接 rm するのは URL 書くのが面倒くさい.
しかも,ワイルドカード効かないし.どうしよ.
checkout して,消してコミットして co したのも消せばいいのか.どうにも working copy は(各マシンで)一個しか持たないという運用しかしたことがなく.
考えて見たら,svn はファイルを rm しても db にはそれが残るんだね.だから,
とやっても,リポジトリは大きなままなんだなぁ.しまったなぁ.
バックアップ用のディスクがもう一杯.どうしようかな.svnリポジトリのバックアップに pdumpfs は使えないなあ.
今朝はジョナサンで徹夜.
ピザを頼んだら予想以上にでかくて難儀.一緒にソーセージまで頼んじゃったから.
1200円なり.うぁ,厳しい.財布が.
うおー,もう七夕かよー.この論文の日々が報われる日が来ますように.
Rubyでカリカリにチューンしたコードを書くのも楽しいですが,Rubyをカリカリにチューンするほうがもーっと楽しいです.
うわー,sicp 明後日か.行けねえ orz
TLS (__thread とか)について調査.グローバル変数と速度差を見る.実はあんまり違わなかった(debian sarge).
誰か,もうちょっと詳しい調査知ってる人いませんか?
TLS は,ruby with native thread で使いまくりっぽいので.
YARV 0.2.1 released。なんとか七夕リリース。
リリース告知は明日。
pdumpfsでやってたのかー。
自分はpost-commitでsvnadmin dump --incrementalしたやつをbzip2で圧縮してhttpsで取得 できるところにおきつつ、リモートのバックアップマシンにGPG署名したメールで通知してます。
というか,HOMEをバックアップしてて.その下にリポジトリを作ってました.
リポジトリから消したいならsvndumpfilterで。
送りますた.そして帰れないこと決定.今日は布団で寝たかった.
さて,そして今度は7/11だ.
bash --login で対話的シェルを起動するとき、ログインディレクトリとホームディレクトリを分けることは可能だろうか。
なんでそんなことを、ってことかもしれないけれど、xyzzy から、cygwin のコンソール(bash)を立ち上げたくて。立ち上げるとホームディレクトリじゃなくて、xyzzy のカレントディレクトリに居て欲しい。
DOS窓の起動はそれで出来てる(run-console)なんだけど、cygwin - bash をそんな感じで起動したい。
環境変数HOMEをそのディレクトリにしてbashを起動して、起動スクリプトで CYGWIN_HOME みたいなのを参照して HOME の設定をやりなおす、みたいにしないとあかんかな。-c でディレクトリ移動してもすぐに終了しちゃうしなぁ。
.bash_profile に cd LOGIN_DIR と加えて解決。
(defun my-run-cygwin-console () (interactive) (call-process "bash --login" :no-std-handles t :show :show :exec-directory nil :environ `(("LOGIN_DIR" . ,(default-directory))) ) ) (global-set-key '(#\C-x #\c) 'my-run-cygwin-console) (global-set-key '(#\C-x #\d) 'run-console)
しかし、bash --login はなんか重い(/etc/profileで何やってんのかよくわからん)ので、~/.bashrc をきちんと作って bash -i で起動するようにした。
(defun my-run-cygwin-console () (interactive) (launch-application "cmd /c bash -i")) (global-set-key '(#\C-x #\c) 'my-run-cygwin-console) (global-set-key '(#\C-x #\d) 'run-console)
なんか、これだけ悩んだのになぁ。
emacs のキーバインドで "\C-2" とかやると怒られる。どうするんだべー、と思って探してみると、"\C-@" で "\C-2" みたいになるらしい。なるほどねえ。
と思ったら,なんかだめだめだったので,[C-数字]はあきらめて,[fx] (ファンクションキー)を使おう.
xyzzy 用にもう一個作ってみた.
(global-set-key '(#\C-c #\C-r) #'(lambda () (interactive) (let* ((file "~/src/rb/t.rb")) (if (or (and (get-file-buffer file) (set-buffer (get-file-buffer file))) (find-file file)) ;; insert (progn (goto-char 0) (insert "\n\n__END__\n") (goto-char 0)) ))))
これは,私が毎日やってること.
うがー,なんだこのプログラムはー!(RubyConf 2005 Agenda)
もう1時間も喋れないから20分枠をクレって言ったのに! 言ったのに!(書いたんだけど)
20分しか喋んなかったら怒られるんだろうか・・・.
日本人沢山居るから,日本人になんか喋らせよう.
国立で中華.ご馳走様でした.おいしかったです.
また3時間寝てしまった.
x,y 双方が SPECIAL_CONST_P() で真かどうかを判断する最も効率的な方法は何か.
((x | y) & 3) | ~(x | y) くらいがいいんだろうか.
method(x, y){<a, b> ...} method x, y do <a, b> ... end
うーん.囲むので残ってるのは <> だけか.あ,
method(x, y){[a, b] ...} method x, y do [a, b] ... end
って,配列やん.
いっそ,
method(x, y){((= a, b =)) ...} method x, y do ((= a, b =)) end
うが,気づいたら4時.あと20時間.
現状では,VM 関数のコールグラフはこんな感じ.
Top VM (setjmp) *1 f() rb_funcall() VM (setjmp) *2 g() raise()
g() が raise した場合,*2 でハンドリングする.
ところで,これを
Top VMe (setjmp) *1 VM f() rb_funcall() VMe (setjmp) *2 VM g() raise()
のように実装すると,実装が単純になったりするだろうか.するような気がする.どうしようかな,こんなふうにしてみようかな.うーん.
結局 VMe に VM がインライン化されて同じだったりして.オーバーヘッド的には変わらないかなあ.プログラムの見通しはちょっとよくなるかな.
VMe と VM の間は2返戻値法でやるのかなぁ.面倒なだけな気がするな.うーむ.
VMe(){ PUSH_TAG(); if(setjmp() == 0){ vm_redo: v = VM(); } else{ 例外処理ハンドラを探す if(例外ハンドラ発見){ goto vm_redo; } else{ POP_TAG(); JUMP_TAG(); } } POP_TAG(); return v; }
今はまったく同じことを1関数内で goto 使ってやっている.
明るくなってしまった.
うわー,6時だ.
うわー,7時だ.
結局13ページでまだTODOが残ってる.どうしよう.
今日も松屋.贅沢だ.
うわー,8時だ.
...決して暇なわけではない.
そういえば,人のソースは見ることがあるけど,人の ChangeLog は見ることが無いな.
目がしょぼしょぼする.
わー,9時半だー.
YARV は GC がちょっと速くなるらしい.しらなかった.
昼飯が600円の弁当.なんて贅沢なんだ.
うわー,もう3時か.
あまりに眠かったので,5時まで眠った.
python を書いていてはまること.
インデントは意外と心地よい.
あー.
のは駄目駄目だ.
perl はかいてて気分が悪くなってきた.
あと8時間.
結局14ページ.
今日は帰りたいなあ.
うあ,雨だ.
やっぱり書いたばかりの文章は客観的に読めない.寝かせる期間がホスィ.
ところで,論文とかを svn で管理するようにしてみた.どうかな.
ノートと学校と家で,情報の共有がやりやすくなった,となるといいんだが.
今眠って,起きたら明日だったら目もあてられないな....
12:05の電車に乗れば帰れる...のかな.どうだろ.
うぅ,無理っぽい orz
私も学生のころはcvsで論文を管理してました。
という感じでいこう.誰か博多の人遊んでくれませんか.
http://www.blue-sky.ne.jp/hnd-kusnh 飛行機だけで3.3万円(一泊あるけど,SWoPPの場所じゃない).
リビジョンごとにアーカイブを作ることにした(http://www.atdot.net/~ko1/archive).
今日(今朝,昨夜)はロイヤルホストで缶詰.デニーズより静かだった気もするが,日曜深夜だからというのもあるんだろうな.今日は広い4人がけの席だった.
論文の締め切りでは,なんかいつも魂を削るようなことをしているような気がする.なんとかならないものかな.
計画的に行動できない俺が駄目なだけなんだけど.
AMD64マシンで fmod の値が変(fmod(3.0, 2.0) => 0.0).なんでだろう.
しょうがないので,
#if defined(HAVE_FMOD) && !__x86_64__
なんて書いて逃げる.しかし,なんでだろうなぁ.Rubyのほうは fmod 使っても平気みたいなんだけど.
30,000,000回ループするだけのプログラムのテスト.
#Ruby whileloop i = 0 while i<30000000 # benchmark loop 1 i+=1 end #Ruby times 30000000.times{|i| } #Python for i in range(30000000): pass #Perl for($i=0; $i<30000000; $i++){ } #Scheme (let loop ((x 0)) (if (< x 30000000) (loop (+ x 1))))
実行時間:
Ruby1.9(times) | 11.95 |
Ruby1.9(wl) | 17.71 |
Python2.4.1 | 8.91 |
Perl5.8.6 | 5.56 |
Gauche0.8.4 | 2.87 |
YARV(times) | 4.906 |
YARV(wl) | 1.11 |
YARV は while loop (だけ)を頑張った感じ.
times はやっぱり遅い.yield が重い.
まぁ,VM部分は他のより頑張ったと思うし.
今度は tak.
Ruby | 17.34 |
Python | 11.48 |
Perl | 35.04 |
Gauche | 2.95 |
YARV | 2.39 |
うーん.Gauche 速いなぁ.
インラインメソッドキャッシュとスタックキャッシュの差かしらん.
次,ackermann関数(3, 9).
Ruby | 30.297 |
Python | 15.1 |
Perl | 15.13 |
Gauche | 24.69 |
YARV | 1.57 |
なんかやけに速いな.というか,gauche がちょっと遅い.
ruby | base | dtc | dtc+si | dtc+si+ou | dtc+si+ou+iu | dtc+si+ou+iu+imc | dtc+si+ou+iu+imc+sc | |
app_tak | 17.562 | 6.766 | 6.203 | 3.172 | 3.078 | 2.812 | 2.641 | 2.39 |
loop_whileloop | 16.328 | 8.625 | 8.079 | 2.078 | 1.86 | 1.547 | 1.547 | 1.031 |
so_ackermann | 30.297 | 6.406 | 5.891 | 2.532 | 2.265 | 2.016 | 1.859 | 1.579 |
3時間仮眠.
目が回る回る.ぐるぐるー.
ご飯を食べないと死んでしまう.
食べてきた.論文執筆中は外食を豪華にしてしまってよろしくない.
そして食べたら眠くなってきた.眠ったら死んでしまう.
ruby-core でやってる O(1) の unshift って,どうやるんだろう.途中をすっ飛ばしてるからよくわかってない.
たぶんスタックオーバフローがおきてる>ackermann関数 on Gauche。gosh -fcollect-stats で実行してみそ。
stack overflow: 4916times.22920ms.殆どの実行時間がスタックのコピーですか.
日曜日があれば良かったのに。金曜日の夜は飲み行くとかで遊べますが、 土曜日はムリだなぁ。
ちなみに「博多の女(ひと)」というお菓子がありまする。 http://www.nikakudou.co.jp/hkt-nohito.html
わーい.
http://centrin.net.id/~marc/performance.html - what about running the benchmarks in Qu as well? Could be interesting :)
I have no enough time to measure with it :-(
悔しかったので改善しました http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Gauche%3aVM%a4%ce%ba%c7%c5%ac%b2%bd
おおぉ.方針としては,(1) そもそも,最初からスタックを結構取っておく (2) ハンドラを高速化する (2') 環境の追い出しを速くする (3) スタック伸張時のアルゴリズム・データ構造を変える,とか色々ありそうですが,どんな対策をしたんでしょうか.
まぁ、なんだかんだいってもそんなもんだよね。
デニーズで缶詰。この時間でも人が沢山居るもんなんだなあ。
さて,PROは7/5締め切り.最後まで諦めないぞ.
で,SWoPP の航空券,探してみたけどむっちゃ高いなぁ.どうしよう.
宿は5000円ちょっとか.どうしよう.
class Line def initialize size, line @size = size @line = normalize(line).freeze @all_lines = nil end def all_lines @all_lines || (@all_lines = make_all_lines) end attr_reader :line def make_all_lines fl = @line.dup el = normalize @line.reverse rf = rotate(fl) re = rotate(el) rf + re end def inspect "(size: #{@size} " + @line.inspect + ")" + "\n" + @all_lines.map{|e| "\t" + e.inspect}.join("\n") + "\n\t--" end def to_s "size : #{@size}\n" + "lines : #{@line.inspect}\n" + "all : #{@all_lines.inspect}\n" end def normalize lines bx, by = *lines[0] [[0, 0]] + lines[1..-1].map{|x, y| [x-bx, y-by] } end def rotate lines ret = [] ret << lines # 0 ret << lines.map{|e| [-e[1], e[0]]} # 90 ret << lines.map{|e| [-e[0], -e[1]]} # 180 ret << lines.map{|e| [e[1], -e[0]]} # 270 end def same? obj if all_lines.include?(obj.line) true else false end end end def parse_set lines set_num = lines.shift.to_i set_lines = [] (set_num+1).times{ size = lines.shift.to_i ls = [] size.times{ l = lines.shift ls << l.split.map{|i| i.to_i} } set_lines << Line.new(size, ls) } set_lines end def parse str lines = str.split("\n") $sets = [] while true $sets << parse_set(lines) if lines[0].to_i == 0 break end end end if true parse ARGF.read elsif false parse DATA.read else parse open('B1').read end # require 'pp' # pp $sets $sets.each{|set| e0 = set.shift set.each_with_index{|e, idx| #p "-- #{idx+1}" puts "#{idx+1}" if e0.same? e } puts "+++++" }
酒井君に教えてもらったのでしょうがないから問題Bを解いてみた。合ってるのかな、これ。
最初、0 番目というものがわからなくてあせった(総当りで同じものの組を求めよ、かと思った)。あと、n 要素だと思ったら 0 番目+ n 要素でパーサが狂ってしまって困った。
一番困ったのが折れ線という言葉を知らないからクラス名に困ったということな気がする。Polygonal Line なのかー(英語は眼中になかった人)。
Val = { 'm' => 1000, 'c' => 100, 'x' => 10, 'i' => 1, } def add num, c if num > 1 num.to_s + c elsif num == 1 c else '' end end def encode num ret = '' Val.sort_by{|e| -e[1]}.each{|k, v| a = num / v ret += add(a, k) num %= v } ret end def decode str ret = 0 prev = nil str.split(//).each{|e| case e when /m|c|x|i/ ret += (prev ? prev : 1) * Val[e] prev = nil when /[2-9]/ prev = e.to_i else raise e end } ret end if false %w(5m2c3x4i m2c4i 5m2c3x).each{|str| p decode(str) p encode(decode(str)) == str } exit end def parse str lines = str.split("\n") num = lines.shift.to_i ret = [] num.times{ ret << lines.shift.split } ret end sets = parse(ARGF.read) sets.each{|x, y| puts encode(decode(x) + decode(y)) }
ついつい調子に乗って問題Cも解いてしまった。たったこれだけなのに30分かかるんだなぁ。
しかし、こういう問題をやると思うが、トライアンドエラーはつくづく重要だな。一個メソッドを作ったらとにかくテスト。
コンパイルごとに30秒のロスが出てしまう環境だとつらくてたまらない。
問題Dはグラフを作って最短経路問題か。
しかし、
当然ながら,頭数の多い馬車ほど速い.
どこが当然なんだ。
問題Fはどうやって解くんだろうなあ。
各 x と o 間の移動コストをざくっと出して、それで最短経路問題かなぁ。
x が 10 しかないんだから、それで行けそうね。
うー、しらなかった。Array#shift は O(1) だったのか。だからこんなに速いんだな。うーむ。なるほど。こうやれば出来るんだなあ。
論文を書かなきゃ、と思うと体が拒否反応を起こしてハックが進む進む。
RClass#iv_tbl に自分自身を突っ込んでおけば(GC対策)、RClass も share することは出来るね。MVM instance はこれでさくっとできそうだ。他に共有するものはあるかな。
さて、組み込みクラスはこれでいいとして、require したクラスに同様のことができるか?
require を省略できるか、という意味だが、require で副作用がある場合に出来ないことは多々ありそうだ。はて、どうしよう。無理かな。無理かな。この辺はユーザに頼るしかない気がする。つまり、require するファイルは pure だぜ、と指定。
そこは、中田さんが仰っていた once で解決かなぁ。
once も実装しないとなぁ。//o がまだ対応できてないんだよね。
MVM化で一番大変そうなのが I/O だよな。さっぱりわからん。ライブラリさん頑張って、でいいんだろうか。
久々に GC にはまる。
しかし、なんでローカル変数をきちんと見てないんだろう。あのあたりにバグがあるなぁ・・・。
見たところバグはないように思える。
ということは、根が深いということか...。
うう,日が昇ってきた...
RHG読書会,「dRubyによる分散・Webプログラミング」読もうか.
読みたいし,次の決まらないし.
しまった、うっかり寝過ごして、OOPSLA のポスターの修正をやるのを忘れていた orz
selective inlining を真面目にやって、基本ブロックは1命令でやれるようにするしかないのか。なんとなく、gcc なら出来るような気はしてきたし。
しかし、一番しないといけないのは、send 命令のシェイプアップのような気がしてきた。でかすぎるので、いっそ複数命令に分けるかな。でも、分けるとなぁ。関数化するべきか。でも、VM の内部データを触っていて、そのポインタを渡さないといけなくて。これについては改善していく予定だが。
まずは VM の構造を変えないと。
そして今日はポスターの締め切り。うーん。そして(略)。
コード量が増える問題については、何処までコード量を増やしてもいいのかについてきちんと評価取らないといかんなぁ。しかし、それをどうやって見積もるか。L1 I-Cache に乗るサイズがいいサイズ? Ruby だと、ライブラリとかガンガン走らせるんだろうから、実はあんまり意味なかったりして。つまり、スタックキャッシングみたいな、命令を馬鹿みたいに増やす操作は実は悪いだけだった、とか。でも、今でも少しは効いてるんだよな。
いや、単純な命令しか使わない場合(つまり、スタック操作などが相対的に大きなコストになる場合)しか効いてない気がする。うーむ。
例えば、「Ruby の場合、VM を頑張っても意味無い、むしろもっとシンプルな構造にして、ポータビリティを向上させ、メンテナンスを容易にするべき(Pythonの立場)」といわれたとき、というか、そういう結論になったとき、どうすればいいんだろうな。その結論は、結構ありそうな話だが。
ちょっと頑張れば、少しの工夫でこんなに高速化できましたよ、ってのが望ましい結論なんだが。
CVS と Subversion の併用って出来ないのかな。どっちかにコミットしたら自動的にどっちかにコミットされるように。タグとかブランチとか考え出すと駄目なのかな。
うお、木山さんRubyConf発表する予定だったのか。うぅ、日本人10人計画(なにそれ)は実現するんだろうか。
ちなみに、プログラムはいつ発表されるんだろうか...。
英文2ページはなんとか書けた気がする(大感謝>yarv-devel の人たち)。さて、ポスターをでっちあげなくては...。
しかし、果たして preliminary graphic layout of the poster というのは、どの程度まで詰めればいいのか。四角を囲って、ここに何を書く予定、とでもしておけばいいんだろうか?(というか、そこまでしか出来ないっぽい)。
とりあえず出してしまおうっと。
出した。
さて、次、っと。
x86_64 の最適化をちょっと真面目にやるかぁ、とかちょっと思って。ちょっと逃避っぽいけど...。
しかし、レジスタ利用方法がわからない。どっかに載ってないかな。
Register Usage for x64 64-Bit Windows のならあった。
でも、今ほしいのは Linux なんだよう。
なんとなく、Windows のものが一般的な気がする> calling convention on x86_64。
しかし、gcc は r10, r11 を使うコードを吐いていたような...。
YARV 0.3 を出したいが、はて何時出したものか。肉の日は過ぎちゃったしなぁ。
ICPC2005 日本地区予選の問題を解いてみようかと思ったんだけど、問題が見つからない。残念。
久々にラーメン屋でラーメンを食った。
method(x, y){|(a, b) ...} method(x, y){@(a, b) ...} method(x, y){$(a, b) ...} method(x, y){\(a, b) ...} method(x, y){!(a, b) ...} method(x, y){,(a, b) ...} method(x, y){.(a, b) ...} method(x, y){%(a, b) ...} method(x, y){*(a, b) ...} method(x, y){^(a, b) ...} method(x, y){&(a, b) ...} method(x, y){?(a, b) ...} method(x, y){/(a, b) ...} method(x, y){'(a, b) ...} method(x, y){"(a, b) ...} method(x, y){:(a, b) ...} method(x, y){;(a, b) ...}
どれもキモイな。
method(x, y) do |(a, b) end method(x, y) do @(a, b) end 略
method(x, y){(a, b) p [a, b] }
は結構好きなんだけど、やっぱり違和感あるな。
method(x, y){|a, b) ...}
なんてどうだろう。怒られるんだろうなあ。
method(x, y){(a, b); ...} method(x, y){(a, b) ... } method(x, y) do (a, b) ... end
がいいなぁ。なんとなく。
{} でくくったブロックの最初には () でくくった式が来ちゃイケナイってのは、無茶苦茶でかい仕様変更だから無理なんだろうなぁ。
dynamic super instruction をするんだったら、VM コード(コピー元になる命令列)の大きさは関係ないんじゃなかろうか、ということに気づいた。どうなんだろう。
specialized instruction の工夫。
現在、recv << obj というメソッドに対して、
if(CLASS_OF(recv) == rb_cString && CLASS_OF(obj) == rb_cString && !redefined(rb_cString, "<<")){ rb_str_concat(recv, obj); } else if(CLASS_OF(recv) == rb_cArray && !redefined(rb_cArray, "<<")){ rb_ary_push(recv, obj); }
みたいなコードを書いてるんだけど(redefined() はまだグローバル変数をチェックしてるだけ)、これを
if(CLASS_OF(recv) == rb_opt_cString && CLASS_OF(obj) == rb_opt_cString){ rb_str_concat(recv, obj); } else if(CLASS_OF(recv) == rb_opt_cArray){ rb_ary_push(recv, obj); }
こう書ける事に気づいた。
rb_opt_cArray には、最初に rb_cArray を入れておき、何か基本命令が再定義されたらこいつに Qundef を入れておけば、これは絶対にマッチしない。
じゃぁ、rb_opt_Hoge に何時誰が Qundef を入れるかっていうことなんだけど...。例えばクラスごとに再定義フックなんてのを持たせるのはどうだろう。クラスのメソッドが再定義されたら呼ばれる関数。Ruby レベルでは別に要らないかも。
これなら、特殊命令を用意するクラスにハンドラを書けば解決できる。
Fixnum#+ のチェックには、相変わらず使えないけど。でもこれはそれ以上は無理だよなぁ。
もう一個思いついた。
Fixnum#+ の特化命令 opt_plus_Fixnum で最初にコンパイルしておいて、例えば "a" + "b" という式だったとする。そこで、その部分の命令を opt_plus_String に変更する。かなり楽ちんだけど、それなりの効果は...。どうなんだろう。
String#+ はそれ自体が凄いオーバヘッドなので、先に Fixnum のチェックをしているというのはあんまり関係ないような気もする。わかんないけど。
You could have SVN do a CVS check in with a post-commit script, but I believe you would need to write extra code for it to handle branches. I am less familiar with CVS's equivalent of the post-commit script, but it could probably do the same.
I see. The reason why I wrote the idea of using SVN and CVS is switching Ruby's version control system to SVN. If we can use two system concurrently, we can check subversion dependability.
http://www.logos.ic.i.u-tokyo.ac.jp/icpc/2005/contest/problems.html
だとどうなの?
どう,というのはどういうことでしょうか.速度かな.あんまり変わらないような気がするけど.
A great site where one can enjoy the thought of a great mind long departed. Cheers for the good work!