ひょっとしてCPS変換しなくてもA正規化すればいいのでは?
という誘惑にかられたことから、ちょっとベンチマークとってみた。
(どっちが速度が出るか比較したかった。速い方がいいじゃん!)
使用したコードは以下
(define tarai-org (lambda (x y z) (if (<= x y) y (tarai-org (tarai-org (- x 1) y z) (tarai-org (- y 1) z x) (tarai-org (- z 1) x y))))) (time (tarai-org 10 5 0)) (define (<=/cps x y k) (k (<= x y))) (define (-/cps x y k) (k (- x y))) (define tarai-cps (lambda (x y z k) (<=/cps x y (lambda (b) (if b y (-/cps x 1 (lambda (x2) (tarai-cps x2 y z (lambda (t1) (-/cps y 1 (lambda (y2) (tarai-cps y2 z x (lambda (t2) (-/cps z 1 (lambda (z2) (tarai-cps z2 x y (lambda (t3) (k (tarai-cps t1 t2 t3))))))))))))))))))) (time (tarai-cps 10 5 0 (lambda (x) x))) (define tarai-anf (lambda (x y z) (let ((G139 (<= x y))) (if G139 y (let ((G140 (- x 1))) (let ((G141 (tarai-anf G140 y z))) (let ((G142 (- y 1))) (let ((G143 (tarai-anf G142 z x))) (let ((G144 (- z 1))) (let ((G145 (tarai-anf G144 x y))) (tarai-anf G141 G143 G145))))))))))) (time (tarai-anf 10 5 0)) (define tarai-lambda (lambda (x y z) ((lambda (G143) (if G143 y ((lambda (G144) ((lambda (G145) ((lambda (G146) ((lambda (G147) ((lambda (G148) ((lambda (G149) (tarai-lambda G145 G147 G149)) (tarai-lambda G148 x y))) (- z 1))) (tarai-lambda G146 z x))) (- y 1))) (tarai-lambda G144 y z))) (- x 1)))) (<= x y)))) (time (tarai-lambda 10 5 0))tarai-orgが元のたらいまわし関数。以下、-cps、-anf、-lambdaと続くが、順に元の関数のお手製CPS変換、A正規化、A正規化後letをlambdaに変換したものとなっている。 っで、以下がベンチマーク結果
Petite Chez Scheme 7.9.4 (time (tarai-org 10 ...)) no collections 16 ms elapsed cpu time 0 ms elapsed real time 0 bytes allocated (time (tarai-cps 10 ...)) no collections 0 ms elapsed cpu time 0 ms elapsed real time 840 bytes allocated (time (tarai-anf 10 ...)) 7 collections 78 ms elapsed cpu time, including 0 ms collecting 0 ms elapsed real time, including 0 ms collecting 29505472 bytes allocated, including 29469704 bytes reclaimed (time (tarai-lambda 10 ...)) 7 collections 78 ms elapsed cpu time, including 0 ms collecting 0 ms elapsed real time, including 0 ms collecting 29505120 bytes allocated, including 29489216 bytes reclaimed Gauche 0.9 ;(time (tarai-org 10 5 0)) ; real 0.016 ; user 0.016 ; sys 0.000 ;(time (tarai-cps 10 5 0 (lambda (x) x))) ; real 0.000 ; user 0.000 ; sys 0.000 ;(time (tarai-anf 10 5 0)) ; real 0.031 ; user 0.031 ; sys 0.000 ;(time (tarai-lambda 10 5 0)) ; real 0.437 ; user 0.359 ; sys 0.078個人的には超意外にもCPSが一番早かった!!
Gaucheのdisasm関数でコンパイル結果を見てみたが、末尾最適化が効いてるのかな?
Chez Schemeの結果からアロケーションが結構発生するみたいだけど、それを踏まえてもありと思わせる結果である。
でも、これってこれらのVMがCPS変換されたコードを速く走らせるのであって、CPS変換されたコードが無条件で速くなるわけではないんだよなぁ・・・
う~ん・・・
No comments:
Post a Comment