2015-01-23 13 views
7

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

हास्केल:

import Data.Array.Repa 
len = 1024*1024*64 
arr = fromFunction (Z :. len) (const 1) :: Array D DIM1 Float 
main = sumAllP arr >>= print 

जावास्क्रिप्ट:

var len = 1024*1024*64 
var arr = []; 
var sum = 0; 
for (var i=0; i<len; ++i) 
    arr[i] = 1; 
for (var i=0; i<len; ++i) 
    sum += arr[i]; 
console.log(sum); 

और एक कच्चे बेंचमार्क:

apple1$ ghcjs -O2 bench_fill.hs -funfolding-use-threshold10000 -funfolding-keeness-factor1000 -o bench_fill.js; time node bench_fill.js/all.js 
Linking bench_fill.js (Main) 
6.7108864e7 

real 0m1.543s 
user 0m1.512s 
sys 0m0.033s 

apple1$ time node benchfill.js 
67108864 

real 0m1.764s 
user 0m1.173s 
sys 0m0.583s 

कैसे GHCJS के लिए लूप एक स्लिम, स्वच्छ देशी की तुलना में तेजी से चला सकते हैं? जेनरेट किए गए कोड के संपर्क में आने वाले बॉक्सिंग की मात्रा पर विचार करना संभव नहीं होना चाहिए।

+1

क्या आप सुनिश्चित हैं कि हास्केल कंपाइलर केवल अंतिम परिणाम मुद्रित करने के लिए कोड को अनुकूलित नहीं करता है? किसी भी मामले में हमें शायद यह पता लगाने के लिए जेनरेट किया गया कोड देखना होगा कि यह तेज़ क्यों है। – JJJ

+9

कृपया ghcjs से आउटपुट .js प्रदान करें। इस सवाल का जवाब कैसे दिया जाए। –

+1

[यह] (https://gist.github.com/viclib/3023b1c44daf7f33ede4) आउटपुट जेएस है। [यह] (https://gist.github.com/viclib/9108f02fb1655cdc0787) इसके अलावा, यह सुनिश्चित करने के लिए कि यह भर गया था, राशि को प्रिंट करने के बाद पूरे सरणी को प्रिंट करता है। – MaiaVictor

उत्तर

4

Array D DIM1 Floatdelayed array है। यह सिर्फ const 1 और सरणी की सीमा के रूप में दर्शाया गया है। कहीं भी संग्रहीत 64 मिलियन फ्लोट की कोई सरणी नहीं है।

जावास्क्रिप्ट प्रोग्राम वास्तव में 64 मिलियन युगल की एक सरणी बनाता है, जो 512 एमबी मेमोरी का उपयोग करता है। ऐसी बड़ी सरणी को पढ़ने और लिखने की लागत गैर-नगण्य है (जैसा कि इसे आवंटित करने की लागत है; पर्याप्त सिस्टम समय पर ध्यान दें)।

+1

आह, मैं देखता हूं - मेरी गलती मान ली गई थी कि 'sumAllP' पहले सरणी की गणना की गई थी। 'ComputeP' को कॉल करना धीमा कर देता है - यद्यपि अभी भी एक छोटे (4x) मार्जिन द्वारा। लेकिन अब मुझे कुछ और अप्रत्याशित मिला: लंबाई को दोगुनी करने से जावास्क्रिप्ट प्रोग्राम मेमोरी से बाहर हो जाता है, जबकि हास्केल प्रोग्राम (कंप्यूटपी का उपयोग करके) जावास्क्रिप्ट में संकलित नहीं होता है। मुझे यकीन है कि computeP वास्तव में सरणी को कंप्यूटिंग कर रहा है क्योंकि यह प्रिंट करता है, इसलिए ... यह मेरे लिए एक रहस्य के रूप में छोड़ा गया है। – MaiaVictor

+1

यह कोई फर्क नहीं पड़ता कि सरणी का मूल्यांकन कब किया जाता है। 'arr' भौतिक रूप से एक सरणी के रूप में संग्रहीत नहीं है इस पर ध्यान दिए बिना कि आप इसका कितना मूल्यांकन करते हैं या कितना कम मूल्यांकन करते हैं। –

+1

यदि आप एक भौतिक सरणी चाहते हैं, तो आप अन्य यू 'जैसे' यू '('डी' के बजाय) का उपयोग कर सकते हैं। –

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