昨晩の件
fold-right とか left とかの件。
定義が以下。
(define (fold-rignt op init seq) (if (null? seq) init (op (car seq) (fold-right op init (cdr seq))))) (define (fold-left op init seq) (define (iter result rest) (if (null? rest) result (iter (op result (car rest)) (cdr rest)))) (iter init seq))
大量のデータを吸わせて簡単な演算させてみたら処理時間に大きな差があったとの事。試してみます。
gosh> (use srfi-1) #<undef> gosh> (use gauche.time) #<undef> gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 0.750 ; user 0.690 ; sys 0.020 499999500000 gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 6.851 ; user 0.950 ; sys 0.100 499999500000 gosh>
確かに全然違うな。disasm してみた。
gosh> (disasm (lambda () (if (null? seq) init (op (car seq) (fold-right op init (cdr seq)))))) main_code (name=#f, code=0x47ec00, size=24, const=8, stack=14): args: #f 0 GREF #<identifier user#seq>; seq 2 BNNULL 7 ; (null? seq) 4 GREF #<identifier user#init>; init 6 RET 7 GREF #<identifier user#seq>; seq 9 CAR-PUSH ; (car seq) 10 PRE-CALL(3) 21 12 GREF-PUSH #<identifier user#op>; op 14 GREF-PUSH #<identifier user#init>; init 16 GREF #<identifier user#seq>; seq 18 CDR-PUSH ; (cdr seq) 19 GREF-CALL(3) #<identifier user#fold-right>; (fold-right op init (cdr seq)) 21 PUSH-GREF-TAIL-CALL(2) #<identifier user#op>; (op (car seq) (fold-right op init (cdr s ... 23 RET #<undef> gosh> (disasm (lambda () (if (null? rest) result (iter (op result (car rest)) (cdr rest))))) main_code (name=#f, code=0x47eae0, size=22, const=7, stack=12): args: #f 0 GREF #<identifier user#rest>; rest 2 BNNULL 7 ; (null? rest) 4 GREF #<identifier user#result>; result 6 RET 7 PRE-CALL(2) 16 9 GREF-PUSH #<identifier user#result>; result 11 GREF #<identifier user#rest>; rest 13 CAR-PUSH ; (car rest) 14 GREF-CALL(2) #<identifier user#op>; (op result (car rest)) 16 PUSH-GREF #<identifier user#rest>; rest 18 CDR-PUSH ; (cdr rest) 19 GREF-TAIL-CALL(2) #<identifier user#iter>; (iter (op result (car rest)) (cdr rest)) 21 RET #<undef> gosh>
むむむ。これって現実トウヒの範疇を越えてるなぁ。データが大量になると再起で処理時間消費しちゃう、って理解で良いのかどうなのか。
上記がビンゴかどうかは上記のインストラクションの中身を確認してみないと何とも言えないかも。
インストラクション見ても
ボトルネックは不明。むむむ、と言いつつ色々ヤッてみたら実行するタイミングで計測された時間にばらつきがある模様。同じ値で連続して実行してみた。
gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 8.684 ; user 0.630 ; sys 0.090 499999500000 gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 8.426 ; user 0.460 ; sys 0.070 499999500000 gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 10.823 ; user 3.350 ; sys 0.090 499999500000 gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 0.446 ; user 0.430 ; sys 0.000 499999500000 gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 0.651 ; user 0.600 ; sys 0.010 499999500000 gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 0.452 ; user 0.430 ; sys 0.000 499999500000 gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 0.635 ; user 0.610 ; sys 0.010 499999500000 gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 0.473 ; user 0.430 ; sys 0.000 499999500000 gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 6.320 ; user 5.870 ; sys 0.050 499999500000 gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 0.449 ; user 0.430 ; sys 0.010 499999500000 gosh> (time (fold-right + 0 (iota 1000000))) ;(time (fold-right + 0 (iota 1000000))) ; real 0.631 ; user 0.600 ; sys 0.000 499999500000 gosh> (time (fold-left + 0 (iota 1000000))) ;(time (fold-left + 0 (iota 1000000))) ; real 0.449 ; user 0.440 ; sys 0.010 499999500000 gosh>
- fold-right
- 1 回目
- ; real 8.684
- ; user 0.630
- ; sys 0.090
- 2 回目
- ; real 10.823
- ; user 3.350
- ; sys 0.090
- 3 回目
- ; real 0.651
- ; user 0.600
- ; sys 0.010
- 4 回目
- ; real 0.635
- ; user 0.610
- ; sys 0.010
- 5 回目
- ; real 6.320
- ; user 5.870
- ; sys 0.050
- 6 回目
- ; real 0.631
- ; user 0.600
- ; sys 0.000
- 1 回目
- fold-left
- 1 回目
- ; real 8.426
- ; user 0.460
- ; sys 0.070
- 2 回目
- ; real 0.446
- ; user 0.430
- ; sys 0.000
- 3 回目
- ; real 0.452
- ; user 0.430
- ; sys 0.000
- 4 回目
- ; real 0.473
- ; user 0.430
- ; sys 0.000
- 5 回目
- ; real 0.449
- ; user 0.430
- ; sys 0.010
- 6 回目
- ; real 0.449
- ; user 0.440
- ; sys 0.010
- 1 回目
がつん、って沢山時間がかかるケイス以外の時間見てみると若干繰り返しの方が早い程度でさほどの差異は無いように見えます。
しかしこの振れは一体何が原因なのでしょうか。OSX が微妙とか?
ペースト位置
間違えていた件。(とほほ