8

मैं जावा में समवर्ती प्रोग्रामिंग सीख रहा हूं, और गेम ऑफ लाइफ के लिए सिमुलेशन लिख रहा हूं।कॉनवे के जीवन के खेल के लिए मल्टीथ्रेडेड जावा प्रोग्राम - सीमा कोशिकाओं पर विवाद

यहाँ मैं क्या सोच रहा हूँ है:

  • उपयोग पूर्णांक [] [] कोशिकाओं के राज्यों की दुकान
  • विभाजन पूर्णांक टी खंडों में [] [] और टी कार्यकर्ता धागे का उपयोग करने के
  • टी थ्रेड अपने सेगमेंट से पढ़े जाएंगे, अपने सेगमेंट में सभी सेल्स के लिए नए मानों की गणना करेंगे और कोशिकाओं को अपडेट करेंगे।
  • एक बार जब वे गणना समाप्त कर लेते हैं तो वे अन्य श्रमिकों के लिए
  • समाप्त करने के लिए बाधा को प्रतीक्षा करते हैं जब बाधा पार हो जाता है मुख्य थ्रेड यूआई अपडेट करेगा।
  • श्रमिक अगले राज्य की गणना करने के लिए आगे बढ़ते हैं।

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

मेरे विकल्प क्या हैं?

  • रननेबल के बजाय कॉल करने योग्य का उपयोग करें और कार्यकर्ता धागे नए मान को वापस करें (सेगमेंट को अपडेट करने के बजाय)। बाधा पार होने के बाद मुख्य धागा मैट्रिक्स को अपडेट कर सकता है। इस विकल्प में मैट्रिक्स में वर्कर थ्रेड द्वारा दिए गए परिणामों की प्रतिलिपि बनाना शामिल है।
  • दो बाधाओं का उपयोग करें। मजदूर धागे सीमावर्ती कोशिकाओं की एक प्रति अपने पड़ोसियों के सेगमेंट बनाते हैं और पहले बाधा पर इंतजार करते हैं। एक बार यह बाधा पारित हो जाने के बाद, वे अगले राज्यों की गणना करने और स्थान पर सेगमेंट अपडेट करने के लिए आगे बढ़ते हैं। फिर वे दूसरी बाधा पर इंतजार करते हैं। मुख्य धागा यूआई अद्यतन करता है।

मेरे सवाल है, वहाँ सीमा कोशिकाओं पर विवाद है कि कॉपी करने डेटा को शामिल नहीं करता या कि उपरोक्त दो विकल्प और अधिक कुशल है से निपटने के लिए किसी भी अन्य तरीका है? रीडरवाइटर लॉक, अस्थिर चर या अन्य सिंक्रनाइज़िंग तंत्र का उपयोग कर सकते हैं?

अद्यतन: अब तक double buffering solution by Peter सबसे साफ है। लेकिन मेरे पास एक प्रश्न है। चूंकि दो सरणी साझा डेटा हैं और हम किसी सिंक्रनाइज़ेशन (सिंक्रनाइज़ एक्सेस या अस्थिर चर) का उपयोग नहीं कर रहे हैं, क्या यह दृश्यता समस्या नहीं बनाएगा? क्या कई सीपीयू सरणी मानों को कैश कर सकते हैं और प्रत्येक पुनरावृत्ति के साथ सरणी का केवल एक हिस्सा अपडेट कर सकते हैं? फिर थ्रेड को सीमा कोशिकाओं के लिए पुरानी मान मिल जाएगी। क्या यह संभव है? यदि नहीं, क्यों। यदि हां, तो मैं इसे कैसे हल करूं? ऐसा लगता है declaring two arrays volatile will not make their individual elements volatile

+0

कुछ विचार करने के लिए नियमित int –

+0

लाभ के बजाय AtomicInt का उपयोग कर रहा है? क्या वह अधिक सिंक्रनाइज़ेशन नहीं होगा? – Helen

+0

आपको int का उपयोग करने की आवश्यकता क्यों है, क्या यह बूलियन का उपयोग करके स्टोर करने के लिए अधिक तार्किक और कुशल नहीं होगा? – Pool

उत्तर

1

यह आपके वास्तविक प्रश्न का उत्तर नहीं देता है, लेकिन मेरी सिफारिश आपका पहला विकल्प होगा ... कार्यकर्ता धागे उन्हें अद्यतन करने के बजाय नए मान लौटाएंगे। मैं इसे एक कदम आगे ले जाऊंगा और "एग्रीगेटर" को कार्यकर्ता धागे से परिणामों को एक नए बोर्ड स्टेट एरे में जोड़ दूंगा और फिर पहले को छोड़ दें। मेरा तर्क यह है कि यह तर्क की समग्र पठनीयता में सुधार करेगा, क्योंकि इसके बारे में चिंता करने की कोई "वैश्विक बातचीत" नहीं होगी।

कहा जा रहा है कि, मैं थोड़ी पक्षपातपूर्ण हूं क्योंकि मैं एक कार्यात्मक तरीके से प्रोग्राम करना पसंद करता हूं, सिवाय इसके कि जब कोई मजबूत कारण न हो।

+0

+1 बोनस के रूप में: कोई विवाद नहीं! :- –

1

मैं निम्नलिखित दृष्टिकोण की कोशिश करेंगे:

  • कार्यकर्ताओं परिकलन है, लेकिन केवल भीतरी कोशिकाओं को मान वापस लिखें।
  • सीमा कोशिकाओं के लिए, परिणामों को संग्रहित करें।
  • जब गणना पूर्ण हो जाती है, तो बाधा पर प्रतीक्षा करें।
  • जब सभी कर्मचारी पहले बाधा पर हैं, तब रिलीज़ करें और प्रत्येक को सीमा कक्ष लिखने दें। एक दूसरे बाधा पर
  • होने तक प्रतीक्षा यूआई अद्यतन

भंडारण एक n x m टाइल के लिए आवश्यक 2 * (n + m - 1) है, इसलिए आम तौर पर बड़े टाइल (8x8 या अधिक) कैश की गई मूल्यों के लिए आनुपातिक रूप से कम स्मृति की आवश्यकता है।

5

मेरा सुझाव है कि 2 int [] [] arrays। आइए उन्हें ए और बी को कॉल करें। सभी अजीब संख्या वाले "टिक" के मूल्यों को पकड़ेंगे और बी भी संख्याबद्ध टिकों को पकड़ेंगे।

ए प्रारंभिक स्थिति जैसा दिखता है उसे आरंभ करें। फिर अपने धागे को प्रत्येक सेल की अगली स्थिति की गणना करने के लिए ढीला कर दें, और परिणामों को बी में संबंधित सेल में रखें। एक बार आपके सभी धागे किए जाने के बाद, आपके पास बी में आपका नया राज्य है, अब अगले राज्य की गणना करने के लिए बी का उपयोग करें प्रत्येक सेल का, और परिणामों को ए में संग्रहीत करें। किसी भी समय, एक सरणी केवल पढ़ी जाएगी, और दूसरा केवल लिखेंगे, इसलिए कोई भी विवाद नहीं होगा।

लाभ:

  • डेटा की कोई नकल अब तुम क्या की तुलना में। प्रति सेल केवल एक ही लेखन हो रहा है।
  • किनारे/कोने के मामलों के बारे में चिंता करने की ज़रूरत नहीं है, क्योंकि एल्गोरिदम सरल है।
  • स्मृति की कोई आवंटित आवंटन नहीं। जब आप शुरू करते हैं तो बस दो सरणी आवंटित करें।

नुकसान:

  • आप दो बार के रूप में ज्यादा स्मृति को आबंटित करने की जरूरत है।
+1

डबल बफरिंग –

+0

के लिए +1 यह अच्छा लगता है। लेकिन मेरे पास साझा डेटा की दृश्यता के बारे में एक सवाल है। अद्यतन देखें। – Helen

0

मैं बस java.util.concurrent.Exchanger<V> पर ठोकर खाई। यह विनिमय के बिंदु के रूप में कार्य करता है। मैं संभवतः आसन्न धागे के बीच सेल-स्टेटस की सूचियों का आदान-प्रदान करने के लिए इसका उपयोग कर सकता हूं। यह बाधा से बेहतर होगा क्योंकि मुझे केवल आसन्न श्रमिकों के बीच सिंक्रनाइज़ करने की आवश्यकता है।

0

डबल बफरिंग के साथ कैशिंग समस्या के बारे में आपके अपडेट का उत्तर देने के लिए, यह कोई समस्या नहीं है। सीपीयू के पास सुसंगत कैश होता है, और वे जानते हैं कि किसी अन्य सीपीयू कैश में डेटा बदल दिया गया है।

+0

ठीक है। लेकिन जावा मेमोरी मॉडल के कारण दृश्यता अभी भी एक मुद्दा है।चूंकि अपडेट में लिंक दिखाता है, सरणी संदर्भों को अस्थिर और संदर्भों को ओवरराइट करने की घोषणा करना उस पर ध्यान रखेगा। यद्यपि इसका भी अर्थ है, सीपीयू मूल्यों को कैश नहीं कर सकते हैं (या अस्थिर संदर्भों को संशोधित करने के बाद फेंक दें)। – Helen

+0

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

+0

दरअसल, एक अस्थिर सरणी संदर्भ से बाहर काम करने से आप प्रत्येक सीपीयू रजिस्टर में रखने के बजाय मेमोरी एड्रेस को मेमोरी एड्रेस से देख सकते हैं। शायद प्रत्येक पुनरावृत्ति की शुरुआत में आप अस्थिर संदर्भों को अस्थायी गैर-अस्थिर संदर्भों में प्रतिलिपि बना सकते हैं, क्योंकि आप किसी भी तरह के पुनरावृत्ति के दौरान उन्हें नहीं बदलेंगे। –

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

  • कोई संबंधित समस्या नहीं^_^