[Message Prev][Message Next][Thread Prev][Thread Next][Message Index][Thread Index]

[MD:870]CCL coding system on Meadow.



In article <un28tykfr.fsf@xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx>,
  Miyashita Hisashi(宮下 尚:HIMI) <himi@xxxxxxxxxxxxxxxxxxxxxxxxx> writes:

> > ExCCLはまだ使ってないけど、(あれはもうちょっとmucs-cclを改良しないと
> > 使いにくい;_;) こんなサボったもの作ってみました。どうでしょうか
> > 
> > とりあえず、decoderだけ。
> > 
> > でも、まだまだ最適化できる。

> いくつかミスってました。

結局, 次のようにすると動きました。

(define-ccl-program ew-ccl-decode-b-2
  `(1
    (loop
     (read r1 r2 r3 r4)
     (r0 = r1 ,ccl-b64-array)
     (r0 = (r0 << 6))
     (r1 = r2 ,ccl-b64-array)
     (r0 = ((r1 | r0) << 6))
     (r1 = r3 ,ccl-b64-array)
     (r0 = ((r1 | r0) << 6))
     (r1 = r4 ,ccl-b64-array)
     (r0 = (r1 | r0))
     (write (r0 >> 16))
     (if (r3 == ?=)
 	 ((end))
       ((write ((r0 >> 8) & ?\xff))
 	(if (r4 == ?=)
 	    ((end))
	  ((r1 = (r0 & ?\xff))
	   (write-repeat r1))))))))

;; なんか >8 の挙動が今一つよくわからない。

が、しかし、ew-ccl-decode-b より遅いです。
SS/5 上の Emacs 20.2 で次のコードを試したのですが、ew-ccl-decode-b が
31秒ほどで済むのに対し、ew-ccl-decode-b-2 は 35秒ほどかかります。

(let ((i 100000) (status (make-vector 9 nil)) a b)
  (setq a (current-time))
  (while (< 0 i)
    (setq i (1- i))
    (ccl-execute-on-string
     ew-ccl-decode-b ; or ew-ccl-decode-b-2 or -3
     status
     "AB8gISIjJCUmJygpKissLS4vMDk6Ozw9Pj9AQVpbXF1eX2Bhent8fX5/gP8="))
  (setq b (current-time))
  (elp-elapsed-time a b))

で、ew-ccl-decode-b-2 をもとにして次のように最適化を行なうと、30秒ほど
で済むようになりました。

(eval-when-compile
(defun ew-ccl-decode-b-bit-ex (v)
  (logior
   (lsh (logand v (lsh 255 16)) -16)
   (logand v (lsh 255 8))
   (lsh (logand v 255) 16)))
)

(define-ccl-program ew-ccl-decode-b-3
  `(1
    (loop
     (read r0 r1 r2 r3)
     (r0 = r0 ,(vconcat
		(mapcar
		 (lambda (v)
		   (cond
		    ((eq v t) 0)
		    (v (ew-ccl-decode-b-bit-ex (lsh v 18)))
		    (t 0)))
		 ew-ccl-256-to-64-table)))
     (r1 = r1 ,(vconcat
		(mapcar
		 (lambda (v)
		   (cond
		    ((eq v t) 0)
		    (v (ew-ccl-decode-b-bit-ex (lsh v 12)))
		    (t 0)))
		 ew-ccl-256-to-64-table)))
     (r0 |= r1)
     (r1 = r2 ,(vconcat
		(mapcar
		 (lambda (v)
		   (cond
		    ((eq v t) 0)
		    (v (ew-ccl-decode-b-bit-ex (lsh v 6)))
		    (t 0)))
		 ew-ccl-256-to-64-table)))
     (r0 |= r1)
     (r1 = r3 ,(vconcat
		(mapcar
		 (lambda (v)
		   (cond
		    ((eq v t) 0)
		    (v (ew-ccl-decode-b-bit-ex v))
		    (t 0)))
		 ew-ccl-256-to-64-table)))
     (r0 |= r1)
     (r0 >8= 0)
     (write r7)
     (if (r2 != ?=)
	 ((r0 >8= 0)
	  (write r7)
	  (if (r3 != ?=)
	      (write-repeat r0))))
     (end))))

;; さらなる高速化案:
;; (1) r0 の 25bit 目を利用して = を読んでいないということを 1回の比較
;;  で確認する。
;; (2) loop unrolling して一度に 7byte づつ読む。

まぁ、ew-ccl-decode-b は partial evaluation した結果のようなものなんで、
そう簡単には勝てないってことなんでしょうか。
ew-ccl-decode-b-3 で勝てたのも ew-ccl-decode-b には変な文字を無視する
ための loop/repeat/break が入っているからかも知れません。

;; そうそう、ew-ccl-decode-b-3 を書いていて気づいたんですが、変な文字
;; がきた時に 26bit 目を立てるようにテーブルを作れば 4バイト読むたびに
;; 1回のテストで変な文字の読み飛ばしが実現できますね。
-- 
[田中 哲][たなか あきら][Tanaka Akira]