में फास्ट कॉम्प्लेक्स अंक अंकगणितीय क्लोजर में कुछ बुनियादी जटिल संख्या अंकगणितीय लागू कर रहा था, और ध्यान दिया कि यह लगभग संकेतों के साथ लगभग बराबर समकक्ष जावा कोड की तुलना में लगभग 10 गुना धीमा था।क्लोजर
की तुलना करें:
(defn plus [[^double x1 ^double y1] [^double x2 ^double y2]]
[(+ x1 x2) (+ y1 y2)])
(defn times [[^double x1 ^double y1] [^double x2 ^double y2]]
[(- (* x1 x2) (* y1 y2)) (+ (* x1 y2) (* y1 x2))])
(time (dorun (repeatedly 100000 #(plus [1 0] [0 1]))))
(time (dorun (repeatedly 100000 #(times [1 0] [0 1]))))
उत्पादन:
साथ"Elapsed time: 69.429796 msecs"
"Elapsed time: 72.232479 msecs"
:
public static void main(String[] args) {
double[] z1 = new double[] { 1, 0 };
double[] z2 = new double[] { 0, 1 };
double[] z3 = null;
long l_StartTimeMillis = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
z3 = plus(z1, z2); // assign result to dummy var to stop compiler from optimising the loop away
}
long l_EndTimeMillis = System.currentTimeMillis();
long l_TimeTakenMillis = l_EndTimeMillis - l_StartTimeMillis;
System.out.format("Time taken: %d millis\n", l_TimeTakenMillis);
l_StartTimeMillis = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
z3 = times(z1, z2);
}
l_EndTimeMillis = System.currentTimeMillis();
l_TimeTakenMillis = l_EndTimeMillis - l_StartTimeMillis;
System.out.format("Time taken: %d millis\n", l_TimeTakenMillis);
doNothing(z3);
}
private static void doNothing(double[] z) {
}
public static double[] plus (double[] z1, double[] z2) {
return new double[] { z1[0] + z2[0], z1[1] + z2[1] };
}
public static double[] times (double[] z1, double[] z2) {
return new double[] { z1[0]*z2[0] - z1[1]*z2[1], z1[0]*z2[1] + z1[1]*z2[0] };
}
उत्पादन:
Time taken: 6 millis
Time taken: 6 millis
वास्तव में, प्रकार संकेत एक फर्क नहीं पड़ता प्रतीत होता है: यदि मैं उन्हें हटा देता हूं तो मुझे लगभग एक ही परिणाम मिलता है।
"Elapsed time: 137.337782 msecs"
"Elapsed time: 214.213993 msecs"
तो मेरी सवाल कर रहे हैं: कैसे मैं जावा कोड के प्रदर्शन के करीब प्राप्त कर सकते हैं क्या वास्तव में अजीब बात है कि अगर मैं एक आरईपीएल बिना Clojure स्क्रिप्ट चलाने के लिए, मैं धीमी परिणाम प्राप्त है? और आरईपीएल के बिना क्लोजर चलाने के दौरान पृथ्वी पर क्यों अभिव्यक्ति का मूल्यांकन करने में अधिक समय लगता है?
अद्यतन ==============
बढ़िया है, deftype
में टाइप संकेत के साथ और defn
रों में deftype
उपयोग कर, और dotimes
बजाय repeatedly
का उपयोग कर के रूप में के रूप में अच्छा प्रदर्शन देता है या जावा संस्करण से बेहतर है। आप दोनों को धन्यवाद।
(deftype complex [^double real ^double imag])
(defn plus [^complex z1 ^complex z2]
(let [x1 (double (.real z1))
y1 (double (.imag z1))
x2 (double (.real z2))
y2 (double (.imag z2))]
(complex. (+ x1 x2) (+ y1 y2))))
(defn times [^complex z1 ^complex z2]
(let [x1 (double (.real z1))
y1 (double (.imag z1))
x2 (double (.real z2))
y2 (double (.imag z2))]
(complex. (- (* x1 x2) (* y1 y2)) (+ (* x1 y2) (* y1 x2)))))
(println "Warm up")
(time (dorun (repeatedly 100000 #(plus (complex. 1 0) (complex. 0 1)))))
(time (dorun (repeatedly 100000 #(times (complex. 1 0) (complex. 0 1)))))
(time (dorun (repeatedly 100000 #(plus (complex. 1 0) (complex. 0 1)))))
(time (dorun (repeatedly 100000 #(times (complex. 1 0) (complex. 0 1)))))
(time (dorun (repeatedly 100000 #(plus (complex. 1 0) (complex. 0 1)))))
(time (dorun (repeatedly 100000 #(times (complex. 1 0) (complex. 0 1)))))
(println "Try with dorun")
(time (dorun (repeatedly 100000 #(plus (complex. 1 0) (complex. 0 1)))))
(time (dorun (repeatedly 100000 #(times (complex. 1 0) (complex. 0 1)))))
(println "Try with dotimes")
(time (dotimes [_ 100000]
(plus (complex. 1 0) (complex. 0 1))))
(time (dotimes [_ 100000]
(times (complex. 1 0) (complex. 0 1))))
आउटपुट:
Warm up
"Elapsed time: 92.805664 msecs"
"Elapsed time: 164.929421 msecs"
"Elapsed time: 23.799012 msecs"
"Elapsed time: 32.841624 msecs"
"Elapsed time: 20.886101 msecs"
"Elapsed time: 18.872783 msecs"
Try with dorun
"Elapsed time: 19.238403 msecs"
"Elapsed time: 17.856938 msecs"
Try with dotimes
"Elapsed time: 5.165658 msecs"
"Elapsed time: 5.209027 msecs"
आप स्थापित करने की कोशिश की है [ '* चेतावनी दी-ऑन-प्रतिबिंब *'] (http://clojuredocs.org/clojure_core /clojure.core/*warn-on-reflection*) यह देखने के लिए कि क्या कोई प्रतिबिंब छेड़छाड़ कर रहा है? – DaoWen
@ दाओवेन: नहीं, मैंने कभी भी उस सेटिंग का उपयोग नहीं किया है। मैंने अभी भी स्क्रिप्ट को '(सेट! * चेतावनी-पर-प्रतिबिंब * सत्य) के साथ फिर से चलाया है, और इसके अलावा स्टडआउट पर कोई चेतावनी मुद्रित नहीं है, इसका मतलब है कि कोई प्रतिबिंब उपयोग नहीं किया जा रहा है, है ना? बस यह सुनिश्चित करना चाहते हैं कि मैं इसे सही तरीके से उपयोग कर रहा हूं। – OpenSauce