Let's start Scheme

2012-06-18

Sagittarius vs SBCL その2

さすがにワード単位での比較(というか、機能が違うものの比較)はおかしいだろうと思い、SBCL限定で動くbytevector->integerをまじめに実装してみた。以下がコード。
(defun u64vector->integer (bvec)
  (declare (optimize (safety 0) (speed 3) (debug 0)))
  (let* ((len (length bvec))
  (ans (sb-bignum:%allocate-bignum len)))
    (loop :for e :of-type (unsigned-byte 64) :across bvec
          :for i :of-type fixnum :from 0
          :do (sb-bignum:%bignum-set ans (- len i 1) e))
    ans))

(defvar u64 (make-array 25 :initial-contents
   (loop :for i :of-type fixnum :from 0 :to 24 :collect i)))
(time (dotimes (i 100000)
 (u64vector->integer u64)))

(defvar *sbcl-bignum-element-size* 8)

(defun bytevector->integer (bvec)
  (declare (optimize (safety 0) (speed 3) (debug 0)))
  (let* ((len (length bvec))
  (bignum-size (ceiling (/ len *sbcl-bignum-element-size*)))
  (ans (sb-bignum:%allocate-bignum bignum-size)))
    (loop :for i :of-type fixnum :from 0 :to bignum-size
   :do (let ((e 0)
      (pos (- len 1 (* i *sbcl-bignum-element-size*))))
  ;; FIXME the size must be calculated by element size
  (declare (type (unsigned-byte 64) e))
  (loop :for j :of-type fixnum :from 0 :to *sbcl-bignum-element-size*
        :do (unless (< (- pos j) 0)
       (setf e (+ e (ash (aref bvec (- pos j))
           (ash j 3))))))
  (sb-bignum:%bignum-set ans i e)))
    ans))

(defvar bv (make-array 100 :initial-contents
         (loop :for i :of-type fixnum :from 0 :to 99 :collect i)))
(time (dotimes (i 100000)
 (bytevector->integer bv)))
基本的にはSagittariusで実装しているやり方と一緒。(もっとうまいやり方があれば教えてください。)
オリジナルも動作がおかしかったので多少修正。(Bignumに入れる順番が逆だった)。
Sagittariusのベンチマークは以前と一緒。環境はUbuntu (Virtual BOX)。バージョンは忘れた。確認方法も忘れたorz
っで、結果:
~/build$ sbcl --script bv-int.lisp
Evaluation took:
  0.023 seconds of real time
  0.024001 seconds of total run time (0.024001 user, 0.000000 system)
  104.35% CPU
  76,849,374 processor cycles
  10,399,624 bytes consed
  
Evaluation took:
  0.595 seconds of real time
  0.596037 seconds of total run time (0.596037 user, 0.000000 system)
  [ Run times consist of 0.004 seconds GC time, and 0.593 seconds non-GC time. ]
  100.17% CPU
  1,935,858,048 processor cycles
  304,000,848 bytes consed
  
~/build$ sash bv-int.scm 

;;  0.034603 real    0.032002 user    0.000000 sys
あ、確かにSBCLのbytevector->integerの方が10倍遅い。多分、ashがまずいんじゃないかな、と勝手に推測。bvecがfixnumのベクタだと宣言できて、ashの結果がbignumにならないことが宣言できればもう少し速くなる気がするけど、そこまでは面倒なのでやらない。
同じ機能がSBCLより速かったという事実だけで十分です。

タイトルが「vc」になっていたので修正。

No comments:

Post a Comment