2012-05-30 13 views
6

अनुकूलित करने के रूप में, मैं डैरेन विल्किन्सन द्वारा ब्लॉग पोस्ट Gibbs sampler in various languages (revisited) में उदाहरण प्रोग्राम को फिर से लिखता हूं।सरल सामान्य लिस्प gibbs नमूना प्रोग्राम

कोड नीचे दिखाई देता है। इस कोड को चारों ओर 53 सेकंड में मेरी (5 वर्षीय) मशीन पर चलता है,, SBCL 1.0.56 का उपयोग कर buildapp का उपयोग कर एक कोर छवि बनाने, और फिर

time ./gibbs > gibbs.dat 

साथ इसे चलाने के बाद से इस समय के लिए गणना की गई कैसा था पोस्ट में अन्य भाषाओं में, मैंने सोचा कि मैं कुछ तुलनात्मक करता हूं पोस्ट में सी कोड लगभग 25 सेकंड में चलता है। यदि संभव हो तो मैं लिस्प कोड को आजमाने और तेज़ करना चाहता हूं।

############################## 
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)) 

तो मैं साथ sh gibbs.sh बुला 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 

मैं 6 संकलक नोट जब SBCL 1.0.56, जो नीचे पुन: पेश साथ संकलन मिल के साथ निष्पादन योग्य 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 

अद्यतन 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 से अधिक है। एसबीसीएल उपयोगकर्ता मेलिंग सूची में स्टीफन द्वारा इसकी मदद की गई, (थ्रेड "Optimizing a simple Common Lisp Gibbs sampler program" धागे में दूसरा संदेश देखें, इस, एक्स घोषित करने से अधिक या शून्य के रूप में इस प्रकार होने के लिए द्वारा हल किया जा सकता है

(declare (type (double-float 0.0 *) x)) 

प्रासंगिक दस्तावेज के बारे में FLOAT types और Interval Designators

थी के लिए कॉमन लिस्प Hyperspec देखें लगता है कि थोड़ा सा कोड तेज है। यह अब 52 सेकंड से कम विश्वसनीय है, लेकिन फिर भी, लाभ का अधिक नहीं है। यह भी यदि यह क्षम्य नहीं है किसी कारण से, मुझे पता है क्यों चाहते हैं के बारे में

note: doing float to pointer coercion (cost 13) 

नोट छोड़ देता है। इसके अलावा, ध्यान दें कि नोट का क्या अर्थ है, चाहे वह दिलचस्प होगा। विशेष रूप से, pointer शब्द का अर्थ क्या है? क्या यह इस तथ्य से संबंधित है कि सी कार्यों को बुलाया जा रहा है? इसके अलावा, लागत 13 प्रतीत नहीं होता है। क्या मापा जा रहा है?

इसके अलावा, रेनर ने सुझाव दिया कि उपभोग को कम करना संभव हो सकता है, जो रनटाइम को कम कर सकता है। मुझे नहीं पता कि या तो उपभोग में कमी संभव है, या यह रनटाइम को कम करेगा, लेकिन मुझे राय और दृष्टिकोण में रुचि होगी। कुल मिलाकर, ऐसा लगता है कि इस फ़ंक्शन के प्रदर्शन को बेहतर बनाने के लिए बहुत कुछ नहीं किया जा सकता है। शायद यह बहुत छोटा और सरल है।

उत्तर

4

ध्यान दें कि आम लिस्प में THE विशेष ऑपरेटर है। यह आपको अभिव्यक्ति परिणामों के लिए प्रकार घोषित करने की अनुमति देता है। उदाहरण के लिए यदि आप संभव हो तो प्रकार को कम करने की अनुमति देते हैं।

उदाहरण के लिए (SQRT somefloat) का परिणाम क्या है? यह एक फ्लोट हो सकता है, लेकिन somefloat नकारात्मक होने पर यह एक जटिल संख्या हो सकती है। यदि आप जानते हैं कि कुछ फ्लोट हमेशा सकारात्मक होता है (और केवल तब), तो आप (the double-float (sqrt somefloat)) लिख सकते हैं। तब संकलक अधिक कुशल कोड उत्पन्न करने में सक्षम हो सकता है।

यह भी ध्यान दें कि आम लिस्प में OPTIMIZE घोषणाएं हैं। यदि आप सबसे तेज़ कोड चाहते हैं तो आपको यह सुनिश्चित करने की ज़रूरत है कि आप उन्हें तदनुसार सेट करें। संभवतः केवल व्यक्तिगत कार्यों के लिए। आम तौर पर यह बहुत आक्रामक होने के लिए विश्व स्तर पर अनुकूलन को बदलने से बेहतर है।

आम लिस्प में एक फ़ंक्शन DISASSEMBLE है जो आपको संकलित कोड को देखने देता है।

फिर मैक्रो TIME है। इससे प्राप्त दिलचस्प जानकारी में यह शामिल है कि यह कितना दिलासा करता है। डबल-फ्लोट अंकगणित के साथ शायद बड़ी मात्रा में विपक्ष है। मदद के लिए एसबीसीएल मेलिंग सूची पर पूछना उपयोगी होगा। हो सकता है कि कोई आपको बता सके कि उस विपक्ष से कैसे बचें।

+0

हाय, रेनर। टिप्पणी के लिए धन्यवाद, लेकिन मैं कुछ और विशिष्ट के लिए उम्मीद कर रहा था। मैं पहले से ही 'OPTIMIZE' का उपयोग कर रहा हूं। मैंने 'THE' का उपयोग करने का प्रयास किया, लेकिन यह नहीं देखा कि यह 'x' और' y' असाइनमेंट के आरएचएस को छोड़कर उपयोगी होगा, और उन मामलों में, मैं उम्मीद करता हूं कि संकलक यह समझ सकता है कि युगल से प्राप्त होने वाले सभी अभिव्यक्तियां स्वयं दोगुनी हैं। मैंने कोशिश की, लेकिन यह कोई ध्यान देने योग्य अंतर नहीं बनाता है। बेहतर विचारों की कमी के लिए, मैं कंपाइलर नोट्स से छुटकारा पाना चाहता हूं, लेकिन मुझे समझ में नहीं आता कि वे मुझे क्या कह रहे हैं। –

+0

मैं प्रोफाइलिंग का भी प्रयास कर सकता हूं, लेकिन मुझे यकीन नहीं है कि कोड के इतने छोटे टुकड़े के लिए यह कितना उपयोगी होगा। किसी विशेष घोषणा के बिना, मुझे 1 मिनट से थोड़ा अधिक समय मिल रहा था, और अब मुझे लगभग 52 सेकंड मिल रहे हैं, इसलिए घोषणाओं ने बहुत अंतर नहीं किया है। –

+0

आह, वर्ग रूट के बारे में अच्छा बिंदु। मैंने यह खो दिया। धन्यवाद। –

2

यह मेरे लिए काम करता है:

(sqrt (the (double-float 0d0) (+ (* 2d0 x) 2d0))) 
+1

जो एसकर्ट चेतावनी गायब हो जाता है, लेकिन क्या आप एक स्पष्टीकरण जोड़ सकते हैं, कृपया? धन्यवाद। –

संबंधित मुद्दे