2010-04-10 6 views
7

पर हाल ही में धागे जोड़ना मैं अपने जावा समवर्ती पाठ्यक्रम के लिए एक ट्यूटोरियल पर काम कर रहा हूं। समानांतर में प्राइम संख्याओं की गणना करने के लिए थ्रेड पूल का उपयोग करना है।जावा थ्रेड पूल

डिज़ाइन इरेटोस्टेनेस की चलनी पर आधारित है। इसमें एन बूल की एक सरणी है, जहां एन सबसे बड़ा पूर्णांक है जिसे आप जांच रहे हैं, और सरणी में प्रत्येक तत्व एक पूर्णांक का प्रतिनिधित्व करता है। सच है, झूठा गैर प्रधान है, और सरणी शुरू में सभी सच है।

एक थ्रेड पूल का उपयोग निश्चित संख्या में धागे के साथ किया जाता है (हमें पूल में धागे की संख्या के साथ प्रयोग करना चाहिए और प्रदर्शन का निरीक्षण करना चाहिए)।

एक थ्रेड को प्रक्रिया के लिए एक पूर्णांक एकाधिक दिया जाता है। तब थ्रेड को उस सरणी में पहला सच्चा तत्व मिलता है जो थ्रेड के पूर्णांक का एक बहु नहीं है। धागा तब थ्रेड पूल पर एक नया धागा बनाता है जिसे पाया गया नंबर दिया जाता है।

एक नया धागा बनने के बाद, मौजूदा धागा सरणी में इसके पूर्णांक के सभी गुणों को झूठी में सेट करना जारी रखता है।

मुख्य प्रोग्राम धागा पूर्णांक '2' के साथ पहला धागा शुरू करता है, और उसके बाद सभी तैयार धागे को समाप्त करने की प्रतीक्षा करता है। यह तब प्रमुख संख्याओं और गणना करने के लिए लिया गया समय निकाल देता है।

मेरे पास यह मुद्दा है कि थ्रेड पूल में जितने अधिक धागे हैं, धीमे यह 1 धागा सबसे तेज़ होता है। यह तेजी से धीमा नहीं होना चाहिए!

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

मैं जानना चाहता हूं कि क्या गलत हो रहा है, और यदि जावा थ्रेड पूल का उपयोग बार-बार किया जा सकता है।

+3

थ्रेड दृष्टिकोण के साथ चलते रहें, यह एक सीखने का अनुभव है और जब आप पूरा कर लेंगे तो आप धागे के बारे में बहुत कुछ समझेंगे। Eratosthenes की चाकू के बारे में कौन परवाह करता है? कई पेशेवर प्रोग्रामर इस पृष्ठ पर ज्ञान को कभी नहीं समझते हैं। बस याद रखें कि अगर किसी महिला के पास 9 महीने में बच्चा हो सकता है तो इसका मतलब यह नहीं है कि नौ इसे एक महीने कर सकता है !!! –

उत्तर

5

आपका समाधान धीमी चला सकते हैं के रूप में धागे निम्नलिखित समस्याओं में से कुछ के लिए जोड़ रहे हैं:

  • धागा निर्माण ओवरहेड्स: एक धागा बनाने महंगा है।

  • प्रोसेसर विवाद: अगर प्रोसेसर को निष्पादित करने के लिए वहां अधिक धागे हैं, तो कुछ थ्रेड को नि: शुल्क प्रोसेसर की प्रतीक्षा कर दिया जाएगा। नतीजा यह है कि प्रत्येक धागे के लिए औसत प्रसंस्करण दर गिर जाती है। इसके अलावा, ओएस तो धागे टाइम-स्लाइस की जरूरत है, और उस समय जो अन्यथा "असली" काम के लिए इस्तेमाल किया जाएगा दूर ले जाता है।

  • वर्चुअल मेमोरी विवाद: प्रत्येक थ्रेड अपने ढेर के लिए स्मृति की जरूरत है। अपने मशीन काम का बोझ के लिए पर्याप्त भौतिक स्मृति नहीं है, तो, प्रत्येक नए धागा ढेर आभासी स्मृति विवाद जो पेजिंग जो नीचे

  • कैश विवाद बातें धीमा कर देती है में परिणाम बढ़ जाती है: प्रत्येक थ्रेड (शायद) की एक अलग अनुभाग स्कैनिंग हो जाएगा सरणी, जिसके परिणामस्वरूप स्मृति कैश याद आती है। यह मेमोरी एक्सेस धीमा कर देता है।

  • लॉक विवाद: यदि आपके धागे सभी साझा किए गए सरणी को पढ़ रहे हैं और अपडेट कर रहे हैं और synchronized और सरणी तक पहुंच को नियंत्रित करने के लिए एक लॉक ऑब्जेक्ट का उपयोग कर रहे हैं, तो आप लॉक विवाद से पीड़ित हो सकते हैं। एक भी ताला वस्तु प्रयोग किया जाता है, तो प्रत्येक धागा ताला प्राप्त करने के लिए इंतजार कर रहे अपने समय के सबसे खर्च करेगा। शुद्ध परिणाम है कि गणना प्रभावी रूप से धारावाहिक है, और कुल मिलाकर प्रसंस्करण दर एक एकल प्रोसेसर/धागे की दर के लिए चला जाता है है।

पहले चार समस्याओं बहु सूत्रण के लिए निहित हैं, और वहाँ भी कई धागे बनाने नहीं और जो कि आप पहले से ही बनाया है पुन: उपयोग से कोई वास्तविक समाधान कर रहे हैं ... अलग। हालांकि, लॉक विवाद समस्या पर हमला करने के कई तरीके हैं। उदाहरण के लिए,

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

अंत में, धागे की पुनरावर्ती निर्माण शायद एक गलती है, क्योंकि यह यह मुश्किल धागा पुनः प्रयोग और एंटी-लॉक-विवाद उपायों को लागू करने कर देगा है।

+0

संक्षेप में, आपको वास्तव में परीक्षण करना होगा कि धागे जोड़ना प्रदर्शन में सुधार करता है, मान लें कि जटिलता जोड़ने से बेहतर समाधान होता है क्योंकि अक्सर ऐसा नहीं होता है। –

+0

@ पीटर - मैं कहूंगा कि अभ्यास का बिंदु यह है कि जब आप प्रोसेसर जोड़ते हैं तो ऐप के प्रदर्शन को स्केल करने के लिए आपको थ्रेड * सही तरीके से * उपयोग करना होगा। –

+0

मुझे वास्तव में लगता है कि इस पोस्ट तक एक वोट देने के लिए पर्याप्त नहीं है, मल्टीथ्रेडिंग के संभावित दोषों के लिए इतना अच्छा सारांश है। – posdef

3

आपके सिस्टम पर कितने प्रोसेसर उपलब्ध हैं? यदि # थ्रेड> # प्रोसेसर, अधिक थ्रेड जोड़ना इस तरह की गणना -बद्ध कार्य के लिए चीजों को धीमा करने जा रहा है।

कोई फर्क नहीं पड़ता कि आप कितने धागे शुरू करते हैं, वे अभी भी एक ही सीपीयू साझा कर रहे हैं। जितना अधिक समय सीपीयू थ्रेड के बीच स्विचिंग खर्च करता है, उतना ही कम समय यह वास्तविक काम कर सकता है।

यह भी ध्यान रखें कि एक धागा शुरू करने की लागत एक प्राइम की जांच की लागत की तुलना में महत्वपूर्ण है - संभवतः आप 1 धागे को आग लगने के समय सैकड़ों या हजारों गुणा कर सकते हैं।

+0

मेरे वर्तमान कंप्यूटर में दो कोर हैं, लेकिन मूल रूप से कोड को कोर कोर i7 पर 4 कोर (8 आभासी) के साथ परीक्षण किया गया था और इसमें समान समस्याएं थीं। यानी 1 धागा = 1 एस। 4 धागे = 20 एस। – ljbade

0

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

आपके द्वारा डिज़ाइन की गई समस्या थ्रेड पूल द्वारा हल करने के लिए एक अच्छा नहीं है, क्योंकि आपको क्रम में चलाने के लिए धागे की आवश्यकता है। अगर मैं यहाँ गलत हूं तो मुझे सही करो।

धागा # 1: 3 खोजने के लिए झूठी

धागा # 3 3 के एकाधिक सेट: करने के लिए झूठी

धागा # 2 2 के एकाधिक सेट को खोजने के 5, झूठी

धागा करने के लिए 5 के एकाधिक सेट # 4: 7 मिल जाए, झूठी

....

ये धागे क्रम में चलाने के लिए की जरूरत है और वे interleaving रहे हैं (कैसे क्रम कार्यक्रम टी करने के लिए 7 के एकाधिक सेट हेम) मायने रखता है।

उदाहरण के लिए, यदि पहले धागा # 1 सेट चल धागा # 3 शुरू होता है "4" गलत पर, यह "4" खोजने के लिए और 4 के गुणकों पुनर्स्थापित करने के लिए जारी रहेगा। इस अतिरिक्त काम का एक बहुत कुछ कर समाप्त होता है, हालांकि अंतिम परिणाम सही हो जाएगा।

+0

थ्रेड 5 कभी "ढूंढ नहीं पाएगा" 4 - इसका एकमात्र उद्देश्य 5 के सभी गुणकों को हटाना है। एक बार सभी कार्यकर्ता धागे गैर-प्राइम को हटाने के बाद, मुख्य धागे शेष संख्याओं को "ढूंढ" पाएंगे। – danben

+0

यदि थ्रेड # 3 को समाप्त होने से पहले शुरू होने वाले थ्रेडों की प्रतीक्षा करने की आवश्यकता है, तो हमें एकाधिक धागे की आवश्यकता नहीं है। समस्या यह है कि थ्रेड # 3 को * 2 * गुणों के सभी * को हटाने के लिए थ्रेड # 1 का इंतजार करने की आवश्यकता नहीं है, लेकिन इसे खोजने से पहले "पर्याप्त" 2 गुणकों को हटाने के लिए थ्रेड # 1 का इंतजार करना होगा। – evergreen

0

अग्रिम में एक निश्चित ThreadPoolExecutor बनाने के लिए अपने प्रोग्राम को पुन: स्थापित करें। सुनिश्चित करें कि आप ThreadPoolExecutor # prestartAllCoreThreads() को कॉल करते हैं। अपनी मुख्य विधि पूर्णांक 2 के लिए एक कार्य सबमिट करें। प्रत्येक कार्य एक और कार्य सबमिट करेगा। चूंकि आप थ्रेड पूल का उपयोग कर रहे हैं, इसलिए आप धागे का एक समूह नहीं बनायेंगे और समाप्त नहीं करेंगे, बल्कि इसके बजाय एक ही धागे को नए कार्यों पर ले जाने की इजाजत देनी होगी। यह कुल निष्पादन ओवरहेड पर कम हो जाएगा।

आपको पता होना चाहिए कि इस मामले में थ्रेड की इष्टतम संख्या मशीन पर प्रोसेसर (पी) की संख्या के बराबर है। अक्सर यह मामला है कि अधिकतम संख्या में धागे पी + 1 है। ऐसा इसलिए है क्योंकि P + 1 संदर्भ स्विचिंग से ओवरहेड को कम करता है जबकि निष्क्रिय/अवरुद्ध समय से हानि को कम करता है।