2012-06-01 10 views
5

यह चारों ओर ले जाता है 1 सेकंडस्कैला समांतर संग्रह कभी-कभी आउटऑफमेमरी एरर क्यों करते हैं?

(1 to 1000000).map(_+3) 

इस java.lang.OutOfMemoryError देता है जबकि: जावा ढेर अंतरिक्ष

(1 to 1000000).par.map(_+3) 

संपादित करें:

मैं मानक स्केला 2.9.2 है विन्यास। मैं इसे स्कैला प्रॉम्प्ट पर टाइप कर रहा हूं। और बैश में मैं देख सकता हूं [-एन "$ JAVA_OPTS"] || JAVA_OPTS = "- Xmx256M -Xms32M"

और मेरे पास मेरे env में JAVA_OPTS सेट नहीं है।

1 लाख पूर्णांकों = 8MB, बनाने सूची में दो बार = 16MB

+0

क्या आप यहां थोड़ा और विवरण जोड़ सकते हैं? आप अपने जेवीएम, किसी अन्य स्विच को कितनी मेमोरी शुरू करते हैं? क्या आप इसे आरपीएल में चलाते हैं या आप इसे संकलित करते हैं? यदि आप इसे आरईपीएल से चलाते हैं तो आपने पहले कितने निर्देश निष्पादित किए हैं? मैंने बस अपने आरईपीएल में कोशिश की और मैंने इसे ओओएम के बिना 10 बार निष्पादित किया। – drexin

+0

मेरे REPEL में बस ठीक काम करता है। – Jan

+0

@ जेन मेरे लिए यह आरईपीएल में भी ठीक काम करता है, लेकिन केवल पहली बार ... – Christian

उत्तर

9

यह निश्चित रूप से JVM स्मृति विकल्प और स्मृति एक समानांतर संग्रह शेयर करने के लिए आवश्यक करने के लिए से संबंधित लगता है। उदाहरण के लिए:

scala> (1 to 1000000).par.map(_+3) 

, एक OutOfMemoryError तीसरी बार यह मूल्यांकन करने के लिए करने की कोशिश की के साथ समाप्त होता है, जबकि

scala> (1 to 1000000).par.map(_+3).seq 

कभी नहीं में विफल रहा है। मुद्दा गणना नहीं है कि यह पैरारलल संग्रह का भंडारण है।

3

असफलता के लिए कई कारण हैं:

  1. समानांतर संग्रह विशेष नहीं हैं, इसलिए वस्तुओं बॉक्सिंग हो। इसका मतलब है कि आप स्मृति उपयोग प्राप्त करने के लिए 8 के साथ तत्वों की संख्या गुणा नहीं कर सकते हैं।
  2. map का उपयोग करना मतलब है कि सीमा को वेक्टर में परिवर्तित कर दिया गया है। समानांतर वैक्टरों के लिए एक कुशल समावेशन अभी तक लागू नहीं किया गया है, इसलिए विभिन्न प्रोसेसर द्वारा उत्पादित इंटरमीडिएट वैक्टर विलय करके कमाई की जाती है - अधिक मेमोरी की आवश्यकता होती है। इसे भावी रिलीज में संबोधित किया जाएगा।
  3. आरईपीएल पिछले परिणामों को स्टोर करता है - प्रत्येक पंक्ति में मूल्यांकन ऑब्जेक्ट स्मृति में रहता है।
+0

क्या उन्हें किसी दिन विशेष बनाना संभव है? –

+0

एक बार सरणी विशेषज्ञता लागू हो जाने के बाद, कुछ संग्रह प्रकारों को विशेषीकृत किया जाना चाहिए, हां। – axel22

2

यहां दो मुद्दे हैं, समानांतर संग्रह को संग्रहीत करने के लिए आवश्यक स्मृति की मात्रा और समानांतर संग्रह को पार करने के लिए आवश्यक स्मृति की मात्रा।

अंतर इन दो पंक्तियों के बीच देखा जा सकता है:

(1 to 1000000).map(_+3).toList 
(1 to 1000000).par.map(_+3).toList 

आरईपीएल भंडार का मूल्यांकन भाव, याद है। मेरे आरईपीएल पर, मैं स्मृति से बाहर होने से पहले इन दोनों 7 बार निष्पादित कर सकता हूं। समांतर निष्पादन के माध्यम से गुजरने से अस्थायी रूप से अतिरिक्त मेमोरी का उपयोग होता है, लेकिन एक बार टोलिस्ट निष्पादित हो जाने पर, अतिरिक्त उपयोग कचरा एकत्र होता है।

(1 to 100000).par.map(_+3) 

, जो एक सामान्य वेक्टर की तुलना में अधिक स्थान में समा जाता है (इस मामले में एक ParVector में) एक ParSeq [इंट] वापस आती है।इससे पहले कि मैं स्मृति से बाहर चलाने के

(1 to 100000).map(_+3) 

11 बार: यह एक मैं, इससे पहले कि मैं स्मृति से बाहर चलाने के लिए 4 बार निष्पादित कर सकते हैं, जबकि मैं इस पर अमल कर सकते हैं। तो समानांतर संग्रह, यदि आप उन्हें चारों ओर रखते हैं तो अधिक जगह ले लेंगे।

एक कामकाज के रूप में, आप उन्हें वापस करने से पहले List जैसे सरल संग्रह में बदल सकते हैं।

क्यों इतना स्थान समानांतर संग्रह द्वारा लिया जाता है के लिए और के रूप में क्यों यह संदर्भ रखता है बहुत सी बातें, मैं नहीं जानता कि करने के लिए है, लेकिन मुझे लगता है views [*], और अगर आपको लगता है कि यह एक समस्या है, raise an issue for it है।

[*] बिना किसी वास्तविक सबूत के।

0

मैं एक ही था, लेकिन एक ThreadPool का उपयोग कर मेरे लिए समस्या से छुटकारा पाने के लिए लगता है: बड़े संग्रह के लिए

val threadPool = Executors.newFixedThreadPool(4) 
    val quadsMinPar = quadsMin.par 
    quadsMinPar.tasksupport = new ThreadPoolTaskSupport(threadPool.asInstanceOf[ThreadPoolExecutor]) 

ForkJoin भी कई धागे बनाने जा सकता है।

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