Gauche > Archives > 2009/10/10

2009/10/10 05:17:48 UTCyosaka
#
簡単なプログラムでベンチマークを取ってみたのですが、Gaucheではローカル手続きで末尾再帰にするのが一番効率的なんですか?
2009/10/10 05:34:53 UTCshiro
#
@yosaka 何と比較したかによりますが、ローカル手続きの末尾再帰だと大抵はループにコンパイルされるので速くなることが多いでしょうね。
#
グローバル手続きへの末尾再帰だと、一応その手続きの呼び出しインストラクションが入ります。ループ中にそのグローバル手続きが再定義される可能性があるので。
2009/10/10 05:57:31 UTCyosaka
#
今回ベンチマークを取ったのは、1..1000000までのリストで10000以下をリストにして返すというプログラムです。fold,fold-right,filter,take,named let,internal definede比較してみて、internal defineが一番速かったので
#
もしかしたら、ローカル手続きの末尾再帰が一番効率的なのかなと思い質問しました。
2009/10/10 06:04:19 UTCshiro
#
ああなるほど。そのくらいだと手続き呼び出しの時間が支配的になると思うので、全く手続き呼び出しが発生しないinternal defineが速くなりそうですね。named letも構文糖衣なだけでinternal defineと同じにならないかな? disasmしてみると手続き呼び出しがどうなってるかわかると思います。
2009/10/10 06:09:01 UTCyosaka
#
ベンチマーク結果は
#
;(time (fold-right (lambda (x y) (cond ((> 10000 x) (cons x y)) (else y) ...
; real   0.662
; user   0.610
; sys    0.050
;(time (fold (lambda (x y) (cond ((> 10000 x) (cons x y)) (else y))) '() ...
; real   0.219
; user   0.200
; sys    0.020
;(time (filter (lambda (x) (> 10000 x)) (iota 1000000)))
; real   0.222
; user   0.220
; sys    0.000
;(time (take (iota 1000000) 10000))
; real   0.143
; user   0.140
; sys    0.000
;(time (let loop ((init '()) (lis (iota 1000000 1))) (cond ((null? lis)  ...
; real   0.102
; user   0.110
; sys    0.000
;(time (loop (iota 1000000 1)))
; real   0.100
; user   0.100
; sys    0.000
#
です。
#
ほとんどnamed letとinternal defineはほとんど同じですね。
#
shiroさん、質問に答えて頂きありがとうございました。
2009/10/10 09:38:59 UTC(び)
#
久しぶりに実家に行って、20kg超の姪っ子を肩車して2km先の公園まで歩いた
#
トレーニング再開の一歩にはヘヴィすぎ