K.Sasada's Home Page

Diary - 2005 July

研究日記

文月

_31(Sun)

ジャンプ(スコープをまたぐジャンプ)関係を全部片づける。思いつく限りの対応をしたけど、まだ残ってるんだろうなあ。

というわけで、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 を抜ける、というルールは実装するのが大変そうだなぁ...

_m(Mon Jan 23 10:45:32 JST 2006)
ret = Array.new(self.length)
...
  ret[i] = yield(self[i])

だとどうなの?

_ささだ(Wed Jan 25 15:12:56 JST 2006)

 どう,というのはどういうことでしょうか.速度かな.あんまり変わらないような気がするけど.

_baccarat hints(Thu Mar 02 05:23:03 JST 2006)

 A great site where one can enjoy the thought of a great mind long departed. Cheers for the good work!

_30(Sat)

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 だったのか。


そういえば、ヒトクイマジカル読了。もうさっぱりわけわからん。

_29(Fri)

そういえば、博多飲み会の件はどうなったんだろう?


先日、行きの電車で乗り換えの情報を知りたくて携帯電話でウェブを見て探してみたんだけど、全然見つからない。

見つかっても、有料だったり JavaScript 必須だったり。

そのときは、ちょっと急いでいて、少しでも早く目的地に着きたかったので、困った。誰かに電話なりメールなりして調べてもらうという最終手段はあるというものの。

デスクトップでは何も考えずに検索できてしまうため、いつもは気にならないのだけれど。

なんかいいサービスありませんかね。メールで検索結果を返すプロキシシステムでも、ちょっと作ろうかしらん。


あら、なんではねられてるんだろう。

ML 作りましょうか ruby-enkai-kyusyu-2005-summer at quickml.atdot.net で、CC は ko1 at atdot.net で。遊んでくれる人ご参加ください。

予定としては、

  • 8/2 羽田 -> (13時ごろ着)福岡(博多に前泊)
  • 8/3 (朝)博多 -> 武雄温泉(ソファーに2泊)
  • 8/5 武雄温泉 -> (19時には着予定)博多(博多泊)
  • 8/6 (16時くらい)福岡 -> 羽田

こんな感じなんで、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.

_nagai(Fri Jul 29 15:49:20 JST 2005)

 飲み会の件のメールがはねられたので,こちらに辿ってきたら丁度書き込みが.(^_^; 空き時間等はどうなってますか? できれば後はメールで打ち合わせをしたいと思ってます

_shiro(Fri Jul 29 20:19:56 JST 2005)

パターンマッチは単一の値だと面白くないんじゃないすか。構造をdestructuringして、そのうちの一部を即値や型とマッチさせて他を変数にバインドする、みたいな場合は、パターンマッチだと一発ですが手で条件を記述すると大変。

_shiro(Fri Jul 29 21:10:37 JST 2005)

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 ......)))

_28(Thu)

やっとコミった。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 に、利用例を入れてみた。

頭が悪いので、実際に書いてみないとわからん。

_27(Wed)

というわけで、スタックを分けることにしたんだけど、遅くなった。

コントロールフレームポインタ用の 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
_雪見酒(Wed Jul 27 08:47:19 JST 2005)

 32bit Winは動きますが、vmwareは32bitアプリケーションで、64bitOSは動きません

_ささだ(Wed Jul 27 11:04:30 JST 2005)

 なるほど、ありがとうございます。となると、やるなら 64 bit OS 上で VMWare 動かして・・・なんだろうか。

_雪見酒(Wed Jul 27 12:35:36 JST 2005)

 はい、vmwareは64bitOS上(Windows/Linux)で正常に動く32bitアプリケーションです。vmwareそのものは64bitネイティブではありません。

_26(Tue)

mixi にエントリ作れないけど、若者なら若手の会に行くだろ。


今日も英語がわからず大変悲しい思いをした。


yarv のビルドの時間が30秒弱から1分にふくれてしまった。どうしたもんだか。

_25(Mon)

眠いよー。全然終わんないよー。


Java に「カレントディレクトリ」ってないんですかね?


本郷キャンパスは2度目だったんだけど、ほんとに歴史を感じる建物が多いんですね。なんか木が鬱蒼としていたところもあったし。

そして予想通り迷って、3分前くらいに到着。席は一杯。しょうがないので一番前に座った。

レクチャー自体は英語がわからず半分も理解できなかったんだけど、なんとなく面白かった。

Vista は NT のバージョン何になるのか聞いたら、知らない、とのこと。


スタバで2時間粘ってやっとのことでコンパイルを通した。でも、本当にそれだけ。

_maeda(Mon Jul 25 14:04:21 JST 2005)

 System.getProperty("user.dir")で得ることはできます。変更する機能については、「マルチスレッド環境でcurrent directoryが何を意味すべきか、という議論の結果、割愛された」と記憶しています。

_ささだ(Mon Jul 25 19:58:19 JST 2005)

 いつもありがとうございます。まさに、マルチスレッド環境において、カレントディレクトリをどう対処しているのか知りたくて探してました。なるほど、Java はそうなのか。

_shiro(Tue Jul 26 21:02:14 JST 2005)

 本郷は、でもずいぶん旧い建物を建て替えちゃったんじゃないかなあ。

_ささだ(Tue Jul 26 22:14:09 JST 2005)

 新しい建物もたくさんありましたね。

_24(Sun)

昨日は 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 で作ってしまったほうがいいような気もする。

さっさと動かしてから考えたほうが、と。

頑張ればあと一個くらい減るんだけど。

_t(Sun Jul 24 05:51:22 JST 2005)

理由になるかわかりませんが、(int, int)は

  type ('a, 'b) fuga = 'a -> 'b list;;
  type hoge = (int, int) fuga;;

みたいなとき使います(型のタプル?)

_向井(Sun Jul 24 15:54:54 JST 2005)

 haskellでは (Int, Int)みたいに書くし、単なる慣習という気がします。意味が直積なので int * int というのは素直だと思いますけれど。

_酒井(Sun Jul 24 20:10:47 JST 2005)

 「*」は二項演算子に見えるのに、実際には「int*int*int」は「(int*int)*int」とも「int*(int*int)」とも異なっているのが、なんだか奇妙に感じました。

_ささだ(Mon Jul 25 08:13:16 JST 2005)

 "直積だから" という理屈はわかるんですが、(,) でもいいのに * にしたという理由がわからない、という意味です。

_酒井(Mon Jul 25 22:18:15 JST 2005)

 いや、直積ならば (,) よりも * で表現する方が自然でしょう。

_ささだ(Tue Jul 26 00:17:06 JST 2005)

 ふーむ。

_とおる。(Wed Jul 27 15:37:40 JST 2005)

 (,) は内積。

_h(Wed Jul 27 20:57:14 JST 2005)

 参考までに:「どうして ocaml って list 'a と書かないの?」「Milnerにきいてくれ by Xavier Leroy」

_酒井(Thu Jul 28 00:09:35 JST 2005)

 そ、そーなのか……

_向井(Thu Jul 28 01:16:56 JST 2005)

 camlp4r を使うと list 'a って書けるんですけどね。→拙訳 http://www.jmuk.org/~mukai/camlp4tut.html#label-63 あたりを参考に。それでもタプルは*のままですが……。

_23(Sat)

未踏ユースとおったらしい。あれは通るよねぇ。ふふふ。


エンダーのゲーム読了。大体オチは読めるんだけど、最後の最後、ゲームの風景の再現は良かったなぁ。

_ogino.(Sat Jul 23 00:25:05 JST 2005)

 たのしみですねえ。

_22(Fri)

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 する何かを作ればいいんだよな。

ただの怠慢だった。


ルパンってこんなハリウッドっぽかったっけ?

_21(Thu)

型に重きをおく言語で、がんばれば HTML とかのサニタイズの問題は解決する?


PTT。浅学で、はじめてスタッキングファイルシステムというのをきちんと認識した。


しかし、Ruby でも << じゃなくて += で文字列結合することって多いよね。

...もしかして、俺だけ?

いや、もちろん性能を気にするときには考えますが。

うーん、でも、見た目から効率はあんまり判断できないよなー。


そういえば、Java のコードで、toString 書くの面倒で、"" + 1 とか書いてたんだけど、これはどうなんだろう。

_shiro(Thu Jul 21 11:58:54 JST 2005)

 エスケープ済とそうでないのとを別の型にしてれば(実際意味的には別だし)コンパイラがチェックしてくれるかな。

_ささだ(Thu Jul 21 14:31:14 JST 2005)

 そうそう。そんな感じ。で、どこまできれいなシステムができるんだろう。

_青木(Thu Jul 21 23:48:17 JST 2005)

 いかにも Haskell な人が作りそうな……

_arton(Fri Jul 22 01:37:30 JST 2005)

 っていうか、それはString.valueOf(1)がお勧め。Rubyだとto_sだからかな。ちなみにnew Integer(1).toString() は却下。

_20(Wed)

なんか、時が移るのは早いね、という感想が多いな。


なんか、今回はレスポンスが多いなあ。先月と何が違うんだろう。


indirect threaded code の意味を間違えていた。気づけてよかった。


Rubyist のための他言語探訪 【第 1 回】 Python を読んで混乱した話。

イミュータブルな文字列

Python では文字列を書き換えることはできません。効率を考えるとうれしくないのですが、オブジェクトの書き換えは面倒を引き起こすこともありますから、うれしくないことばかりでもありません。

効率を考えたら immutable な文字列のほうが効率的だよなぁ、と思ったら、うささんに「bang なメソッドが使えるからより効率的」と言われた。

うーん。


http://www7.ocn.ne.jp/~cabinas/ とりあえず、ここが安そうなので、初めてのカプセルホテルに挑戦。

_arai(Wed Jul 20 18:01:20 JST 2005)

 はじめまして。博多で一泊ですか? もしお時間があれば,

_arai(Wed Jul 20 18:01:40 JST 2005)

 こちらで飲み会を企画して、YARVの話をしてもらうかわりに、宿泊費カンパを募るというのはどうでしょう?

_shiro(Wed Jul 20 19:40:12 JST 2005)

bangなメソッドと、部分文字列の共有と、どっちが嬉しいかしらん。

_ささだ(Wed Jul 20 19:56:36 JST 2005)

 十全とはいきませんが、宿泊費くらいはなんとか。ただ、できれば安い宿を教えていただけると ^^; 話すのはなんでもいくらでも・・・。その辺どうしましょう>たむらさん

_ささだ(Wed Jul 20 19:57:51 JST 2005)

 どうなんでしょうねぇ>共有 scheme は immutable でしたよね。

_ささだ(Wed Jul 20 19:58:41 JST 2005)

 そうでもなかった>scheme

_shiro(Wed Jul 20 20:44:28 JST 2005)

 今、R6RSでunicode supportをどうするかで紛糾してるんですが(srfi-75)、「immutableにするか、length changing mutationをサポートしないと意味ないよー」と控えめに主張してます。

_あらい(Wed Jul 20 21:51:11 JST 2005)

あ、申し遅れましたが、むかし未踏に参加していた新井といいます。 安い宿は楽天トラベルあたりで探すと良いかとおもいます。 プラザホテルなどは割と安く、場所が便利なのでよいですね。

話していただけると嬉しいです。 福岡のrubyistが喜ぶとおもいます。

http://www.moodindigo.org/blog/

_なかむら(う)(Thu Jul 21 09:32:17 JST 2005)

 immutableな文字列に関しては、当然実行するプログラムによって優劣が変化するのだと思うのですが、それはともかくとして、一般論としてこの優劣について検証した事例はあるんでしょうかね(私は研究者じゃないので論文が読みたいわけじゃなくて結論が知りたいだけですが)。

_arton(Thu Jul 21 09:36:00 JST 2005)

 Java

_maeda(Thu Jul 21 10:52:29 JST 2005)

 文字列のmutabilityと優劣: 問題に激しく依存するでしょうね。あと、マルチスレッドかどうかとか。ただ、mutableな言語でもコピーしてる場合が多そうだから、共有できると効率は上がるかも?

_たむら(Thu Jul 21 12:47:54 JST 2005)

あ、忘れてた>8/5 おまけに奥さんの実家に行ってていないし。 とりあえず関係者にメールして 8/5の予定聞いときますね。

_ささだ(Thu Jul 21 15:07:25 JST 2005)

 Ruby は共有出来るところはしてますね。オブジェクト(ID)は全部違うけど。

_19(Tue)

旅費振込み完了。

あと、福岡の宿一泊分探さないと。


Universal Studio Japan みたいなのがブラジルにあったら USB になるんだろうか。


Rubyist Magazine 0008 is Released!!


毎月結構大変なんですが、リリースするときはいつも嬉しいものであります。

でも、ネット上での共同作業なので、さぁ打ち上げだ、ということが出来ず、ちょっと残念。


今回のやーまには direct thraeded code の解説だったんだけど、なんというか、重箱の隅というか。


るびま、読んでもらって何ぼなので、何卒宣伝のほど、よろしくお願いします。

_gian(Tue Jul 19 22:08:43 JST 2005)

 パックをつかったんじゃないの?

_ささだ(Tue Jul 19 22:24:20 JST 2005)

 前泊分にパックの宿泊を使ったので、8/5 に泊まる分がないのです。

_18(Mon)

昨日は懇親会、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 を与えられないのね。与えられたほうが色々と楽だと思うんですが。

_shiro(Tue Jul 19 05:31:31 JST 2005)

 thread-specificはsrfi-18でそう定義されてるからですが、たぶん意図としては「alistでもhashtableでも好きなのを入れといてね」ってことなんだと思います。Scheme界ではそのへん、アプリ製作者の裁量に任せちゃうことが多いので、不親切っていえば不親切ですね。

_ささだ(Tue Jul 19 08:58:31 JST 2005)

 はい。意図は理解できますが、たとえば、別作者による複数の module 内で使いまわすのは無理そうですね。

_shiro(Tue Jul 19 09:28:14 JST 2005)

そーなんですよねー。ただkeyとvalueのペアを持てる、というふうにsrfiで決めちゃうと、今度は「keyは何にする? symbolのみ、それとも任意のオブジェクト?」「任意のオブジェクトの場合、何で比較する? eq? eqv? equal?」「全てのキーの一覧を取るAPIは?」等々、細かい議論が噴出して、本来の議論(srfi-18で言えばmultithreading)が霞んでしまうのがScheme 界の常。たぶんこういう「一個だけ値を持てるスロット」の使い方に関するsrfiを別に作る、という方向がScheme的なのでしょうなあ。

_ささだ(Tue Jul 19 10:45:39 JST 2005)

 なるほどねぇ。まぁ、gauche 内では specific じゃなくて parameter を使えということなんでしょうけど。

_17(Sun)

まだスライドが出来ていない。


無事発表終わり。

質問がなくてさびしかった。


BioRuby + ChemRuby の話がすげぇ楽しかった。

_み(Sun Jul 17 15:46:36 JST 2005)

 もっといろいろ聞こうかとおもったら、早目に終らされてしまったorz

_ogino.(Sun Jul 17 17:17:24 JST 2005)

 49倍速くなるのを心待ちにしている人がたくさん。

_16(Sat)

うーん、やっぱり言語デザインの話でしたか。

_15(Fri)

で,日曜日,17日に未踏のキックオフがあるんですが,懇親会が4750円らしい.orz

とりあえずスライド作らないとなぁ.


  • 8/2 羽田 -> 福岡(博多に前泊)
  • 8/3 博多 -> 武雄温泉(ソファーに2泊)
  • 8/5 武雄温泉 -> 博多(博多泊)
  • 8/6 福岡 -> 羽田

8/5 の宿を探さなければ。


今回のインタビューは長いよー。とても長い。

_14(Thu)

今日、家に帰るかどうか悩む。

電車で行けば帰れるんだろうけど。どうせ明日も通学しないといけないしなぁ(だめな発想)。


これは昨日だけど,グインサーガ100巻読んだ.やっと追いついた,と思ったらもう101,102が出ている orz

_13(Wed)

忙しいのがとりあえず通り過ぎたらなんとも怠けきっている。なんとかしないと。


  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 らしい。

_通りすがり(Wed Jul 13 11:04:08 JST 2005)

 ここ数日、RSSの生成ができてないようですよ。この日記。

_ささだ(Wed Jul 13 11:09:45 JST 2005)

 あ、ほんとだ。どうしたんだろう。

_ささだ(Wed Jul 13 11:11:17 JST 2005)

 iconv でエラー吐いてた。iconv をてきとーにするってどうやるんだっけ。

_naruse(Wed Jul 13 14:00:46 JST 2005)

 "Shift_JIS"の代わりに"CP932"を指定すれば、Iconvの実装にもよりますが、多少よくなるかと。

_なかだ(Wed Jul 13 15:40:42 JST 2005)

Iconv.conv("UTF-8", "Shift_JIS", str)

「変換できない文字はブロックに渡して処理」とかも考えてはみたものの…。

_ささだ(Wed Jul 13 21:37:05 JST 2005)

 Iconv.conv は Iconv.iconv(...).join の省略形じゃないんですか?>Rubyリファレンスマニュアル - Iconv

_12(Tue)

sydney ってなんだろう、また新しいのが出てきたのかよ、とか思ったら機能追加なのね。


自宅がB-Fletsになった。今までADSLルータだったのが、無くなったのでファイルサーバを急遽ルータとして使えるようにした。

PPPoE とか DHCP とか、

ちなみに、外向けのNICが10Mのやつしかなかったので、外向きの回線速度は大変遅い。でも、今までのADSLよりちょっと速いくらい。

問題なく使えそうなので、このままでいいや。

_ron(Wed Jul 13 03:28:39 JST 2005)

 Air Stasion WZR-RS-G54 余っているけど、引き取ります?

_ささだ(Wed Jul 13 07:46:06 JST 2005)

 おぉ、これは魅力的ですね。

_11(Mon)

セントラルホテル武雄というところが適当なのかなぁ.でも,一日6000円か.前泊しようとすると18000円.うーむ.

誰かエクストラベッドに寝かせてくれる人はいませんか orz


[swopp-announce:06377] 特別講義のご案内

うおー,これは行かなくては.こういうのができるから東大は凄いよなぁ.


やっと TODO が無くなった.あとはひたすらチェックするだけ.あと7時間.7時間もやりたくないけどな.


そういえば,まつもとさんの集中講義があるんだっけ.もぐりに行くのは無理そうなんで行かないですが,誰かレポート希望.

実装の話を 聞きたい 教えてもらいたい.YARVを49倍速くする方法.

言語のデザインの話は,面倒だからいいや.


あと5時間.あと5時間たてば,YARVでやりたかった実装に手をつけることが出来る.でも,その前に寝るかな.


Scheme は実装が沢山あって,メインストリームになるのはとても困難だと思うが,Ruby はちょっとしか無いから楽だよな.


出した.

そしたら,回答文のところに論文をアップロードしてしまったらしく,回答文は再アップロードできない.

なんてこった.とりあえず,メールしてゴメンナサイしてみる.

しかし,論文をアップロード,の欄に入れたはずなんだがなぁ.寝ぼけてたのかなあ.

_しゅ(Mon Jul 11 13:04:32 JST 2005)

 僕は武雄温泉近くの旅館だけど、それでも6,000円/泊くらい。

_ささだ(Mon Jul 11 13:05:38 JST 2005)

 ネットができるビジネスホテルは無さそうですねえ.ところで,会場はネットワーク引いてるんですか?

_ITScoolの時の者です(Mon Jul 11 13:26:33 JST 2005)

 ログ見たら寝てないようですけど大丈夫ですか?

_しゅ(Mon Jul 11 14:00:20 JST 2005)

 会場には無線LANを設置すると思います。けど、使う人数が人数なので、あまり期待しない方が。

_ささだ(Mon Jul 11 14:04:43 JST 2005)

 駄目です.ところで何のログだろう.

_ささだ(Mon Jul 11 14:05:18 JST 2005)

 なるほど.まぁ,メールくらいはたまにチェックできそうですね.

_10(Sun)

マシン構成を考えると夢広がる。夢だけ。

  • Windows マシン
    • Cel 1.4GHz
    • GA-60XT-A
    • メイン
  • Linux マシン(momonga)
    • Cel 433MHz
    • マザボ忘れた
    • 家庭内サーバ用途

で、

  • Windows マシン
    • AMD64 4000+
  • Linux マシン
    • C3 1.0A
    • GA-60XT-A

みたいにずらそうかな、とか。そうなると、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.うぅ,学生に優しくない.

_sheepman(Sun Jul 10 11:53:26 JST 2005)

 http://search.cpan.org/dist/perl/pod/perlsec.pod#Algorithmic_Complexity_Attacks おもろい

_ささだ(Sun Jul 10 14:54:13 JST 2005)

 英語わかんないので後で頑張って読みます.

_9(Sat)

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講習を受けるといいやがった。絶対無駄だ、と言っても行くといいはる。うーむ。


しかし、久々に雨でびしょびしょになった。数年ぶり。

_えむふる(Sat Jul 09 10:22:45 JST 2005)

 英語がアレなもんなのでExciteで翻訳させたらもっとおかしくなりました。 < /.記事

_zunda(Sat Jul 09 13:45:48 JST 2005)

 確かに! > 息を止めて走りきる感覚。僕は窒息寸前。

_ささだ(Sat Jul 09 14:06:04 JST 2005)

 やっぱ Java デスヨネ.

_8(Fri)

朝日新聞夕刊の一面に、「裾野広げるなでしこ」と大見出しがあってびっくりした。


  そういえば,高橋さんご馳走様でした。あれ楽しみにしています。


■-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 のコピーも無い.

一般に,分岐されやすい基本ブロックを手前に持ってくるのはどういう理由なん だろう.考えられるのは次のとおり.

  • プロセッサのデフォルトの分岐予測は,「分岐しない」を考えるから(ほんと?)
  • x86 に特化した最適化だから
  • 命令キャッシュミスが少なくなりそうだから

ちなみに,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)

インテル&reg; Pentium&reg; 4 プロセッサおよびインテル&reg; Xeon&#8482; プロセッサ最適化リファレンス・マニュアル より引用.

静的予測

BTB (「分岐予測」の節を参照) 内に履歴がない分岐は、静的予測アルゴリズムを使って予測される。Pentium 4 プロセッサ、Pentium III プロセッサ、Pentium Kプロセッサは、以下のような同じ静的予測アルゴリズムを使用する。

  • 無条件分岐は実行されるものと予測する。
  • 条件付き後方分岐は実行されるものと予測する。この規則はループに適している。
  • 条件付き前方分岐は実行されないものと予測する。
  • 間接分岐は実行されないものと予測する。

  • 前方:PC + x
  • 後方:PC - x

うーん.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 を増やして,「今後はそれを使ってください」でいいんだけど,全部書き直しが必要になるわけで.

  • rb_cObject などは TLS に置く 駄目だな,これじゃ.
  • rb_cObject にアクセスするための rb_top_class(rb_intern("Object")) みたいに使う API を作って,rb_cObject をそいつのマクロにする.
  • この辺の基本的なクラスを格納する配列を作る.vm->basic_classes[enumObject] みたいにアクセス.で,マクロでラップ.これかな.

うーむ.

#define rb_cObject (GET_VM_INSTANCE())->basic_classes[idx_of_cObject]

なんか,Ruby が随分と遅くなりそうだなぁ...

_しゅ(Fri Jul 08 09:46:01 JST 2005)

 静的分岐予測では、後方にはまあ分岐するだろう(意味:ループ)、前方にはまあ分岐しないだろう、っていう予測が一般的です。

_なかだ(Fri Jul 08 12:22:11 JST 2005)

 super(&nil)

_ささだ(Fri Jul 08 14:29:27 JST 2005)

 えー.

_7(Thu)

Subversion であるファイルをバージョンコントロール下からはずすにはどうすればいいのかな.svn rm しか無いかな.リポジトリに直接 rm するのは URL 書くのが面倒くさい.


しかも,ワイルドカード効かないし.どうしよ.


checkout して,消してコミットして co したのも消せばいいのか.どうにも working copy は(各マシンで)一個しか持たないという運用しかしたことがなく.


考えて見たら,svn はファイルを rm しても db にはそれが残るんだね.だから,

  1. 大量のゴミと一緒に取りあえず import
  2. checkout して,svn rm して,そして commit

とやっても,リポジトリは大きなままなんだなぁ.しまったなぁ.

バックアップ用のディスクがもう一杯.どうしようかな.svnリポジトリのバックアップに pdumpfs は使えないなあ.


今朝はジョナサンで徹夜.

ピザを頼んだら予想以上にでかくて難儀.一緒にソーセージまで頼んじゃったから.

1200円なり.うぁ,厳しい.財布が.


うおー,もう七夕かよー.この論文の日々が報われる日が来ますように.


Rubyでカリカリにチューンしたコードを書くのも楽しいですが,Rubyをカリカリにチューンするほうがもーっと楽しいです.


うわー,sicp 明後日か.行けねえ orz


TLS (__thread とか)について調査.グローバル変数と速度差を見る.実はあんまり違わなかった(debian sarge).

誰か,もうちょっと詳しい調査知ってる人いませんか?


TLS は,ruby with native thread で使いまくりっぽいので.


YARV 0.2.1 released。なんとか七夕リリース。

リリース告知は明日。

_shugo(Thu Jul 07 12:35:10 JST 2005)

pdumpfsでやってたのかー。

自分はpost-commitでsvnadmin dump --incrementalしたやつをbzip2で圧縮してhttpsで取得 できるところにおきつつ、リモートのバックアップマシンにGPG署名したメールで通知してます。

_ささだ(Thu Jul 07 12:57:51 JST 2005)

 というか,HOMEをバックアップしてて.その下にリポジトリを作ってました.

_こーのいけ(Thu Jul 07 23:51:22 JST 2005)

 リポジトリから消したいならsvndumpfilterで。

_6(Wed)

送りますた.そして帰れないこと決定.今日は布団で寝たかった.


さて,そして今度は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分しか喋んなかったら怒られるんだろうか・・・.

日本人沢山居るから,日本人になんか喋らせよう.


国立で中華.ご馳走様でした.おいしかったです.

_なかだ(Wed Jul 06 08:41:25 JST 2005)

 それは/etc/profileが余計なことをするせい。

_なかだ(Wed Jul 06 12:27:48 JST 2005)

 ちなみに、export CHERE_INVOKING=yesしとけばcdしなくなる

_ささだ(Wed Jul 06 13:04:30 JST 2005)

 今の cygwin だとそうなんですねー。

_5(Tue)

また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 を書いていてはまること.

  • end を付けてしまう
  • return を忘れてしまう

インデントは意外と心地よい.

あー.

  • 引数名に括弧を強要される

のは駄目駄目だ.

perl はかいてて気分が悪くなってきた.


あと8時間.


結局,しょぼいグラフ.他言語処理系比較


結局14ページ.


今日は帰りたいなあ.


うあ,雨だ.


やっぱり書いたばかりの文章は客観的に読めない.寝かせる期間がホスィ.


ところで,論文とかを svn で管理するようにしてみた.どうかな.

ノートと学校と家で,情報の共有がやりやすくなった,となるといいんだが.


今眠って,起きたら明日だったら目もあてられないな....


12:05の電車に乗れば帰れる...のかな.どうだろ.


うぅ,無理っぽい orz

_t(Tue Jul 05 22:36:04 JST 2005)

 私も学生のころはcvsで論文を管理してました。

_4(Mon)

  • 8/3 東京 -> 佐賀,SWoPP 一日目 発表
  • 8/4 SWoPP 二日目
  • 8/5 SWoPP 三日目,佐賀 -> 博多
  • 8/6 博多見物,博多 -> 東京

という感じでいこう.誰か博多の人遊んでくれませんか.


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
  • dtc: direct threaded code
  • si: specialized instruction
  • ou: operands unification
  • iu: instructions unification
  • imc: inline method cache
  • sc: stack caching

3時間仮眠.


ぐらふ.ぐらふ


目が回る回る.ぐるぐるー.


ご飯を食べないと死んでしまう.


食べてきた.論文執筆中は外食を豪華にしてしまってよろしくない.

そして食べたら眠くなってきた.眠ったら死んでしまう.


ruby-core でやってる O(1) の unshift って,どうやるんだろう.途中をすっ飛ばしてるからよくわかってない.

_shiro(Mon Jul 04 12:23:53 JST 2005)

 たぶんスタックオーバフローがおきてる>ackermann関数 on Gauche。gosh -fcollect-stats で実行してみそ。

_ささだ(Mon Jul 04 13:00:40 JST 2005)

 stack overflow: 4916times.22920ms.殆どの実行時間がスタックのコピーですか.

_たむら@博多の人(Mon Jul 04 13:02:25 JST 2005)

日曜日があれば良かったのに。金曜日の夜は飲み行くとかで遊べますが、 土曜日はムリだなぁ。

ちなみに「博多の女(ひと)」というお菓子がありまする。 http://www.nikakudou.co.jp/hkt-nohito.html

_ささだ(Mon Jul 04 16:59:31 JST 2005)

 わーい.

_Jari Aarniala(Mon Jul 04 17:08:45 JST 2005)

 http://centrin.net.id/~marc/performance.html - what about running the benchmarks in Qu as well? Could be interesting :)

_ko1(Mon Jul 04 17:42:15 JST 2005)

 I have no enough time to measure with it :-(

_shiro(Thu Jul 07 10:50:37 JST 2005)

 悔しかったので改善しました http://www.shiro.dreamhost.com/scheme/wiliki/wiliki.cgi?Gauche%3aVM%a4%ce%ba%c7%c5%ac%b2%bd

_ささだ(Thu Jul 07 11:42:10 JST 2005)

 おおぉ.方針としては,(1) そもそも,最初からスタックを結構取っておく (2) ハンドラを高速化する (2') 環境の追い出しを速くする (3) スタック伸張時のアルゴリズム・データ構造を変える,とか色々ありそうですが,どんな対策をしたんでしょうか.

_3(Sun)

まぁ、なんだかんだいってもそんなもんだよね。


デニーズで缶詰。この時間でも人が沢山居るもんなんだなあ。


さて,PROは7/5締め切り.最後まで諦めないぞ.


で,SWoPP の航空券,探してみたけどむっちゃ高いなぁ.どうしよう.

宿は5000円ちょっとか.どうしよう.

_2(Sat)


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 しかないんだから、それで行けそうね。

  1. o から各 x までの距離を出す
    1. ここで、行けないのがあれば判明
  2. x から他の x までの距離を出す
  3. o から出発して各 x へ最短距離でいける経路を探す
    1. 全部通ったら終了 その最小コストを返す
    2. この辺の枝狩りは・・・どうやんだろ

うー、しらなかった。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

_1(Fri)

  • 融合操作(オペランド融合・命令融合)
    • -> ○ 各命令は速くなる
    • -> × 全体のコード量が増える -> × I-Cache に乗らないかも

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 のチェックをしているというのはあんまり関係ないような気もする。わかんないけど。

_Eric Hodel(Fri Jul 01 18:20:32 JST 2005)

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.

_ko1(Fri Jul 01 19:16:58 JST 2005)

 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.

_msakai(Fri Jul 01 23:12:29 JST 2005)

 http://www.logos.ic.i.u-tokyo.ac.jp/icpc/2005/contest/problems.html

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