K.Sasada's Home Page

Diary - 2004 December

研究日記

師走

_31(Fri)

ruby -nlpibak -e '$_.rstrip!' *.c *.h tmpl/*

メモ


ssh -> telnet と入っているサーバからファイルを持ってくる、何か楽な方法は無いものか。


ppc の gcc が吐くアセンブラ出力、レジスタ番号と即値の違いがないので非常にわかりづら。


しあわせの理由読了。解説が坂村先生というのに驚いた。文体が論文ぽい。でも、読後感が・・・。


ことし一年を振り返ってみると、ruby ばかりで研究は何もしていないことに気付く。まずい。

  • yarv
  • nadoka
  • 未踏ユース
  • 日本Rubyの会
  • るびま
  • rubyconf

・・・いうほどやってないな。

  • kahua
  • SWoPP
  • coins

う、やっぱり殆どやってない。


やはり、ruby で研究したほうが良さそうだなあ。きちんとこじつけられるかなあ。


えーと、今年の抱負は・・・。

  • あんまり完成できてない
  • それなりに書いたような気がするけど、きちんと最後まで書いてない。とくにドキュメント
  • 論文一個も書いてない・・・(企画書、研究会予稿、プロシン予稿は書いた)
  • 来年の学費は稼げたと思う
  • 外国には行った
  • 英語は全然さっぱり orz
  • あんまり真面目に生きられなかった
  • 一時間じゃ済まなかった

半分くらいかなあ。


yarv 、構想は結局今年の前半で殆ど終わっていて、あとは気付かなかった難しい部分をちょろちょろと。あとは作業だけなんだよな。


gcc 2.95.3 だと、-f-no-crossjumping がなくて、駄目っぽい。でも、PowerPC の命令セットがよくわからないので、どれくらい駄目なのかわからない。


今更ながら、psyco を見直していたんだけど、Psyco - Documentation は凄いね。これだけ書ければなあ。スライドは、環境的に見れなくて残念。

あと、ps が見れないので残念。


というか、参考文献が大変参考になります・・・。

  • unlift という用語がわからない
  • 3節の証明はやっぱりわからない

ここまでやると、やっぱりすげえなあ。


いいお年を。

_しゅどう(Fri Dec 31 13:12:56 JST 2004)

 楽ではないけれど、ログイン先とのファイル転送に、昔、kermitとかrzsz(XMODEM,YMODEM,ZMODEMプロトコル)を使っていたような。同じくまったく楽じゃないけど、ログイン先でrootになれるならPPPとかSLIPっていう手も。

_anon(Fri Dec 31 15:03:01 JST 2004)

 ttyrec -u って使えるのかな

_shiro(Fri Dec 31 16:03:45 JST 2004)

 懐かしい>kermit。手近に手頃なツールが無くて、手元のシェルをscreenやEmacs内で走らせているか端末のログバッファが十分に大きければ、リモートマシンでuuencodeしたのをcatするって手も。

_ささだ(Fri Dec 31 17:22:57 JST 2004)

 結局、ファイルをウェブサーバに送りつける何かをちょっと書きました。

_30(Thu)

Everyday:2004-12-27 を見て.これは,十分速い素数の列を生成するルーチンを出す,という問題だろうか.

ちなみに,Everyday:2004-12-30 はさっぱりさっぱりわからない.


コント・・・ orz


require 'mathn'

def twinprimes
  pgen = Prime.new
  p1 = pgen.succ
  
  while true
    p2 = pgen.succ
    if p2 - p1 == 2
      yield p1, p2
    end
    p1 = p2
  end
end

def brun limit
  i = 0
  sum  = 0.0
  twinprimes{|p1, p2|
    # p [p1, p2]
    sum += (1.0/p1 + 1.0/p2)
    break sum unless (i+=1) < limit
  }
end

p brun(10000) #=> 1.71403712524201

ruby っぽい? えらい時間がかかったけど.

require 'mathn'

def twinprimes
  pgen = Prime.new
  p1 = pgen.succ

  pgen.each{|p2|
    yield p1, p2 if p2 - p1 == 2
    p1 = p2
  }
end

def brun limit
  i = 0
  sum  = 0.0
  twinprimes{|p1, p2|
    # p [p1, p2]
    sum += (1.0/p1 + 1.0/p2)
    break sum unless (i+=1) < limit
  }
end

p brun(10000) #=> 1.71403712524201

繰り返しを自分で管理してるのがダサい.でも,これ以上は思いつかないなあ.


ところで,そのリンクではコメントは見れないのですね.


なぜ mathn.rb Prime の @@primes はクラス変数なんだろう.


自分だけわざわざ胃を痛くして色々と悩むのは馬鹿らしくなってきたような気がする.相互理解が必要ということなので,きっと私を理解してくれるに違いない(違うってば).

やはり教員にはなれないな.人の面倒を見る=人の人生に関与する,責任を持つ,というのは,今の私には考えられない.重すぎ.


でも,生きていくんだから,きっと他人に何かしら影響を与えてしまうのだよな.

われながら,なんともあまちゃんだ.


ちょっと早いけど正月仕様.


しかし,バカ征く効果凄いな.


MIKO GNYO/Linux が,S-core じゃなくて open Mosix になったのね.S-core よりも,どの辺がよかったんだろう.開発が止まっちゃった(いや,全然知りませんが)からかな.

openMosix はプロセスをばら撒くやつか.pm みたいなものはあるのかな.


お,世界で一番の笹田になれた.


ありがたく,LinkStation を使わせていただく.

・・・.

$ cat /proc/cpuinfo
cpu             : 82xx
revision        : 16.20 (pvr 8081 1014)
bogomips        : 173.67
vendor          : Motorola SPS
machine         : Sandpoint
processor       : PVID: 0x80811014, vendor: Motorola

なんじゃこりゃ.

$ cat /proc/meminfo
        total:    used:    free:  shared: buffers:  cached:
Mem:  129777664 25759744 104017920        0  1290240 13721600
Swap: 542859264        0 542859264
MemTotal:       126736 kB
MemFree:        101580 kB
MemShared:           0 kB
Buffers:          1260 kB
Cached:          13400 kB
SwapCached:          0 kB
Active:           6048 kB
Inactive:        14272 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:       126736 kB
LowFree:        101580 kB
SwapTotal:      530136 kB
SwapFree:       530136 kB
$ ruby -v
ruby 1.8.0 (2003-08-04) [powerpc-linux]
$ gcc -v
Reading specs from /usr/local/lib/gcc-lib/powerpc-unknown-linux-gnu/2.95.3/specs
gcc version 2.95.3 20010315 (release)

ruby は新しいの入れるけど,しかし gcc どうしようかなあ.


がーん,cvs が無い.

1.9.0 の snapshot 取ってくるかな.あ,rpm はあるのか.

あ,subversion のほうが入れるの面倒そうだなあ・・・.


とりあえず wget,と思って入れてみたら,コンパイルできない.

utimbuf が再定義,だそうで.

utime.h と sys/utime.h で,同じ定義が.はてな? とりあえず,sys/utime.h を include しないようにしてみる.通った.


shudoさんのアンテナに Matz にっきがー.重なってないから楽だったのに.


subversion 面倒だなあ・・・.インストールできるかなあ・・・.

あ,クライアントならできるんだ.


ぐ,rpm フェイクか・・・.


さすがに screen と subversion を一緒にビルドしようとすると辛い.


ぐえ,LinkStation,HDD が 14G だと思ったら 146G だった.でか.

自宅のマシンですら 120GB だぞ(一個じゃないけど).

_29(Wed)

ダメダメな日。


「しあわせの理由」をちょっとづつ読んでるんだけど、いろいろと怖い。愛撫とか怖い。面白いけど。


仮想マシンの実装って、なんか難しいところがあるんだろうか。手間の問題だけのような気がする。

あと、仮想マシンにすれば callcc が実装できるわけではないような気がするけど、どうなんだろう(教えてホスィ)。そういう命令セットにすればいいんだろうか。

そういえば、東大のあの実習のページをまた見返せば、今度こそきちんと理解できるだろうか。

_28(Tue)

バグが取れず,今日は帰れないかも.うあー・・・.


取れないよー取れないよー.しかも yarv じゃない罠.

気ばかりが焦る.


なんというか,生まれる前にできたソースを触る不思議.


バグみっけた,と思ったらまだまだ出てくる.ありがち.


一人でゴミ捨て.


やっと動いた orz


問題です。

ここに「金ももらわねーのにこんな本全部読めるか」という学生が居ました。どうしますか?

  1. 頑張って自分で勉強する大切さを教える(自分で勉強するしか、結局しょうがないことを教える)
  2. 無理やり読ませる
  3. 無視する
  4. 逃げる

1 なのかなー。1 が必要なのかなー。1 にするべきなのかなー。やっぱり 1 にすると人は伸びるのかなー。やさしい先輩はきっと 1 なんだろーなー。いいなぁ。

でも、やはり私の力不足で 1 は無理ぽ。残念。ごめんなさい。


今まで、当然ながら 3 だったのですが(いや、私なりに説得してみたりもしたのだけれど、力不足で)、やっぱりまずいかなぁ、とか思わなくもないのです。

だからといって、例えば強制的に「あれをやれ」「これをやれ」とかいうのは私も苦痛だしきっと相手も苦痛だろう。いや、相手関係なく、私が大変になる。

ここを見ている方には、きっと「誰かを指導する」立場の人もたくさんおられるかと思うのですが、こういう場合、どうしてるんですかね。「指導する立場」によって、指導方法も変わってくると思うんですが。

大学、はまぁいいとしても、大学院は、やりたいことをやりに来る場所なので、何も言わなくても勉強したいオーラを出す場所だと思っているんだけど、どうやらそうでもないらしい。彼いわく、「みんなそう」とのこと。

私は、「この本読んできて」とぽいと渡す人なんだけれど、筧先生(早稲田)いわく、「読めませんでした、と返しにきたときにどうやってフォローするか」が問題になるとのこと。なるほど。でも、「読めません」とも言ってこないで放置というのはどうやってフォローすればいいんだろうか。


無視すると逃げるは一緒かも。

やはり、私に教員は無理だな。


筧先生は、他大学、他学科などへの移行の困難さを挙げておられました。たしかに「ここは自分には合わない」と思ったとき、他のところへ移行しようと思っても、日本ではそれを実行するのは大変なことだと思います。


たしかに本を一人で読むのは大変だと思うんだけれど、読書会などを自ら主催しようとは思わないのだろうか。思わないわな、さすがに最初は。

というわけで、読書会を薦めてみよう。K&R をすみからすみまで読んで、問題解けば、きっと力がつくに違いない。でも、私は K&R は読んでいない(ぉぃ。


読書会などは、私は好きなんだけど、じゃぁそんなの鬱陶しくてやってられるか、という人にはどうすればいいんだろうかなぁ。


で、そういうのに興味があるので、るびまのインタビューでは毎回「後進の指導をどうやっていますか?」というのを混ぜている。私の質問の仕方が下手で、なかなか盛り上げられないんだけども。

まつもとさん
勝手にやって〜、でしたっけ。
前田さん、かずひこさん
お昼休みなどに勉強会。
たださん
背中で語る。
増井さん
ご自分が教えてもらってる、などと言っていたような。

いや、この人たちのまわりには、やる気のある人ばかりが寄り付きそうなので、あまり参考にならないような気もする。


自分(達)で勉強していこう、という雰囲気作りが大切、ということか。勉強会、と言ったとき、私が先生でやるというのは駄目ってことだよな。


あ、別に特定の人物が居る、というわけではありません(ということにしておこう)。もし、こんな人があなたの周りに居たら、どうしますか? どう指導されますか? という質問です。

もちろん、このせりふをそのまま言ったわけではないし、いろいろと脈絡があって省略しているところもありますので・・・、って特定のモデルも居ないんだった。まぁ、そういうことで。


http://www.ipa.go.jp/、誰だこの親父、とか言ってえらい人だったらどうしよう。どなたかしらん、この方。


shelarcy さんがこめんとを書いてくれたので、ついでに。未踏で通ったのは wxHaskell をどうのこうのするって話じゃなくて、wxHaskell でどうのこうのするって話だったんですね。前者だと思い込んでました。今度どんなもんするのか教えてください。


t さん

場合によっては学生さんに同意。状況は分からないですが、何がやりたいのかを聞いてあげて欲しいというのと、学生さんの費やす時間と彼がそれで何を得るかに責任はもてないです。

そうかもしれません。ただ、ある程度基礎は書籍などを参考に下積みしないと身につかないのではないかと思うのです。

まぁ、その基礎を必要するところからして、望むものではない可能性もあることはあるのですが。

_しゅどう(Tue Dec 28 18:17:52 JST 2004)

 本当は「読めませんでした」じゃなくて「読みませんでした」だったり。

_shiro(Tue Dec 28 19:24:36 JST 2004)

「テメェはこの本を読むために金払ってここに来とんじゃボケ!」とシメる。

_t(Tue Dec 28 20:16:48 JST 2004)

 場合によっては学生さんに同意。状況は分からないですが、何がやりたいのかを聞いてあげて欲しいというのと、学生さんの費やす時間と彼がそれで何を得るかに責任はもてないです。あと、なぜ、世話する必要があるのだろうと...。自分の知識・経験に対して自身があるわけではないので、助けを求められたら、できる範囲で助けるで十分じゃないかなと思っていました。あと、私は読書会や輪講はあまり好きじゃなかったですが、発表やまとめの勉強にはなりますね。

_shelarcy(Tue Dec 28 20:53:50 JST 2004)

ふむ。自分で何かやってて競合状況にあるときに、優先順位の高い他のことをやって、それをやらなければできないであろう仕事を後回しにしてしまうという意味では分からなくもないかな。当初現実の世界をさておいて Boost.Build v2 を使おうとしていた人としては。 (心変わりして autotools + make 使おうとするまでシェルスクリプト学ばなかったし……ただ、使いこなしていない時点ゆえに、アーリーアダプター過ぎてドキュメントにかかれていないようなことをそこの問題と勘違いしたり問題が切り離せてない時点で質問してしまって迷惑かけたし、それでない道具を使おうとしたときに普通ありえないようなミスを犯してしまったりして、結局遠回りになっちゃったので現時点では同じ道を通ることはお勧めしないけど。)

これをやろうとしない限り現時点ではそれは必要ないと思っている人には、反証を示さないとそれをやるのを拒絶されがちですよね。

_おだか(Tue Dec 28 23:51:32 JST 2004)

問題は言っている内容や方法が正しいどうか、ではないんじゃないでしょうか。

ものの言い方や態度を改めるだけでも相手が受ける印象とかやる気ってのは大きく変わります。いつも隣で見て(聞いて)いる人間としては(あっ、モデルはいないんでしたっけ?)、「その言い方は乱暴だよなぁ」とか「もう少し言い方を工夫できないかなぁ」とか思ったりしてます。

まあ、聞く側の態度にも問題はあるとは思うのですが…。

_nobsun(Wed Dec 29 00:43:55 JST 2004)

人は、強制されようが、されまいが、関係なく、興味や必要を感じれば、行動には出るし、そうでなければ、行動しないでしょう。パンを美味しそうに食べてみせる、それだけでよいと思います。もちろん、訊かれれば、食べ方を一緒に考えればよいのではないでしょうか。

_shiro(Wed Dec 29 05:46:56 JST 2004)

 残念ながら、いつもお腹が空く前にパンを他人から与えられて育った人は、いくらお腹が減っても「自分から手をのばさなければならない」ということを知らなかったりします。その場合、強制でも何でも一度行動させてみることで、「なんだ、手を伸ばせばいいんじゃないか」とわかってもらえることもあります。

_前の人(訂正1)(Wed Dec 29 23:47:05 JST 2004)

 私の前の人がここの管理者です.そして,私が当事者でもあります.そして,彼から電話が入り,ここの議論を読んでみて,なにかあったら書いてくださいとのこと.だけど,無理に書かなくてもいいとのこと.どっちやねん.笑

 確かにこのようなやり取りがありましたが,前後が不十分であるのと,それによる設問と選択肢がこれまた不十分であるため,私からは何とも言えません.しかも,このやりとりは売り言葉に買い言葉のようなところがあり,学生がお金目当てに研究をするなどということは馬鹿げています.そもそも,話の本質はこのようなことではなかったと思います.しかしながら,このやりとりがここで取り上げられているように,話自体の解釈と主張で,双方に多分に誤解があるように思います.

 で,そもそm…とまぁ,ここから彼への文句やら私のお馬鹿な身の上話やらをぐちゃぐちゃぶっちゃけてやろうかと思いましたが,書いている方も読んでいる方も正直うざったいので,省略!

 で、まー結論をとっとと言いますと,せっかく狭い部屋で顔つき合わせて,互いに切磋琢磨している環境にあって,相互理解と,わきあいあいとした雰囲気が必要ではないでしょうか.情報「コミュニケーション」工学専攻ですからね.この日記の下についてくる意見のようにざっくばらんとしていればいいんじゃないですかね.天下り的にこの本を読め!と言われても,読まなきゃいけない本が10冊あったら,その本のプライオリティは最低だと思います.何やかやと話しているうちに,この本のここがこうだとか,あーだとか言えるといいのですが.

 あと,もう,ささださんは変なところを真に受けちゃうんで,あとで,え?そんなところを気にしてたんですか?なーんてことがよくあるようなないような.全てはコミュニケーション不足から通じる些細な誤解があらぬ方向に進んでいると思います.

 以上.我々二人のお馬鹿なやり取りにまじめに付き合っていただいてありがとうございます.

_ささだ(Thu Dec 30 09:52:38 JST 2004)

根本的な問題は、「自分で勉強しない人間に対してどのように指導しますか」という問いなので、あまり「前の人」(これは席が前の人、という意味です)がどうかとは関係ないので、「おばかなやり取り」とは関係ないので、その点だけは明記しておきます。

ついでに書いておくと、選択肢が不十分なら選択肢を追加するという手があると思うのですが。

_おだか(Thu Dec 30 12:16:30 JST 2004)

隣の人を例には出しましたが、それは重要ではなくて僕が言いたかったことは「方法は良くても伝え方が悪かったらダメである」ということです。

まあ、上の書き込みを読む限りでは僕のような意見は必要ない、ということなのかもしれませんけど。

_27(Mon)

脈絡の無いのって、だめだよな。やっぱり。デバッグが足りないような気がする・・・。


と、脈絡なく書いてみる。


やはり通信と書いているのがあれか。

App1 <-> SoftEther VPN ユーザーモードルータ <-> なにかネットワーク <-> App2

ではないかと思うのだけど、最初の App1 <-> SoftEther VPN ユーザーモードルータ を管理者権限なしで行うのはどうするのかなぁ、と。Windows には何か方法があるのかもしれないけど。


って、ユーザモードルータってそういうことか。やっとわかった気がする。気だけ。だけど、そんなに簡単に運用できるものなんだろうか。ルーティングを変更してあげないといけないような気がするのだけれど。やっぱりまだわかってない気もするな。


やっぱりわかっていない気がする。ネットワークの基礎からやり直しが必要そう。


社内Lan から SoftEther ネットワークにアクセスする方法を悩んでいたんですが,「それが出来る」とはどこにも書いてないですね.逆側なら話はもちろん理解できます.


トランシーバー機能付き携帯、来夏発売予定,これってたとえばおうちのサーバと通信できたりしないんだろうか.音響カプラ再来.

って,ふつうにパケット定額でいいのかしらん.定額のサービス範囲がどういうものか知らないのでなんともいえないけれど.


そういえば,先日「groovy を検討してあきらめた」という話を聞いた.groovy でさくさくとロジックを書いて Java で開発されているフレームワークを活用する,という話だったらしい.

で,なんで没になったかというと,groovy は Java のクラスファイルにコンパイルするため,たとえばフレームワーク側から groovy のスクリプトに制限を加える,変更するなどが出来なかった(する方法をみつけられなかった)という話らしい.

ふつーのインタプリタだったらよかったのにねー,とか.そこで JRuby ですよ,と言ったらドキュメントが全然ないため即却下,だったらしい.残念.


最初の誤解は,ルータという言葉の誤読.


Java でなんとかかんとかってやってるんだけど,Windows の eclips でコンパイルして Linux の環境で実行.きちんと動いて凄い.

_み(Mon Dec 27 12:36:09 JST 2004)

 問題はプロシンのデモだ…

_shiro(Mon Dec 27 14:53:13 JST 2004)

この絵の通りじゃないの? http://www.softether.com/jp/vpn2/router/images/user-mode-nat.jpg わしも最初あれっと思ったけど、「リモートのアプリケーションからLAN内のサーバへ アクセスする」んだから、ユーザモードルータはLAN内では単なるクライアントに なるんでないかい。

_び(Mon Dec 27 15:09:17 JST 2004)

 http://www.softether.com/jp/vpn2/router/の図を見てわかった。TCPを用いて、仮想ハブへ接続→この段階でSoftEtherプロトコルを使ってイーサパケットを送受信できるから、このイーサ中にカプセル化されたIPパケットを取り出し、ユーザプロセスとして動作しているVirtualIPRouterで普通のソケットを開いてそこと、SoftEtherで送られてきたIPを解析するすればできるよね。経路とかは普通のイントラネット側それを使えばいいし、仮想ネットワーク側はSoftEtherの枠組みでできるよね。例えば、UNIX系ならVTUNとかでイーサパケットをトンネリングして、普通はtunデバイスとか使ってカーネル<->ユーザリンクを使うけど、IPパケットをユーザプログラム中で捕まえて、TCP/UDP/ICMPを自分で判定してデータの部分を普通のソケットに流し込んでやれば(手間はかかるけど完全にユーザレベルで)できるよね。このような内容だと推測。できるのはわかるけど、ちゃんと作って宣伝していることを褒めましょう。

_maeda(Mon Dec 27 17:26:10 JST 2004)

 「社内Lan から SoftEther ネットワークにアクセスする方法」ふつうのNATルータと同じようにすればできるでしょう。

_ささだ(Mon Dec 27 17:46:44 JST 2004)

 そのために,ルーティングをどうのって書いてました.

_26(Sun)

http://slashdot.jp/article.pl?sid=04/12/24/177254&topic=92&mode=nested&threshold=-1、話がよくわからないのですが、アプリケーション <-> SoftEther VPN ユーザーモードルータ の通信はどうやるんだろう? 管理者権限は本当に必要ないのかな? winsock.dll を置き換えとかするんだろうか。

_はぁ〜(Sun Dec 26 18:58:49 JST 2004)

 あのねぇ...well known portがrootかどうかよりも、そもそも、どんなポート(サービス)が開かれているか、プロトコルがどうなってるかは本質的に別の話なんだけどな。

_ささだ(Sun Dec 26 22:31:42 JST 2004)

 well known port などの話がどうつながるのかわかりません。もしよかったら教えていただけませんか。

_maeda(Sun Dec 26 23:22:56 JST 2004)

 仕組みはそう難しくないと思うが。私の推測があってるなら、TCPとUDPだけ転送するものだと思う。それならユーザレベルでできるでしょ? 登君は今回もプロシンに参加するそうなので、問い詰めてやって。私は残念ながら行けません。

_ささだ(Mon Dec 27 05:08:42 JST 2004)

 ユーザレベルでソフトウェアによる仮想ルータというか、そういうのを作るのはもちろんわかるんですが、アプリケーションが、それとどうやって通信するのかよくわからないのですが、何か私が勘違いしてるのかも。

_ささだ(Mon Dec 27 05:10:35 JST 2004)

 まぁ、インストールしてみればわかるのかもしれませんが、そこまでする気力は無い。システムコールなども通信と私は言っているので、何か「はぁ〜」さんを誤解させている可能性はあるなぁ。

_maeda(Mon Dec 27 10:38:53 JST 2004)

 アプリケーションはSoftEtherコネクションの向こうにいるわけでしょ。この「ルータ」は外から(SoftEtherで)送られてきたTCPやUDPのパケットを、本物(?)のTCPやUDPのソケットへ転送するものでしょ。「アプリケーション」が動いてる遠くのクライアントには、仮想LANカードが(administratorによって)インストールされている必要があるけれど。

_び(Mon Dec 27 12:35:23 JST 2004)

 応用層(のプロセスやスレッド)で単にTCP・UDPを左から右へ流すだけでしょ。左と右の二つのソケット開けば単純よ。結局、squidみたいなプロクシもそうだし、VoIPのプロクシも(カーネルレベルなんてのはほどんどないから)は同じ。ただし、通常ユーザのプロセスだと0〜1023のポートは普通は開けんわな。

_ささだ(Mon Dec 27 13:42:12 JST 2004)

http://www.softether.com/jp/vpn2/router/ に、

SoftEther VPN User-mode Router 2.0 はユーザーモード仮想化技術を使用しています。したがって、インストールおよび動作において、システム管理者特権・カーネルモード特権は一切不要です。

とあったので、

「アプリケーション」が動いてる遠くのクライアントには、仮想LANカードが(administratorによって)インストールされている必要があるけれど。

が必要ない、という話だと思って、疑問に思っています。

それとも、ユーザモードルータというものはとくに管理者権限は要らないが、実際に動作させるには管理者権限の必要な仮想NICのインストールが必要、ということなんでしょうか。それなら理解できます。

スラッシュドットなどを見ていると、「管理者権限も一切必要なく、勝手にVPNを構築できる技術だ」、と書いているように私は見えたんですが「はてどうやってるんだろうなぁ?」というのが私の疑問です。

_maeda(Mon Dec 27 15:04:36 JST 2004)

 softether.comの図をちゃんと見ようよ。クライアントPCには仮想LANカードがあるでしょ。「ルータ」の2つの接続(SoftEther仮想ネット内でのインターフェースと、本物(?)のソケット)間でパケットの転送をするけど、それが「ルーティング」にあたるってことでしょ。転送の際、IPアドレスとポートを本物のそれに書き換えるんだろうから、いわゆるNAT箱だよね。まわりの(本物ネットにつながった)マシンからは、SoftEtherネットワーク内のアドレスは見えない。ユーザモードルータと直接パケットをやり取りしているように見える。だから、他のマシンのルーティングを変えたりは不要。

_25(Sat)

で、コミックこうかくきどーたい1,2を読む。文字が多い。2はさっぱりわからない。1は SAC と全然違うのね。innocence も含め、貼り合わせた感じ。

1.5も一緒に買ったつもりなんだが、見つからない。本屋で置き忘れてるような気がする。内容物の確認はしないと駄目だな。高いのでちょっと辛い。


寝坊。


というわけで,本屋で受け取る.お詫びの図書券くらいは期待したんだが,とくになにもなし.まぁ,泣き寝入りせずに済んでよかった.


というわけで,昨日は,

  • げんしけん5
  • シャーリー
  • こうかくきどうたい 1, 2, 1.5

を購入し

  • グインサーガ 91, 92
  • しあわせの理由

を図書館で借りる.久々の本.


攻殻機動隊を平仮名で書くのは,漢字をすぐに忘れるから.


メリークリスマス.


たださんのインタビューのとき,rubyist にはSF好きが多いですね,と言ったらプログラマにSF好きが多いだけでは,と言われたのだけれど,ではプログラマにSF好きが多いというのは真なのか? もしそうなら何か理由があるのだろうか?

_あひる(Sat Dec 25 19:08:36 JST 2004)

 SFは好きじゃないです

_ogino.(Sun Dec 26 01:22:39 JST 2004)

 プログラマには谷山浩子好きも多いです。←きいてないって。

_ななし(Mon Dec 27 12:04:08 JST 2004)

 いやいや、プログレ好きのほうが多いんじゃないですか?

_24(Fri)

お題: 関数引数の permutation というのを見て,やってみた.

def removed ary, i
  ary = ary.dup
  ary.delete_at i
  ary
end

def parm args
  if args.size == 1
    [args] #=> [[e]]
  else
    res = []
    args.size.times{|i|
      e = args[i]
      parm(removed(args, i)).each{|ary|
        res << ary.unshift(e)
      }
    }
    res
  end
end

p parm( [:a, :b, :c] )
#=> [[:a, :b, :c], [:a, :c, :b], [:b, :a, :c], [:b, :c, :a], [:c, :a, :b], [:c, :b, :a]]

ダサいダサい.

def parm args
  args.empty? ? [[]] :
  (0...args.size).inject([]){|res, i|
    parm(args[0...i] + args[i+1..-1]).each{|ary|
      res << ary.unshift(args[i])
    } && res
  }
end

p parm([:a, :b, :c])
#=> [[:a, :b, :c], [:a, :c, :b], [:b, :a, :c], [:b, :c, :a], [:c, :a, :b], [:c, :b, :a]]

わかりにくくしただけともいう.


年末ということで(いや,あまり意味は無いが)引き出しなどをごそごそしてみると,賞味期限がかなり切れてる.

どうやってお渡しすればいいんですかね>青木さん


というわけで,始末せねば.でも,さすがにゆでスパゲティ 2004 1月ってのは駄目そうだ.


double inject とか言われた.

def parm a
  a.empty? ? [[]] : (0...a.size).inject([]){|res, i|
                      parm(a[0...i] + a[i+1..-1]).inject(res){|res, ary|
                        res << [a[i], *ary]
                      }
                    }
end

p parm([:a, :b, :c])
#=> [[:a, :b, :c], [:a, :c, :b], [:b, :a, :c], [:b, :c, :a], [:c, :a, :b], [:c, :b, :a]]

ライブのチケットをプレオーダーしていたら、いつのまにか決まっていて、いつのまにか振り込み期日が過ぎていた orz メール見逃してた。なんてこった・・・。

チケットとっても行くのを忘れていたりと、もうダメダメだ・・・。

もう関東のチケット売り切れてるよ・・・。大阪までいく勇気がないよ・・・。愛が足りない。やっぱり、ファンたるもの海外でやるんだったら着いていかないと駄目なのかな、と思ったり思わなかったり。

うー・・・。


げんしけん5。

あー、うんー・・・。

_kjana(Fri Dec 24 01:27:49 JST 2004)

 何がださいって、permutation の略が parm な辺り、っていうことでしょうか?

_ささだ(Fri Dec 24 01:32:38 JST 2004)

 ガーン.辞書では permutation は一応調べたんだがなあ.

_23(Thu)

Adobe reader 7.0 いいね.


どうにも,例外の発生を考えると,スタックキャッシングは使えないんじゃないかと思うようになってきた.Java や C++ では,例外発生時スタックを巻き戻すけど,Ruby ではそうでない場合がある.

"a" +
  begin
    "b"
  rescue Exception
    "c"
  end

"b" を作ろうとして GC が発生して,アボーン.

て,例外処理部分に突入するときには必ずスタックキャッシュを使わないようにすればいいのか.また無駄な命令が増えるな.

  putobject_xx_ax "a"
  clearsc_ax_xx
  putobject_xx_ax "b"
  send_ax_ax      :+, 2

こんな感じだろうか.すべての命令に ??_xx が出来るようにしといたほうがいいんだろうか.そうすると,命令数がさらに倍(未満)になるんだよな,多分.すでに300命令あるんだから・・・.

そういえば,いい加減アセンブラほしいよな.現実逃避に作ろうか.いや,駄目だ.


作りたいシステム.

  • ML archive system
  • Wiki
  • tton
  • bibliography management system

夢イッパイ.

あと,この日記ももうちょっとちゃんとしたいよな.


log_a M = log_b M/ log_b a というのはなんでだったかな,とふと気になりだして悩んでしまう.高校数学じゃねーかこんなの orz


数学全然駄目なので,統計学なども駄目なので,統計学を一からやり直したいなあ,などと思う.なんかいい本ないですかね.

http://www.amazon.co.jp/exec/obidos/ASIN/4274065707 こんな本があるのか.

目次を見て脱力.「トキメキ統計学」ってなんだ・・・.統計学にトキメクのか統計学でトキメクのかトキメキを統計学で解くのか.


あと,プログラミングの理論の話もやり直したい.せめて,PRO の論文で数式が出てきた時点でひるまない程度には・・・.


そういえば,年賀状を出さなくなって数年.やっぱり書くようにしたほうがいいのかしらん. でも,住所知らない人ばかり.


〜〜ってどうやるんですか,という質問に,〜〜と答えて,一応ちっちゃいプログラムで確認して,と言ったら,また「そんな時間はない」とか返された.何度説得してもやろうとしない.もう,どうしたもんだか.

そんな奴の書いたプログラムは信用できん,と言ったら膨れていた.急がば回れという言葉を知らないのかなあ・・・.

_び(Thu Dec 23 20:56:53 JST 2004)

 「そんな時間はない」なんて功を成し、周りからもそうだよな、と認められる連中だけだよな。いいぢゃん、卒業/修了できないだけだから。まぁ、世の中の冷たい風の中でがんばってちょ。

_22(Wed)

スピーカー、というか、アンプがもうダメダメな感じ。高校のころ、粗大ゴミを拾ってきた(前はそんなに厳しくなかった)ので、もう寿命と考えるか。

さて、どうしよう。それなりのものは欲しいが、音響関係は(も)さっぱりわからん。下手なもの買ってもアレだしな。


というわけで,文京グリーンコートへ出発.


研究室に帰室.今回も,大変楽しい話を聞けました.とくに,私は全然知らない分野だったのでひじょーに面白かった.

結論.インタビュアーが駄目でも,話す人が面白ければ,面白くなる.


で,帰りに研究室 OB の人とビール.いろんな話を聞けて,楽しかった.

ビールは2杯頼んで,フルーツビールというのも飲んだ.甘い.スパークリングワインのようだ,とはその人の評.たしかに.


せっかくるびまでいろいろチャンスがあるので,お世話になった方などに mixi で繋がらせてもらおう運動.

_babie(Wed Dec 22 18:06:57 JST 2004)

 文京グリーンコートとはアンプとかスピーカーが拾える所でつか?

_ささだ(Wed Dec 22 23:44:52 JST 2004)

 残念ながら拾えませんでした.

_21(Tue)

というわけで、昨日のあれをやって、終わったら OS が落ちた。Win2k 弱いぞ。


ああいうのをやると、やらなきゃ、って気がしてくる。気だけ。


ありゃりゃ困った。テスト環境の gcc は 2.95.4。debian stable だから。

評価用に新しいの入れるかなあ。入るかなぁ。めんどいんだよなあ。

評価は x86_64 だけで取るかなあ。でも、フェアじゃないよなあ。


C(99) では、配列などのオブジェクトを 64MB のサイズで保証するだけなのか。知らなかった。


というわけで,http://www.candc.or.jp/news/news041213_cac-jushoushiki.htmに行くことにした.


今日もキャッチボール.寒いのであまり汗はかかない.


http://www.ipa.go.jp/jinzai/esp/2004mito2/koubokekka.html 出てた.


defmacro debugprint(arg)
  IF($DEBUG)
    p arg
  END
end

debugprint(...)

なんて出来ると嬉しかったりするんだろうか.

_shiro(Tue Dec 21 19:05:48 JST 2004)

 Alan Kayの応募数4件て…

_babie(Tue Dec 21 23:23:50 JST 2004)

 あ、qwikWeb来てる

_20(Mon)

お,もうすぐ 10万アクセスだ.


今日もキャッチボール.


お.

100000 2004-12-20-1-17-27-47 - Mozilla/5.0 Gecko rv:1.7.5 Windows NT 5.1

な人,おめでとうございます.なんかください.


Rails と CGIKit ,ネタについていくために使いたくなってきた.でも,何作るかな.


未踏ソフトウェア - イベント案内 | 未踏16キックオフセミナー@博多 を見る.九州はいけないってば.

しかし,

10. 高橋 明生 氏 (加藤 和彦PM) CLIを実装する次世代オペレーティングシステムの開発

の CLI とはなんだろう.割り込み禁止でもないしコマンドラインインターフェースでもないし.Common Language Infrastructure あたりが妥当だろうか.しかし「実装する」ってのもよくわからんな.どんなんだろう.

やっぱり名前はわかりやすくないと.

しかし,.NET 用語なのかどうかも不明.


これ、むかしにも書いたかも。

M
だらだらと記述された美しいコード。それはまるで天才とプログラム言語がかなでる二重奏のよう。アルゴリズムの本質が、データ構造が以下略
A
深いんですねー。プログラムって
K
不快だよねー。プログラマーの自己陶酔って
_しゅどう(Tue Dec 21 12:52:22 JST 2004)

 10万アクセスありがとう記念ということで、何かください。(僕じゃない?)

_ささだ(Tue Dec 21 13:25:00 JST 2004)

 ホールインワンみたいなもんで、取った人がなんか出すということで。しかし、リファラーを見ると、しゅどうさんではなさげでした。

_19(Sun)

今年初めての忘年会だった。飲みすぎ。


constant をカタカナで書こうとして、コンスたんと、になった。コンスたんってなんだ。となると、セル君が必要なのか。


で、増井俊之さんにインタビューさせていただくわけなのですが、あまり詳しいことを知らないんです。何か「これ聞いて来い」というのがあったら、誰か教えてくださいませ。


日本のビールは好きじゃないんだが、世界にはいろんなビールがあるのか。いつか飲んでみたいなあ。


smbmount でどうやっても書き込めない。(ローカルネットワーク内なので)Everyone OK な状態に。

なんでだと悩むこと一時間。mount コマンドでやったら書けた。なぜ。

_maeda(Sun Dec 19 23:13:02 JST 2004)

 世界のビール: ビアバーBrusselsとか。

_ささだ(Mon Dec 20 18:29:14 JST 2004)

 今度行ってみまーす.

_18(Sat)

寝坊した。

_17(Fri)

やっぱり帰れなかった orz


昨日も論文をたくさん印刷した.満足満足.

・・・読めよ orz


Rubyist Magazine 0004号リリースしました.

お楽しみください.


しかし,全然ヒマにならない.

とにかく,明日は RHG 飲み会だ.


最近帰るのが遅かったり帰ってなかったりで家族の顔を見ていない.なんとか今日は帰りたい.


るびまですが,来月お休みするのは予定通りです.10月ごろから決めてました.たしか.決して疲れたからお休みってわけじゃないです.疲れそうだから休もうってのはあるけど.

4号は,本当はもうちょっと早く出す可能性もあったんですが,今回も予定通りの範囲でしょう.そのかわり,編集の手間を前ほどかけられていない感じがします.今回は,そういうテストケースということで,それはそれでいいんですが,やっぱり編集手を抜いたこの辺がまずい,という反応が得られれば,それをフィードバックして今後につなげていければと思います.

今回も,協力していただいた方,本当にどうもありがとうございました.

次号のネタは「バレンタインデーの思い出」になりそうです.多分.きっと.


今月は私があんまり動かなくてもどうにでもなる,というテストケースにもなりました.多分.というわけで,次号は私は手をつけなくてもいいはずだ.

・・・未踏ユース成果報告でやばそうなんです・・・.


rudl ってどうなんだろうな.要調査.


本当に読みたい Linux で C 本.

  • gcc をインストールしましょう 〜 環境別コンパイルオプション完全制覇
  • とりあえず Hello, World コンパイルしますよ 〜 Hello World で見る機械語 - CPU によってこんなに違うんだね
  • argv の構造 〜 OS 別 argv 実現方法 - 組み込みから Linux まで
  • ...

そもそも Linux でも C でもないという罠.


もうちょっとまじめに考えてみよう.

  • Linuxプログラミングを始めよう 〜 計算機の歴史(EDSAC - BlueGene) と OS の歴史(System/360 - Linux) ... なぜハイパフォーマンス
  • Linuxを表現する3つの概念 〜 (Linux 初心者なので省略)
  • Linuxにおけるユーザ 〜 (UNIX 初心者なので省略)
  • ストリームにかかわるシステムコール 〜 無限ストリームを扱うプログラミング言語(Cじゃないってば)
  • ストリームにかかわるライブラリ関数 〜 (思いつかない)
  • headコマンドを作る 〜 機械語から Haskell まで(だから C じゃないじゃん)
  • grepコマンドを作る 〜 検索アルゴリズム最前線
  • Linuxのディレクトリ構造 〜 i-node の設計と実装
  • ファイルシステム - 近代的ファイルシステムの設計と実装
  • プロセスとメモリ - プロセス管理とメモリ管理の設計と実装〜組み込み向けハードリアルタイム保証から大規模分散システムにおける資源管理について
  • シグナル 〜 シグナルの設計と実装 - セキュリティの観点から
  • プロセスの環境 〜 (プロセス管理は上で言っちゃったなあ)
  • ネットワークプログラミングの基礎 〜 TCP/IP の仕組み
  • HTTPサーバを作る 〜 (思い浮かばない)
  • HTTPサーバを実用化する 〜 動的負荷分散機構
  • 本書を読み終えた後は 〜 (思い浮かばない)

うーん,イマイチ.


何を考えてるんだ俺は.


で,上記を書くために OS HISTORY -- From System/360 to Linux を見たのですが.

マイクロカーネルはモノリシック・カーネルよりオーバーヘッドが発生し処理効率が落ちると言われていますが、これはLinuxができてきた91年であっても古い話です。80年代後半ごろマイクロカーネルの草分けであるMachはのオーバーヘッドの問題はありましたが90年に入るとマイクロカーネル技術は既に、その問題を克服しています。いまだにこの「マイクロカーネルは遅い」という神話を信じている人がいて驚くことがあります。

まともにマイクロカーネルを実装して,処理効率が落ちないことなんてありえるんだろうか?

最近のマシンなら,このあたりの効率はあんまり考えなくてもいい,という話なら理解できるんですが.

マイクロカーネルの話をまともに勉強していないことに気づき愕然.OSの研究室の博士課程学生なのに.

要は,保護と遷移のオーバヘッドのトレードオフなんだと思うが,オーバヘッド削減の工夫はいくらでもあると思うが,0 には出来ないんじゃないかなあ・・・.

上記引用文では「無視できるほど軽くする工夫ができる」という意味だろうか.


そういえば,Hurd ってどうなってんだろうなぁ.


マイクロカーネル - Wikipedia 経由で The L4 microkernel family というのを初めて知る.はて,これはどんなものなんだろう.

この辺の論文を読めば少しはわかるのかしらん.しかし,日本語でまとまった文章はないものか.


メッセージパッシングモデルによる構成の良さはわかってるつもりだけれど,オーバヘッドどこまで削減できるんだろうな.

CPU多くなってくると,話ががらっと変わったりするんだろうか.

_なかだ(Fri Dec 17 20:06:22 JST 2004)

 組み込みじゃargvはないというかmain()から始まるとも限らんのでは。

_ささだ(Fri Dec 17 20:15:49 JST 2004)

 その辺も込みで.

_しゅどう(Fri Dec 17 21:21:36 JST 2004)

 Machベースゆえにマイクロカーネルだと思われがちなMac OS X、実は最乗シックカーネルらしい

_ささだ(Fri Dec 17 21:28:25 JST 2004)

 真剣に悩んでしまった>藻糊シックカーネル

_青木(Fri Dec 17 21:36:22 JST 2004)

 それ、3000 ページくらいいるんじゃない?

_kjana(Sat Dec 18 01:19:58 JST 2004)

Omicron Tiki のマイクロカーネルのページなんかどうでしょ? http://tiki.is.os-omicron.org/tiki.cgi?c=v&p=%A5%DE%A5%A4%A5%AF%A5%ED%A5%AB%A1%BC%A5%CD%A5%EB

_16(Thu)

タスクが大量に降ってきた.まずい.まずい.まずい.

YARV をまた集中的に弄ろうと思ってたんだけど,当分無理かも orz


キャッチボールをする.何年ぶりだ.体中が痛い.

_こーのいけ(Thu Dec 16 23:26:47 JST 2004)

 目撃させていただきました。>キャッチボール

_15(Wed)

やっとテストとベンチマークが通った.コンパイルのテストだけでも,やってあげないとな.

ベリファイアをちゃんと作らないといけないんだろうけれど,面倒くさくてしょうがない.動かすのに必要なものではないのでついつい後回しにしてしまうけれど,効率的なコンパイラの実現を考えると,必要なんだよなあ.

要は,スタックの状態チェックを行うだけなんだけど.・・・多分.


YARV 上で動かすほかの言語をちょっと考えてみる.PDF なんてどうだろうとか,妄想.


考えてみると,$_ などの,スコープローカルな特殊変数が扱えないことに気づいた.具体的には,C メソッドから IO#gets などを行うと,$_ が無い.困ったなあ.これをやるためには,すべての C メソッド起動時に,ちゃんとフレームを作ってあげないといけないということになる.それは,ちょっと嫌だなあ.

しょうがないのかもしれないけど.


で,これを管理するための rb_svar を見てみると,どうやら C メソッド中で $_ を設定する場合などは,ローカル変数テーブルが無いから設定しない,ってことらしい.というわけで,rb_svar を YARV で書き換える必要があることと,C メソッド実行中ということを理解できないといけない.さて,どうやれば出来るだろうか.


なんというか,例外生成のためにスタックトレース作るには,PC を外に見えるようにしないといけないような気がしてきた.でも,毎回 th->pc = pc なんてやると,大変そうだよなあ・・・.うーん.

例外生成される可能性がある部分ではレジスタ値はきちんと見ることが出来ないといけない.困ったなあ.

例外生成される可能性がある部分をピックアップする必要がある.

Ruby C API を呼ぶ前に PC を必ず保存するような処理が必要なのかなあ.殆どの処理は,それが要らないような気がするが・・・.


たとえば,rb_ivar_get を呼ぶときに例外の心配をする必要はあるだろうか.

危なそうなところ,たとえば rb_range_new の前では store する,みたいな対策で行くか・・・.


putrange とか本質的じゃないかなぁ,とか思ってたけど,Range.new(a, b) と (a..b) は違うのでなんとも言えない.


Mac,というか PowerPC 上で YARV を評価してみたいなあ.どっかに落ちてないかな(無いです).10万円くらいで買えるのかしらん.でも,そんな金は無い.中古だともっと安いのかなあ.


ずっと本業(まるちすれっどあーきてくちゃがどうこう)について考えていたんだけど,思いつかない.駄目だもう駄目だ.

本業が疎か杉.

_shiro(Wed Dec 15 20:12:06 JST 2004)

GaucheでもC APIを呼ぶ時は、絶対安全とわかっている時以外はレジスタをVMに退避してます。忘れてはまったことも多いです。 PowerPC上での評価、sourceforgeのコンパイルファームなんかはどうですか? sf.netのはホームディレクトリへのnfsアクセスがものすごく遅いみたいでコンパイルに時間かかりますが。

_い(Wed Dec 15 21:12:51 JST 2004)

 安く手に入るPowerPC環境と言えば「玄箱」でしょう。けっこう遊べます。

_ささだ(Thu Dec 16 00:06:29 JST 2004)

 なるほど。やはり退避は必要ですかね。その辺を自動的に判断させるのは面倒そうだなぁ。

_ささだ(Thu Dec 16 00:07:38 JST 2004)

 sf.net 、速度計測可能なんでしょうか(負荷高そう)。玄箱もそういえば PowerPC でしたね。でもそれなら OpenBloks をちょっと借りる、でも良さそう。

_み(Thu Dec 16 09:43:04 JST 2004)

 PPCは、OpenBlockSSが転がってたよね。さらに、手元にLinkStationがある。当然、ディスク取り出してtelnetdやftpがのってたりする(こんなときのために、研究室にディスクケース付マシン置いたのだけどね)。というわけで、僕は、Macは大嫌いだけど、玄人好みの「玄箱」は好きよ。

_14(Tue)

SC での分岐の合流が解けない・・・.どうしたもんだか.SC 操作命令を入れないと駄目かも.pop して sc に入れるような.


しまった、歯医者の予約忘れてた orz


Allegro CL で OpenGL,何するんだろう.

すちゅーでんとえでぃしょん,$99 だって.ちょっとほしいけど,CL は使えません.あの開発環境の評価みたいなのはほしいかな.あと,Ruby -> S-exp を実行できるかの検証とか.YARV より速そうだよな orz


バグが取れんのぉ・・・.


歯医者再予約したら,クリスマスイブ.

orz


スタックキャッシングの状態の調整は,やはり難しい.ジャンプの合流地点でどうのこうのするのがとみに難しい.で,最適な答えを出すのは,もっと難しいような気もする.余計な swap を入れてみたりね.


C レベルで Array#insert 相当のことが簡単に出来ないことに気づく.どうしよう.途中に一個追加したいだけなんだが・・・.

VALUE rb_ary_insert_one_element(VALUE ary, int idx, VALUE e){
  VALUE rest;
  struct RArray *a = RARRAY(ary);

  if(a->len < idx){
    rb_bug("rb_ary_insert_one_element: idx is too large");
  }

  rest = rb_ary_new4(a->len - idx, a->ptr + idx);
  a->len = idx;

  rb_ary_push(ary, e);
  rb_ary_concat(ary, rest);
  return ary;
}

こんなのをでっち上げる.


どうにもわからないと思っていた swap.

状態を ab -> ba にして,レジスタの値も swap していた.どっちも変えたら swap にならないじゃないか orz

しかし,どうやったら固定に出来るんだろう・・・.できれば代入操作はしないで状態操作だけでやりたいよな.


任意の n 個の stack caching 用コードを自動生成する方法,考えるとえらい大変だな.まじめにきちんと頑張って考えれば出来そうだけど.頭が悪いので出来ない.


例によって,なんでかよくわかってないけれど,動くようになった.


うう,なんとか動いた・・・と思ったら segv


今日のはまり.

      switch(insn_id){
      case BIN(jump):
      case BIN(if):
      case BIN(unless):
        if(state == SCS_BA){
          ...
          goto redo_point;
        }
        
      case BIN(nop):
        ...
        break;
      }

... がある程度長くて油断した.


メモリを開放しないといけないのに,しなかったりするのをメモリリークというが,スタックマシンにおいて,スタックからポップしなきゃいけないのにしないのをスタックリークというんだろうか.これが沢山ありそうで嫌だな.


直せ,はないよなぁ・・・ orz


connect24 で知ったんですが,asahi.com : 就職・転職 - 恥じらいなき社員の職場破壊

いろいろ思うところがあります.

_maeda(Tue Dec 14 23:24:40 JST 2004)

 ラベルでのスタックキャッシュ状態の調整: コードを出すときにラベルの状態が決まって、もう1パスしてジャンプ命令の状態遷移を決める、じゃダメ?

_ささだ(Wed Dec 15 00:07:11 JST 2004)

 それが最適な調整であるかを決めるのはできるのかちょっと不明な気がします.今回は,例外の合流地点での状態を決め打ちし,また分岐での合流では最初にそこにジャンプする奴にあわせることにしました.

_13(Mon)

たしかに,ゲームギアだったら殴るよなあ.


私が「rb_yield が遅い」と言った部分だけで変な理解が広がっちゃってたら嫌だなぁと思っただけで,それだけ理解されていれば問題ないです.


「〜〜について,何か問題がある」という話を聞いて「じゃぁその問題が発生するテストプログラムを作って」と言ったら「なんでそんなもの作らないといけないんですか」「そんなもの作ってる時間はない」と言って,納得してもらえない.

なぜだろう.


吝か(やぶさか) を知った.


いろいろな人が居るもんだなあ・・・.


2004年度C&C賞表彰式・受賞記念講演のご案内 とても行ってみたいけど,とても怖そうだ.


和服でバイクはやっぱり無理だろうか.


雪駄,下駄.setter, getter.

草履は?


YARV では各命令がかなり高機能である.これは,ruby の構造に強く依存しているので,もっと低レベルな仮想機械を想定するとどうなんだろうなぁ,とちょっと考えたけど,面倒なのでやめ.

他の言語とか考えたとき,どうなのかな,って思ってみたんだけどね.実際に,他の言語を実装してみたとき,何か起こるに違いないので,楽しみにしておこう.


VM のデバッグというかチューニングが面倒なので,コンパイル結果のアセンブラ出力を C ソースコードに混ぜ混ぜしようと思ったら,意外と,というか,えらい大変.なかなか単純には行きませんねえ.


INSN_ENTRY(nop){
  /* prepare stack status */
{
  /* declare stack push val */
  /* declare and initialize default opes */
  /* declare and get from iseq */
  /* declare and pop from stack */
  /* for debug */
  DEBUG_ENTER_INSN("nop");
  USAGE_ANALYSIS_INSN(BIN(nop));
  /* management */
  ADD_PC(1+0);
-- 0027 ------------------------------------
	addl	$4, %esi
--------------------------------------------
  #define CURRENT_INSN_nop 1
  #define INSN_IS_SC()     0
  #define INSN_LABEL(lab)  LABEL_nop_##lab
  #define LABEL_IS_SC(lab) LABEL_##lab##_##f
{
  /* none */
  /* push stack val */
#undef CURRENT_INSN_nop
#undef INSN_IS_SC
#undef INSN_LABEL
#undef LABEL_IS_SC
  END_INSN();
-- 0039 ------------------------------------
	movl	(%esi), %eax
	jmp	*%eax
--------------------------------------------
}}
}

INSN_ENTRY(getlocal){
  /* prepare stack status */
{
  /* declare stack push val */
  VALUE val;
  /* declare and initialize default opes */
  /* declare and get from iseq */
  ulong idx = GET_OPERAND(1);
-- 0051 ------------------------------------
L212:
	 # basic block 258
	movl	4(%esi), %eax
--------------------------------------------
  /* declare and pop from stack */
  /* for debug */
  DEBUG_ENTER_INSN("getlocal");
  USAGE_ANALYSIS_INSN(BIN(getlocal));
  /* management */
  ADD_PC(1+1);
-- 0057 ------------------------------------
	addl	$8, %esi
--------------------------------------------
  #define CURRENT_INSN_getlocal 1
  #define INSN_IS_SC()     0
  #define INSN_LABEL(lab)  LABEL_getlocal_##lab
  #define LABEL_IS_SC(lab) LABEL_##lab##_##f
  USAGE_ANALYSIS_OPERAND(BIN(getlocal), 0, idx);
{
  val = *(GET_LFP() - idx);
-- 0064 ------------------------------------
	sall	$2, %eax
	movl	-304(%ebp), %ecx
	subl	%eax, %ecx
	movl	(%ecx), %eax
--------------------------------------------
  /* push stack val */
  PUSH(val);
-- 0066 ------------------------------------
	movl	-300(%ebp), %ebx
	movl	%eax, (%ebx)
	addl	$4, %ebx
	movl	%ebx, -300(%ebp)
--------------------------------------------
#undef CURRENT_INSN_getlocal
#undef INSN_IS_SC
#undef INSN_LABEL
#undef LABEL_IS_SC
  END_INSN();
-- 0071 ------------------------------------
	movl	(%esi), %eax
	jmp	*%eax
--------------------------------------------
}}
}

INSN_ENTRY(setlocal){
  /* prepare stack status */
{
  /* declare stack push val */
  /* declare and initialize default opes */
  /* declare and get from iseq */
  ulong idx = GET_OPERAND(1);
-- 0082 ------------------------------------
L213:
	 # basic block 256
	movl	4(%esi), %eax
--------------------------------------------
  /* declare and pop from stack */
  VALUE val = TOPN(0);
-- 0084 ------------------------------------
	movl	-300(%ebp), %edi
	movl	-4(%edi), %edx
--------------------------------------------
  /* for debug */
  DEBUG_ENTER_INSN("setlocal");
  USAGE_ANALYSIS_INSN(BIN(setlocal));
  /* management */
  ADD_PC(1+1);
-- 0089 ------------------------------------
	addl	$8, %esi
--------------------------------------------
  POPN(1);
-- 0090 ------------------------------------
	subl	$4, %edi
	movl	%edi, -300(%ebp)
--------------------------------------------
  #define CURRENT_INSN_setlocal 1
  #define INSN_IS_SC()     0
  #define INSN_LABEL(lab)  LABEL_setlocal_##lab
  #define LABEL_IS_SC(lab) LABEL_##lab##_##f
  USAGE_ANALYSIS_OPERAND(BIN(setlocal), 0, idx);
{
  (*(GET_LFP() - idx)) = val;
-- 0097 ------------------------------------
	sall	$2, %eax
	movl	-304(%ebp), %ecx
	subl	%eax, %ecx
	movl	%edx, (%ecx)
--------------------------------------------
  /* push stack val */
#undef CURRENT_INSN_setlocal
#undef INSN_IS_SC
#undef INSN_LABEL
#undef LABEL_IS_SC
  END_INSN();
-- 0103 ------------------------------------
	movl	(%esi), %eax
	jmp	*%eax
--------------------------------------------
}}
}

こんなのを吐かせてみた.

ちなみに,これ危ない版.

ローカル変数を得るためだけに,こんなに命令数使ってるんだから,まぁ遅いよな.インタプリタ.

JIT コンパイルも,ジャンプ命令が減るだけだから,そんなに速くならなさそうな気がするなあ・・・.


今日のはまり(もっとはまってますが).

register int *r;
volatile int *v;

v = r = hoge;

で,r = hoge の機械語しか発生しなくてはまった.さて,なぜでしょう.

脱初心者への道は遠い.


INSN_ENTRY(nop){
  /* prepare stack status */
{
  /* declare stack push val */
  /* declare and initialize default opes */
  /* declare and get from iseq */
  /* declare and pop from stack */
  /* for debug */
  DEBUG_ENTER_INSN("nop");
  USAGE_ANALYSIS_INSN(BIN(nop));
  /* management */
  ADD_PC(1+0);
-- 0027 ------------------------------------
	addl	$4, %esi
	movl	%esi, -28(%ebp)
--------------------------------------------
  #define CURRENT_INSN_nop 1
  #define INSN_IS_SC()     0
  #define INSN_LABEL(lab)  LABEL_nop_##lab
  #define LABEL_IS_SC(lab) LABEL_##lab##_##f
{
  /* none */
  /* push stack val */
#undef CURRENT_INSN_nop
#undef INSN_IS_SC
#undef INSN_LABEL
#undef LABEL_IS_SC
  END_INSN();
-- 0039 ------------------------------------
	movl	(%esi), %eax
	jmp	*%eax
--------------------------------------------
}}
}

安全版.まぁ,とりあえずこれでいいや.


問題その2.次のプログラムを gcc でコンパイルして実行すると,どんな出力が得られるでしょう.


int main(){
  register int reg1 asm("esi");
  volatile i = 10;
  reg1 = i;
  {
    register int reg2 asm("esi");
    reg2 = i * i;
    printf("2 %d\n", reg2);
  } 
  printf("1 %d\n", reg1);
  return 0;
}

納得いくような,いかないような・・・.


やはり,でかい部分は無理しても関数化するのがいいような気がしてきたなあ・・・.


そういえば,ruby-eng のりまいんだーが来ないのは,やっぱり青木さんとこの環境変更が効いてるんだろうか.


stack caching,分岐があるとややこしい.どうしようかな.


# PC を volatile 変数に一緒に代入
yarv  0.703000   0.000000   0.703000 (  0.707000)

# 上記をしない(ちょっと危険)
yarv  0.422000   0.000000   0.422000 (  0.411000)

んー.やっぱえらい効くなあ.

しかし,SC キャッシュをレジスタ指定しなかった場合,ほとんど速度差はなかった.どういうこっちゃねん.

_しゅどう(Mon Dec 13 22:33:31 JST 2004)

前に並んでいる命令列の影響とか、stack cachingでのジャンプの扱いとか、当然ながら、僕と同じ轍を踏んでますのう。

_ささだ(Mon Dec 13 23:27:57 JST 2004)

 分岐の話は気にしていなかったという駄目次元だったので,ちょろっと変えました.

_12(Sun)

なぜ私が ruby -d で ruby を使うかというと,私が使うほとんどの場合は ruby のテスト(使い方確認とか動作確認とか)ばかりだからなのです.で,数行のプログラムはそのテスト用環境で作っちゃう.nadoka とかは,-d を付けな・・・付けてますね,私.信用できないから.quickml とかは付けてないです.


さて,これは ruby を使うというんだろうか.


何と比較するかにもよるんですが、"yield" は YARV での整数加算よりも遅い、という話です。yield は遅いから使っちゃだめとかではないです。

ところで素直に ripper じゃ駄目なんでしょうか。

_11(Sat)

2時.資料作った.58ページ.まだ評価を取っていないので,それを取ってから帰るか.髭そらないと・・・.


3時.プレゼン資料.http://www.namikilab.tuat.ac.jp/~sasada/tmp/youth_2004_sasada_mid.pdf

OOo 凄いなー.


さて,プロシン原稿は日曜日昼までに投函しないと間に合わない.しかし,今日土曜日は未踏ユース中間発表である.で,きっと夜遅くまで懇親会だ.間違いない.

どうしよう orz

人の発表中に内職して,明日日曜日の発表が終わり次第学校に戻り,コミットしたものを印刷して郵便局に走りこむというコースか.3時までに出せば次の日10時に届けてくれるそうなので,なんとかそれに間に合わせよう.


しまった.今日は泊まりだったらしい orz 家に帰る気まんまんだったぞ.

どうしやう.


というわけで、今日家に帰ることができないということで、今日中に返却しなきゃいけないマトリックスレボリュージョンズを見る。

どうにも話がよくわからない。前作を憶えてないからかもしれないけど。まぁ、派手な何かができればよかったんだろうか。

しかし、我ながら馬鹿だ。


淺川君の日記に特異メソッド対応って書いてあったので対応。所要時間30分。でも、visibility はいいかげん。body を見てるのがなんなのかよくわからない。まぁ、いいや。

まぁ、この辺は考えるところじゃないしな。


発表終了.

しかし,Ruby 二つをぶつけるのはちょっとやり辛い・・・.今回は先行だったけど,やっぱやりづらい.

淺川君のは楽しい.いいか悪いかは置いておいて,楽しい.書いてるコード量は俺よりも1万行多いらしい(俺 7000行,彼17000).メソッドディスパッチ手法も初めて聞いた.いや,CLOS で聞いたことがあるような気はするな.あれはメソッドキャッシュの手法だったけど.

なかなか .NET との連携は大変ぽい.Win32OLE みたいにすれば簡単かな,とか思ってたんだけど.


速度は YARV が勝ってる.まぁ,そらそうだわな.


プレゼンは惨敗.内部構造の話なんかしちゃだめだって,RubyConf のときに学んだはずなんだが,やっぱり言わないとなぁ.

プロシンで何言おうかなあ・・・.


筧先生談:プログラムは反応がすぐわかる(バグがあればすぐにわかる)が,ドキュメントはよくわからない.だから,ドキュメント製作は大変だ.

うんうん.


やっぱプロシンは内部構造述べたほうがいいような気はするなあ.


やっぱ地味だよなぁ.どうしようかなぁ・・・.なんとかならないかなあ・・・.

喋る内容がなぁ.

_shiro(Sat Dec 11 19:34:08 JST 2004)

一般的には、聴衆が聞きたい内容、知りたい内容は何か、を考えるのがコツでは。目玉になるようなとびきりの新手法の提案ばかりが面白いプレゼンとは限らない。「ちょっと考えるとこれがボトルネックになりそうだけど測って見たら実はこっちだった」とか、「テストコードでは見落としがちだが既存のコードの多くを走らせるには意外にこんなところが障害になった」とか、実際に手をつけたからこそわかるディテールってのも、結構聞いてておもしろいもんです。というのは、手をつけないでもこうなるだろうなと予想できるようなことについては、わざわざ聞く必要もないわけで。手をつけないとわからないことこそ、知る価値がある。

_ささだ(Sat Dec 11 23:30:06 JST 2004)

 実装することで得られた知見ってことですよねえ.そういうのを自覚するのが苦手で.

_shiro(Sun Dec 12 06:52:47 JST 2004)

 対象となる聴衆と似たような人を捕まえて、飯でも食いながら自分のやってることを簡単に話してみます。そこで質問が多く出た箇所とか、感心された箇所なんかが要注目箇所です。

_ささだ(Mon Dec 13 13:31:29 JST 2004)

 誰を考えるかなあ.

_10(Fri)

最初、書くことが無いなあと思ってなんでもかんでも放り込んでいったら10ページ。まだ評価の節を入れないといけないのでそれを含めて10ページにしないと。

今度は削る作業。


何か誤解があるようですが、Linux で C 言語なんて、YARV をビルドするときくらいしか使っていません。いや、svn でとってきてビルドするだけだから、C言語自体は滅多に触りませんね。先日 amd64 で yarv が全然動かないのをデバッグしたくらいか。でも、Linux 関係ないな。

自分で書くときはもっぱら cygwin/gcc か VC を使います。もちろんインラインアセンブラなんて使ったことないですよ。MIPS用シミュレータでしか。

未だに signal とかファイルシステムとか、よくわからないんだよな。signal ってトランポリンで実装しなくていいのん? とか。

正直なところ、実装よりの話は知らないことも無いんだが、利用方法(こういう場面ではどういうシグナルを利用するとか、これこれのコマンドをどう使うとか)は全然知らないんですよね。やっと SIGKILL でいろいろ殺せることを最近知ったくらいで。パイプとか select とか、C言語レベルで使ったこともありません。実際の場面で。

C 言語でポインタを使ったプログラミングができる
できるできる。多分。
ただし関数ポインタは使った経験がなくてもよい (なんでもここに壁があるらしい)
あー、使ったことない事もないなぁ・・・。でも、まだネイティブコードを生成して関数もどきを動的に作るようなことはしたことがないんで、やっぱり初心者(さっさとやれよ)。
Linux の経験については cd, ls, cp, mv あたりはわかっていてほしい
知ってる知ってる! あー,でも青木さんの要求する「わかる」というレベルには行ってないような気がするな.
エディタが使えるのも必須
秀丸が使えます。emacs や vi は全然使えてません。

もうひとつの誤解が、レビュー申し込んだつもりは無かったんです。あそこでああ書くのは紛らわしかったな・・・。


忙しい言いながら、キルビルを見る。なんかグログロでアレだった・・・。いや、返却期限があとちょっとなんですよ・・・。やっぱ借りるんじゃなかった。

まだマトリックスレボリューションズが残ってる。うぅ。


さて,評価書こう.もう,大雑把でいいや.


意外な新事実.YARV の yield は遅すぎ.times{|i| ...} は速いんだけど,times{...} は YARV のほうが遅い.要するに,ブロックローカル変数領域の確保は遅いけど,yield 自体はそんなに遅くないってこと.まぁ,そりゃそうか,という気がしないでもない.これについてはプロシン原稿には触れないでおこう・・・.しかし,困ったな,どうしよう.

というわけで,yield のコストが気になる部分は,やはり最適化しなければならない.

どうしたもんだかね.

いや,先日のインライン化の話は,あれはあれで十分に効果的であるとは思ってるんですが,あの方式だと,他のものを対応させるのが面倒でね.あと,ruby -> C -> ruby ... を繰り返すものがあった場合,やっぱり遅い.

どうしたもんだかなあ・・・.

全てを Ruby で書かせるってのが一番速くなるし最適化しやすいしいろいろと美しいところもあると思うんだが,そうではないというのもあるしなあ.


http://www.namikilab.tuat.ac.jp/~sasada/tmp/prosym2005_a1.pdf.一歩手前.


来年は木山軍団がやってきて RubyVM 追いつかれそうだ.どうしよう.


http://www.namikilab.tuat.ac.jp/~sasada/tmp/prosym2005_a2.pdf.うささんに色々ご指摘頂きました.ありがとうございます.

でも,明日の資料が出来ていない.どうしようかな.

_青木(Fri Dec 10 17:18:11 JST 2004)

 いや、こっちもギャグなので。

_ささだ(Fri Dec 10 18:07:26 JST 2004)

 実はLinuxでC本はギャグ本だった説.

_9(Thu)

一気に書いたので疲れた・・・.

さて,評価何で取ろうかなあ・・・.

いや,二つしか選択肢は無いんですが.

  • 現在のベンチマークで Ruby と YARV を比べる
  • 現在のベンチマークで Ruby と YARV(最適化 1) YARV(最適化 2)... を比べる

いや,後者のほうがいいってわかってるんだけどね.たとえば Stack Caching はまだまともに動いていないので,評価できなくなるし.でも,SC は動くものだけでも載せておきたい.while loop だけでも載せるか.SC だけは特別視して.

動くものだけでなんとなく評価取るってのはアリなのか.うーん,どうしようかな.


 #ruby-lang で英語のアブストラクトを直してもらった.いや,助かります.ありがとう>drbrain


しかし,今日のゼミはきつかった.時期的に.


目がかすんできたよパトラッシュ.


プロシン締め切りが今日投函だったのを待ってもらって,月曜必着にしてもらって.

土日は未踏ユース中間報告会で.しかも初日の最初.

さて,何時資料を作ろう.

rubyconf の資料とか写真を使いまわしてお茶を濁すかなあ・・・.

_み(Thu Dec 09 21:17:23 JST 2004)

 漏れも今日は辛かった…けどねぇ、時期的に限界だし。

_8(Wed)

while loop は 10倍速くなったけど、times などのイテレータを利用すると1.x 倍しか速くならない。これは、Ruby 処理系としては失敗だよな・・・。

block inlining を真面目に考えないと駄目か。うーん、なんとかならないかなー・・・。


というか、いろいろ遊びすぎた orz 。真面目にやばい。とてもヤバイ。

攻殻機動隊なんて見てる暇ないよ orz。


やべえ、summary の subject 、ruby-eng のものをコピペしたまんまだった。しまったなぁ。


切羽詰るとアイデアが生まれる。

5.times{|i|
  ...
}

は、ブロックを

{|i|
  cnt = 0
  max = 5
  while cnt < max
    i = cnt
    ...
    cnt += 1
  end
}

に変換することでまったく等価に処理が可能である。あ、break とか redo は微妙だな・・・。この例では問題ないかな。多分。

まぁ、rb_yield 遅いよウワーン問題は、これで解決ってことでいいんじゃなかろうか。


[1,2,3].each{|e|
  ...
}

#=>
{|e|
  cnt = 0
  while cnt < ary.length
    e = ary[e]
    ...
  end
}

Array#length と Array#[] を特殊化すればいいやね。

これなら変換はむちゃくちゃ簡単だ。

・・・多分。


shelarcyさん通ったのか。めでたい。


さて、コンパイル時どうなるのかな。うーむ。この結果をコンパイルすることになるのか。AOT だと大変そうだな・・・。それ用もコンパイルすることになるのかしらん。


そういえば、論文なんて久しぶりに書いてるから、句読点を「.,」にするのを忘れていたよ。

駄目学生だ・・・。

今日一日で7ページまで行った。図と評価と関連研究とまとめと参考文献をでっちあげれば、後2ページは埋まるな。

いや、今日からはじめてる時点でダメダメなんだけど orz。

_hdk(Wed Dec 08 10:23:45 JST 2004)

 Cからのyieldが遅くてRubyからのyieldが遅くないのなら、変換というか、標準クラスの実装をCからRubyというかVMコードに移したほうが速くなる場合があるという話なのかなと思いました。

_ささだ(Wed Dec 08 11:19:53 JST 2004)

 違います。yield 自体重いのでイヤンという話です。

_hdk(Wed Dec 08 11:34:42 JST 2004)

 そうなのですか。。変換だと、メソッド再定義に弱いんじゃないかなーとか思ったのですがまた出直してきますorz

_ささだ(Wed Dec 08 12:37:30 JST 2004)

 変換対象を使うのは each ですから。キャッシュなどは考えないと駄目だろうけど。

_shiro(Wed Dec 08 16:45:24 JST 2004)

 ブロック中から呼び出した関数の中で継続を捕獲して、eachを抜けた後に再開しても大丈夫? 元のtimesやeachのセマンティクスがcntの上書き前提であったのならいいですが。

_ささだ(Wed Dec 08 17:07:25 JST 2004)

 駄目じゃん orz

_ささだ(Wed Dec 08 17:12:01 JST 2004)

 でも、たとえば times や each を Ruby で実装すると、再開はしません。このあたりはどうあるべきなんだろう。現状は、C で実装されてるから「たまたま」再開されただけのような気がします。どうあるべきかはちょっとわかりません。

_ささだ(Wed Dec 08 17:26:54 JST 2004)

 つまりは、Ruby レベルで継続を考慮したイテレータを作るのは不可能ってことなのかな? YARV レベルでそれをサポートするには、継続情報として保存するべき領域を別にとって、そいつにアクセスするようにしないと駄目、ってことかいな。メソッドフレームに、そういう領域を用意すれば、出来ないことは無いような気もする。

_shiro(Thu Dec 09 06:05:30 JST 2004)

 まあ、そこまでして継続をサポートすべきかっていう話になるんじゃないでしょうか。第一級の継続は意味的にはクリーンなのですが、実装戦略を縛ることは確かです。

_7(Tue)

なんとなく win32ole で遊ぶ。

require 'win32ole'

ppt = WIN32OLE.new("PowerPoint.application")

pres= ppt.Presentations.add
slide = pres.Slides.add 1, 11
text  = slide.Shapes.Item(1).TextFrame.TextRange
text.text = "Hello PPT"
text.font.size = 72

5.times{|i|
  slide = pres.Slides.add i + 2, 2
  text  = slide.Shapes.Item(1).TextFrame.TextRange
  text.text = "page #{i + 2}"
  text  = slide.Shapes.Item(2).TextFrame.TextRange
  text.text = "this is page #{i+2} contents"
}

pres.SlideShowSettings.Run

面白い。これなら、rd から PPT生成も出来るね。頑張ればすぐに出来そうだが。

定数ってどうやって取るんだろうな。即値になってしまったが。


命令数、実に371個。多すぎ。


stach caching、動いちゃったよ。ちょっと信じられない(オイ)。

しかも、速くなってるよ。ありえない(マテコラ)。

ヤター。かなり嬉しい。2 level stack caching のコード自動生成系。


gcc では遅くなった orz。さっきのは vc の g-。

んー、while ループでしか試して無いんだけど(ほかを動かすのが怖い)、なんで駄目なんだろうなあ。命令数は明らかにキャッシュしたほうが速いのだが。マイクロオペコードになったとき、レジスタに載らなくなっちゃったりするのかしらん。


うーん、例によって、どこを見ても遅くなっている原因がわからない。キャッシュかなぁ、キャッシュかなぁ。


というわけで、今度はほんとにさっぱりさっぱりわからない。

この程度の規模なら、branch prediction とかの問題は関係ないはずだし。うーん、うーん。

わからんわからん言ってるまとめ>[yarv-dev:354] Stack caching


VTune 入れて解析するかなあ。


gcc では、なぜか再起動したら SC できちんと速くなった。なんでだろー、なんでだろー。

VC では、やっぱり SC なしのほうが速い。なんでだろー、なんでだろー。

VTune で見ると、misprediction of indirect jump の値がでかい。


cygwin/gcc 3.3.3
yarv  1.782000   0.000000   1.782000 (  1.796000) direct threaded / SC
yarv  2.000000   0.000000   2.000000 (  2.009000) direct threaded / SC なし
yarv  2.562000   0.000000   2.562000 (  2.588000) switch/case / SC あり
yarv  2.875000   0.000000   2.875000 (  2.918000) switch/case / SC なし

なんとも、非常に理想的な値が出てきてくれた。

スタックキャッシュの変数を register VALUE reg asm("regname"); にしてみた。

yarv  1.640000   0.000000   1.640000 (  1.719000) direct threaded / SC
yarv  1.703000   0.000000   1.703000 (  1.735000) direct threaded / SC なし
yarv  2.468000   0.000000   2.468000 (  2.483000) switch/case / SC あり
yarv  3.062000   0.000000   3.062000 (  3.102000) switch/case / SC なし

うーむ、レジスタの使い方がうまくなったか。

ちなみに、asm をつけない、ただの register 指定子は元からつけてたんだけど。

yarv  0.906000   0.015000   0.921000 (  0.904000)

レジスタの使い方を変えたらこれだけ速くなった。これが限界だろうか。


gcc のバグ? にあたった。

func(){
  register int reg asm("eax");
  reg = val;
  ...
  {
    (途中の何か)
  }
  print(reg);
}

で、(途中の何か)を実行中に eax を上書きしてしまっている。

どうしたもんかなあ。

かなり危険、と考えたほうが無難か。

_6(Mon)

最適化したら遅くなってしまった。大変困った。どうしよう。

具体的には、命令融合。

なんつうか、ガックシ。icache ミスってことだろうか。それとも、命令スケジューリングが崩れたか。


不思議。一個だけ融合すると、遅くならない(ちょびっと速くなる)けど、二個融合すると遅くなる。謎。

icache miss かなぁ・・・。


原因がわかった。関数の位置だった。さて、わかったはいいんだけど、なんでなのかもよくわからないんだよな。やっぱ icache か。

つまり、

switch(insn){
  ...
  case insnA:
    ..
  case insnB:
    ..
}

と、

switch(insn){
  ...
  case insnB:
    ..
  case insnA:
    ..
}

の性能が違うって意味なんだな。さて、どうしてくれよう。

命令の利用率に従って並び替えるような何かを作ったほうがいいんだろうか。しかし、困ったもんだなあ。これからどんどん大きくなるというのに。小さいサイズにしたほうが、結局速いって結果になるのかもしれないな。スタックキャッシュは1個で。うわー、なんてこった。

ちょっと、別の環境でも試してみよう。


面白いことに、命令名でソートしたら、少し速くなった。もう面倒だからこれでいいや。


要するに、C コンパイラはそんなに賢くないと思わないとあかんのかなぁ。


そもそも、そんなに効果が無い(コストがかからない)ところでサイズばかりがでかくなって、性能が落ちた、というところか。

まずはスタックキャッシングをきっちりやらないと、ということか。でも、なんとなくスタックキャッシュレジスタは1個がいいような気もしてきたなぁ。全部手で作るのなら、1個できっちり作るのがいいんだろうけれど。


んー、やっぱり遠くに飛ぼうとすると遅くなるのか。


わからんなぁ。やっぱり。


解決。-fno-crossjump ですた。


VC は、int const hoge = 1; とやっても、hoge をスタックにとってくれやがる。しかも、毎回そのスタックの値にアクセスしやがる。しょうがないんで、その変数を define してやった。

そうしたら、構造体のメンバ名とバッティング orz。


しょうがないので、構造体のメンバ名を変更。ヨワ。


amd64 でやると、オペランド統合したほうが遅い。困ったなあ。こっちは何が原因なんだかようわからん。


VC、-Og- をはずせば十分 gcc に匹敵するほど速くなる。でも、不安定になるかもしれないから安全策のためにこのままらしい。

とりあえず、私もそのまま様子を見るか。


スタックキャッシングについて考えているんだけど、これほんとに自動化できるのか。どの程度頑張れるか。

_shiro(Mon Dec 06 06:27:50 JST 2004)

 ジャンプテーブルにコンパイルされているのは確かなの? > switch

_ささだ(Mon Dec 06 09:46:40 JST 2004)

 gcc の場合、threaded code にしてますので明示的にジャンプテーブルになってます。ことの顛末はこちらのスレッドをご参照ください。>[yarv-dev:346] Operand unification

_ささだ(Mon Dec 06 09:46:56 JST 2004)

 いや、全部が全部解決したわけじゃないんだよな。

_shiro(Mon Dec 06 11:34:54 JST 2004)

 あーなるほど。コードが細切れになって分岐予測が無効化されちゃうと痛いってことかな。

_ささだ(Mon Dec 06 13:29:22 JST 2004)

 それもありますが、そもそも分岐命令が一個増えるって嫌な感じです。

_5(Sun)

ruby  1.562000   0.000000   1.562000 (  1.617000)
yarv  1.266000   0.016000   1.282000 (  1.270000)

break、だいぶ速くなった。でも、やっぱりまだ不十分かなぁ。

十分速いとは言えないが、まぁとりあえず許してもらおう。頑張ればもうちょっと速くなる。


例のOSSとガラパゴス諸島がどうの、という話を /.jp で読んでいたら、やっとガラパゴスシステムズの意味がわかった。遅すぎ。

_4(Sat)

ary = Array.new(10)
100000.times{
ary.each{|e|
  ary.each{|ee|
    ary.each{|eee|
      break
    }
  }
}
}

ruby 16.781000   0.000000  16.781000 ( 16.821000)
yarv 75.047000   0.015000  75.062000 ( 75.340000)

break が死ぬほど遅い。どうしようかな。

たしかに、break のたびにオブジェクトを一個作るので、重いに決まってるような気もする。しかし、他の方法で実装するにしても、どうやったもんだろうなあ。

ensure などで、途中で ruby code 走らせるから、thread に持たせるという実装にはしなかったのだけれど、push/pop でやったほうがいいのかしらん。

_3(Fri)

とにかく require が出来ないのは致命的なんだよな。どうしよう。うーん。


rb_iterate がうまく動かない。実は、どの辺がまずいのかもよくわかっていない。うーんー。pure ruby でやれば動くのはわかってるんだけど。うーむ。


ようするに、IFUNC について考えて無いんだよな。うーん。思いつかない。

_2(Thu)

rb_funcall の仕様を間違えてただけだった(rb_call と間違えた)。

undef respond_to? をしていたらどうなるんだろう。困るだけで終わりかな。するほうが悪いよな、きっと。


読みたい論文があって図書室へ行くとちょうどそれが載っている号が無い orz

そんなところできっちりオチを付けてくれる必要は無いから。


rb_iterate にきちんと対応しないと enumerable 系は全滅かー。どうしようかな。

yield に一個分岐が増えちゃうなあ。まぁしょうがないのか。


命令の利用法の集計と、レジスタの利用法の集計するものを入れた。

C で ruby のハッシュを使うプログラムだが、なんというかちょっと疲れる。そもそもハッシュでなんかやるっていうのも結構大変だしね。

しかし、名前を analysis hoge にしたのは失敗だったかなぁ。でも、statistics ってなんか嫌い。


というわけで、bigram もとってみた。でも、小さいプログラムしか走らせていないため、よくわからない。

単純なバイグラムにすると、メソッドをまたいだ命令まで集計してしまうなぁ。まぁ、いいか。メソッドフレームを作ったり消したりする命令では、数えなければいいだけか。

def m
end

i=0
while i<1000
  i+=1
  m
end

こんなプログラムだと、

= Usage Analisys

== Insn/operand usage
getlocal:
  count: 2001
  operands:
  = 0:
   > 2       : 2001
setlocal:
  count: 1001
  operands:
  = 0:
   > 2       : 1001
putnil:
  count: 1001
  operands:
putself:
  count: 1000
  operands:
putobject:
  count: 2002
  operands:
  = 0:
   > 1000    : 1001
   > 0       : 1
   > 1       : 1000
pop:
  count: 1000
  operands:
methoddef:
  count: 1
  operands:
  = 0:
   > :m      : 1
  = 1:
   > <ISeq:m@../test.rb>: 1
send:
  count: 1000
  operands:
  = 0:
   > :m      : 1000
  = 1:
   > 0       : 1000
  = 2:
   > false   : 1000
  = 3:
   > 0       : 1000
  = 4:
   > 0       : 1000
end:
  count: 1001
  operands:
  = 0:
   > 3       : 1000
   > 4       : 1
jump:
  count: 1000
  operands:
  = 0:
   > -24     : 1000
unless:
  count: 1001
  operands:
  = 0:
   > 17      : 1001
opt_plus:
  count: 1000
  operands:
opt_lt:
  count: 1001
  operands:

== Register usage:
  0 get pc   : 29018
  0 set pc   :  2001
  1 get sp   : 19011
  1 set sp   : 17011
  2 get cfp  :  4004
  2 set cfp  :  2001
  3 get lfp  :  4002
  3 set lfp  :  2001
  4 get dfp  :  2001
  4 set dfp  :  2001
  5 get self :  1000
  6 get iseq :     2

== Insns bigram
getlocal         - putobject       :  2001
setlocal         - getlocal        :     1
setlocal         - putself         :  1000
putnil           - end             :  1001
putself          - send            :  1000
putobject        - setlocal        :     1
putobject        - opt_plus        :  1000
putobject        - opt_lt          :  1001
pop              - jump            :  1000
methoddef        - putobject       :     1
send             - putnil          :  1000
end              - pop             :  1000
jump             - getlocal        :  1000
unless           - getlocal        :  1000
unless           - putnil          :     1
opt_plus         - setlocal        :  1000
opt_lt           - unless          :  1001

こんな感じ。これだけ見ても、アレだなぁ。

とりあえず fib を速くしてみようか。


def fib n
  if n < 3
    1
  else
    fib(n-1) + fib(n-2)
  end
end

fib(14)

を実行して、

= Usage Analisys

== Insn/operand usage
getlocal:
  count: 1505
  operands:
  = 0:
   > 2       : 1505
putself:
  count: 753
  operands:
putobject:
  count: 1883
  operands:
  = 0:
   > 14      : 1
   > 1       : 753
   > 2       : 376
   > 3       : 753
methoddef:
  count: 1
  operands:
  = 0:
   > :fib    : 1
  = 1:
   > <ISeq:fib@../test.rb>: 1
send:
  count: 753
  operands:
  = 0:
   > :fib    : 753
  = 1:
   > 1       : 753
  = 2:
   > false   : 753
  = 3:
   > 0       : 753
  = 4:
   > 0       : 753
end:
  count: 754
  operands:
  = 0:
   > 3       : 1
   > 4       : 753
jump:
  count: 377
  operands:
  = 0:
   > 25      : 377
unless:
  count: 753
  operands:
  = 0:
   > 4       : 753
opt_plus:
  count: 376
  operands:
opt_minus:
  count: 752
  operands:
opt_lt:
  count: 753
  operands:

== Register usage:
  0 get pc   : 19206
  0 set pc   :  1507
  1 get sp   : 13551
  1 set sp   : 11671
  2 get cfp  :  3016
  2 set cfp  :  1507
  3 get lfp  :  2258
  3 set lfp  :  1507
  4 get dfp  :  1507
  4 set dfp  :  1507
  5 get self :   753
  6 get iseq :     2

== Insns bigram
getlocal         - putobject       :  1505
putself          - getlocal        :   752
putself          - putobject       :     1
putobject        - send            :     1
putobject        - jump            :   377
putobject        - opt_minus       :   752
putobject        - opt_lt          :   753
methoddef        - putself         :     1
send             - getlocal        :   753
end              - putself         :   376
end              - end             :     1
end              - opt_plus        :   376
jump             - end             :   377
unless           - putself         :   376
unless           - putobject       :   377
opt_plus         - end             :   376
opt_minus        - send            :   752
opt_lt           - unless          :   753

これを見ると、とりあえず getlocal 2 を融合してみようか、という至極単純なものしか見えてこない。ちなみに、2 は引数の最初。putobject の 1 も、まぁ順当か。


というわけで、今日中にオペランド融合命令生成ルーチンとコンパイル時に置き換えるものを作らないと。


http://olab.is.s.u-tokyo.ac.jp/~oyanagi/reports/SC2004.html を拝見させていただく。すげぇなぁ、やっぱ。死ぬ前に一度は行ってみたいものだ。


親の健康保険の被扶養者から外れるらしい。しょぼーん。いったいいくらかかるんだ。


電話して聞いてみた。(所得額の 4.8%) + 25200。高い。


どうやら、ちょうど「ちょびっと限度額より上」になりそうな予感がする。で、保険とか税金とかで、マイナスになってしょぼーん、という予感。ショボーン。


Ruby のこと(eval.c とか)はよくわからないのですが、ルビィスト・マガジンという表記はショボーンでした。

_1(Wed)

うお、12月になってるよ。 ちょっと待ってくれぇ。


はまり。

OK:  file = "#{year}#{'%02d' % (i+1) }"
NG:  file = "#{year}#{'%02d' %  i+1  }"

いや、考えればわかるんだけどね。でも String#% を使うとき、modulo を意識しないよねえ。



int main(){
  int i;
  for(i=0; i<3;i++){
    if(i%2 == 0)
      goto hoge;
  ret:;
  }

  {
    int x = 123;
    if(0){
    hoge:
      x = 456;
    }
    printf("==> %d\n", x);
    if(x == 456){
      goto ret;
    }
  }
  return 0;
}

こんなコードはどうなんだろうね(駄目です)。

いや、やりたいのは if(0) の中に飛び込む goto は有効かってことなんですわ。

yarv で、

switch(insn){
  insnA:
    A1;
    A2;
    break;

  insnB:
    B1;
    A2;
    break;
}

ってのがあったとき、

switch(insn){
  insnA:
    A1;
  a2_point:
    A2;
    break;

  insnB:
    B1;
    goto a2_point;
}

と、したいじゃないですか。だけど、それだと A1 の前に初期化するはずだった変数などが A2 から突入すると初期化できないんだよね。

#code
switch(insn){
  insnA:
    A1;
    if(0){
      a2_point:
      initialize_from_insnB;
    }
    A2;
    break;

  insnB:
    B1;
    goto a2_point;
}

なコードを書こうかな、と思ってみたわけなんですが、さて、これはコンパイラさんにとって大変か? フロー解析は大変になるのはわかるが、出力コードの品質にどの程度影響が出てくるか? が気になるわけです。で、上記サンプルを書いてみたんだけど、これくらい小さいと、十分最適化できてるような気がする。さて、yarv のようなでかい switch/case の場合、これはどうなんだろうね、ってのが命題。まぁ、やってみてどれくらい遅くなるか、でいいか。

1.9 sec が 2.0 sec になった。5% 性能低下(cygwin/gcc)。

素直に A1, A2 を関数化(A2 だけでいいか)するのがいいかなぁ。やっぱり。


関数化しようと思ったら、すっかりレジスタ(関数ローカル)変数のことを忘れていた。それへのコミットが出来ないので、関数化できず。しくしく。マクロにするってのは手なんだけどちょっと長すぎる・・・。


static inline だったら、参照渡しすれば勝手にローカル変数参照にしてくれないだろうか。VC だと無理だろうなあ。


やはり頭のいい人の話はわからん orz


 -d で鬱陶しいのは嫌なのでパッチを書いてみた。

Index: eval.c
===================================================================
RCS file: /src/ruby/eval.c,v
retrieving revision 1.738
diff -u -r1.738 eval.c
--- eval.c	30 Nov 2004 17:28:16 -0000	1.738
+++ eval.c	1 Dec 2004 13:18:20 -0000
+NODE *node_Object_respond_to = 0;
+ID   id_Object_respond_to    = 0;
+
 int
 rb_respond_to(obj, id)
     VALUE obj;
     ID id;
 {
-    if (rb_method_boundp(CLASS_OF(obj), id, 0)) {
-	return Qtrue;
+    volatile VALUE klass = CLASS_OF(obj);
+    if (rb_method_node(klass, id_Object_respond_to) == node_Object_respond_to){
+	if (rb_method_boundp(klass, id, 0)) {
+	    return Qtrue;
+	}
+    }
+    else{
+	VALUE sym = ID2SYM(id);
+	return rb_funcall(obj, id_Object_respond_to, 1, &sym);
     }
     return Qfalse;
 }
 
+
 /*
  *  call-seq:
  *     obj.respond_to?(symbol, include_private=false) => true or false
@@ -7596,7 +7647,9 @@
     rb_define_global_function("loop", rb_f_loop, 0);
 
     rb_define_method(rb_mKernel, "respond_to?", rb_obj_respond_to, -1);
-
+    id_Object_respond_to   = rb_intern("respond_to?");
+    node_Object_respond_to = rb_method_node(rb_cObject, id_Object_respond_to);
+    
     rb_define_global_function("raise", rb_f_raise, -1);
     rb_define_global_function("fail", rb_f_raise, -1);
 
Index: object.c
===================================================================
RCS file: /src/ruby/object.c,v
retrieving revision 1.162
diff -u -r1.162 object.c
--- object.c	29 Nov 2004 06:09:40 -0000	1.162
+++ object.c	1 Dec 2004 13:18:20 -0000
@@ -2056,9 +2056,10 @@
     const char *tname, *method;
     int raise;
 {
-    VALUE result = rb_funcall_rescue(val, rb_intern(method), 0);
+    ID m;
 
-    if (result == Qundef) {
+    m = rb_intern(method);
+    if (!rb_respond_to(val, m)) {
 	if (raise) {
 	    rb_raise(rb_eTypeError, "cannot convert %s into %s",
 		     NIL_P(val) ? "nil" :
@@ -2068,11 +2069,10 @@
 		     tname);
 	}
 	else {
-	    ruby_errinfo = Qnil;
 	    return Qnil;
 	}
     }
-    return result;
+    return rb_funcall(val, m, 0);
 }
 
 VALUE

yarv のパッチが混ざっていたので紛らわしい。

性能評価。

require 'benchmark'

class C
  def respond_to? *args
    true
    @ary = [:C]
  end

  def to_ary
    @ary
  end
end

obj = Object.new
c   = C.new
max = 100000

Benchmark.bm{|x|
  x.report("miss"){
    max.times{
      Array(1)
    }
  }
  x.report("hit "){
    max.times{
      Array(c)
    }
  }
}
パッチ前
      user     system      total        real
miss 11.563000   0.016000  11.579000 ( 11.891000)
hit   6.250000   0.000000   6.250000 (  6.359000)

パッチ後
      user     system      total        real
miss  0.328000   0.000000   0.328000 (  0.328000)
hit   0.625000   0.000000   0.625000 (  0.625000)

これだけ違うのは本当なんだろうか・・・。うーん。同じプログラムを実行しているはずなんだけど。

ちなみに、このパッチでは SEGV りました。そのままでは使えません・・・。だから dev に投げないんだけど。

Sasada Koichi / sasada@namikilab.tuat.ac.jp
$Date: 2003/04/28 10:27:51 $