Posted 2015-06-23 14:27:15 GMT

前回Common Lispと多方向分岐について書きましたが、最適化は処理系任せでした。

クロージャーの配列を使う

これをユーザーレベルでどうにかしよう、という例も昔からあって、前回紹介したSymbolicsの最適化についての議論でもJeffrey Mark Siskind氏が、配列にクロージャーを詰めれば良いじゃないか、というような発言があります。

このアイデアは割合に定番なものですが、残念ながら case の場合と比較してみると100倍位遅いことが多いです。

( i ) let random 10 rand macrolet ( i &body body ) ` funcall svref loop :for b :in body :collect ` lambda ( ) ,b ,b body vector ,@ ,i fcase loop :for x :from 0 :repeat 256 :collect ` progn * i rand 256 fcase i . #. defun 256way/vector (defun 256way/case (i) (let ((rand (random 10))) (case i . #.(loop :for x :from 0 :repeat 256 :collect `((,x) (progn (* i rand))))))) (let (tem) (dotimes (i 1000000 tem) (setq tem (256way/vector 255)))) Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz |------------------------------------------------------------|# (let (tem) (dotimes (i 1000000 tem) (setq tem (256way/vector 0)))) Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz |------------------------------------------------------------|# (let (tem) (dotimes (i 1000000 tem) (setq tem (256way/case 0)))) Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz |------------------------------------------------------------|# (let (tem) (dotimes (i 1000000 tem) (setq tem (256way/case 255)))) Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz |------------------------------------------------------------|#

何もしていない case で一番遅い場合より遅いので、速度という面では何もしない方が良いケースが多そうです。

諦めない

しかし、ここで一頑張りした例があり、 load-time-value でクロージャーの配列をロード時に固定しようというアイデアがあります。

アイデアとしては処理系が用意する分岐テーブルを自前で用意するのに近いです。

( i ) loop :for x :from 0 :repeat 256 :collect ` ( ,x ) progn random 10 * ,x 256 ncase i . #. defun 256way/ncase (let (tem) (dotimes (i 1000000 tem) (setq tem (256way/ncase 255)))) Intel(R) Xeon(R) CPU E3-1230 v3 @ 3.30GHz |------------------------------------------------------------|#

これだと結構速度が出ていて case の時より速い位ですが、実はコードが違っていることに気付いたでしょうか。

ncase は load-time-value を利用するためフォームの周りのローカル変数は取り込めず等価なコードは実現できないのです。惜しい。

まとめ

環境を捕捉できる ncase があれば解決かなと思いますが、可能なのでしょうか。自分は無理かなあと思っています。

何にしろ、多分、捕捉したら遅くなるのでしょう。

変数を捕捉する必要がないのならば、 load-time-value を使うのは有力なテクニックかなと思います。

■

