연습을 위해 Darren Wilkinson이 블로그 게시물 Gibbs sampler in various languages (revisited)에 예제 프로그램을 작성했습니다.간단한 Common Lisp gibbs sampler 프로그램을 최적화하는 방법
아래 코드가 나타납니다. 이 코드는, SBCL 1.0.56을 사용 buildapp를 사용하여 코어 이미지를 생성하고이 타이밍이 계산 된 방법 이었기 때문에
time ./gibbs > gibbs.dat
으로 실행, 주변 53초 내 (5 세) 컴퓨터에서 실행 게시물의 다른 언어들, 나는 비슷한 것을 할 것이라고 생각했다. 게시물의 C 코드는 약 25 초 만에 실행된다. 가능하다면 Lisp 코드의 속도를 높이고 싶습니다.
##############################
gibbs.lisp
##############################
(eval-when (:compile-toplevel :load-toplevel :execute)
(require :cl-rmath) (setf *read-default-float-format* 'double-float))
(defun gibbs (N thin)
(declare (fixnum N thin))
(declare (optimize (speed 3) (safety 1)))
(let ((x 0.0) (y 0.0))
(declare (double-float x y))
(print "Iter x y")
(dotimes (i N)
(dotimes (j thin)
(declare (fixnum i j))
(setf x (cl-rmath::rgamma 3.0 (/ 1.0 (+ (* y y) 4))))
(setf y (cl-rmath::rnorm (/ 1.0 (+ x 1.0)) (/ 1.0 (sqrt (+ (* 2 x) 2))))))
(format t "~a ~a ~a~%" i x y))))
(defun main (argv)
(declare (ignore argv))
(gibbs 50000 1000))
은 그럼 아래에 재현 SBCL 1.0.56로 컴파일 할 때 나는 6 개 컴파일러 메모를 얻을
gibbs.sh
##################
gibbs.sh
##################
buildapp --output gibbs --asdf-tree /usr/share/common-lisp/source/ --asdf-tree /usr/local/share/common-lisp/source/ --load-system cl-rmath --load gibbs.lisp --entry main
로와
sh gibbs.sh
를 호출하여 실행
gibbs
을 만들었습니다. 나는 그들에 대해 무엇을해야할지 모르지만, 어떤 힌트에도 감사 할 것입니다.
; compiling file "/home/faheem/lisp/gibbs.lisp" (written 30 MAY 2012 02:00:55 PM):
; file: /home/faheem/lisp/gibbs.lisp
; in: DEFUN GIBBS
; (SQRT (+ (* 2 X) 2))
;
; note: unable to
; optimize
; due to type uncertainty:
; The result is a (VALUES (OR (DOUBLE-FLOAT 0.0) (COMPLEX DOUBLE-FLOAT))
; &OPTIONAL), not a (VALUES FLOAT &REST T).
; (/ 1.0d0 (SQRT (+ (* 2 X) 2)))
;
; note: unable to
; optimize
; due to type uncertainty:
; The second argument is a (OR (DOUBLE-FLOAT 0.0)
; (COMPLEX DOUBLE-FLOAT)), not a (COMPLEX
; DOUBLE-FLOAT).
;
; note: forced to do static-fun Two-arg-/ (cost 53)
; unable to do inline float arithmetic (cost 12) because:
; The second argument is a (OR (DOUBLE-FLOAT 0.0) (COMPLEX DOUBLE-FLOAT)), not a DOUBLE-FLOAT.
; The result is a (VALUES (OR (COMPLEX DOUBLE-FLOAT) (DOUBLE-FLOAT 0.0))
; &OPTIONAL), not a (VALUES DOUBLE-FLOAT &REST T).
; (CL-RMATH:RGAMMA 3.0d0 (/ 1.0d0 (+ (* Y Y) 4)))
;
; note: doing float to pointer coercion (cost 13)
; (SQRT (+ (* 2 X) 2))
;
; note: doing float to pointer coercion (cost 13)
; (CL-RMATH:RNORM (/ 1.0d0 (+ X 1.0d0)) (/ 1.0d0 (SQRT (+ (* 2 X) 2))))
;
; note: doing float to pointer coercion (cost 13)
;
; compilation unit finished
; printed 6 notes
; /home/faheem/lisp/gibbs.fasl written
; compilation finished in 0:00:00.073
UPDATE 1 : Rainer Joswig's answer SQRT의 인수가 즉
The result is a (VALUES (OR (DOUBLE-FLOAT 0.0) (COMPLEX DOUBLE-FLOAT))
; &OPTIONAL), not a (VALUES FLOAT &REST T).
컴파일러가 불평했다, 내가보고 된 알려지지 않은 컴파일러 노트의 원천이었다 , 음수가 될 수 있음을 지적 인수의 값이 양수인지 여부를 알지 못했기 때문에 결과는 복소수가 될 수 있습니다. 이 예에서 값 x
은 감마 분포의 샘플 변량이므로 은 항상 0보다 큽니다. Stephan은 SBCL 사용자 메일 링리스트 에서 유용하게 지적했습니다 (스레드 "Optimizing a simple Common Lisp Gibbs sampler program"의 두 번째 메시지 참조). 이것은
(declare (type (double-float 0.0 *) x))
관련 문서에 대한 FLOAT types 및 Interval Designators.
티의 커먼 리스프 HyperSpec을 참조로 다음과보다 제로 클 X를 선언함으로써 해결 될 수있다 코드의 속도가 빨라지는 것 같습니다. 이제는 안정적으로 52 초 미만이지만 그래도 이득은별로 없습니다. 이것은 어떤 이유로, 나는 이유를 알고 싶습니다 고칠 수없는 경우 이것은 또한
note: doing float to pointer coercion (cost 13)
대한 메모를 남긴다. 또한 노트가 의미하는 바에 대한 설명은 상관없이 흥미로울 것입니다. 특히 여기에 단어 pointer
은 무엇을 의미합니까? 이것은 C 함수가 호출된다는 사실과 관련이 있습니까? 또한 비용 13은 처럼 보이지 않습니다. 무엇이 측정되고 있습니까?
또한 라이너 (Rainer)는 consing을 줄이는 것이 가능하여 런타임을 단축시킬 수 있다고 제안했습니다. consuction reduction이 가능한지 또는 런타임이 단축되는지 여부는 알지 못합니다. 하지만 의견이나 접근 방식에 관심이 있습니다. 전반적으로이 기능의 성능을 향상시키는 것은 그리 많지 않습니다. 어쩌면 너무 작고 간단합니다.
안녕, 라이너를. 의견을 주셔서 감사합니다,하지만 나는 더 구체적인 것을 기대하고있었습니다. 이미'최적화 '를 사용하고 있습니다.'THE'를 사용해 보았지만'x'와'y' 할당의 RHS를 제외하고는 어디에서 유용할지 보지 못했습니다. 컴파일러는 복식에서 파생 된 모든 표현이 스스로 복식임을 추론 할 수 있습니다. 나는 그것을 시도했지만, 눈에 띄는 차이는 없다. 더 나은 아이디어가 없다면 컴파일러 노트를 없애고 싶습니다. 그러나 나는 그들이 무엇을 말하고 있는지 이해하지 못합니다. –
프로파일 링을 시도해 볼 수도 있지만 코드의 작은 부분에 얼마나 유용할지 모르겠습니다. 특별한 선언이 없으면 1 분이 조금 넘게되었는데 지금은 약 52 초 정도 걸리므로 선언문에 많은 차이가 없습니다. –
아, 제곱근에 대한 좋은 점. 나는 그것을 놓쳤다. 감사. –