प्रोग्रामिंग में थ्रेड्स का उचित उपयोग क्या है?


13

मैं यह सुनकर थक गया हूं कि लोग सलाह देते हैं कि आपको प्रति प्रोसेसर केवल एक धागा का उपयोग करना चाहिए, जबकि कई कार्यक्रम प्रति प्रक्रिया 100 का उपयोग करते हैं! उदाहरण के लिए कुछ सामान्य कार्यक्रमों को लें

vb.net ide uses about 25 thread when not debugging
System uses about 100
chrome uses about 19
Avira uses more than about 50

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


7
यह सिफारिश व्यापक है। एक थ्रेड प्रति प्रोसेसर की सीमा केवल कम्प्यूटेशनल रूप से बाध्य अनुप्रयोगों के लिए उपयुक्त है। अधिकांश प्रोग्राम IO- बाउंड होते हैं, चाहे वह नेटवर्क ट्रैफ़िक हो, डिस्क एक्सेस हो, या RAM भी हो। यही कारण है कि वेब सर्वर, डेटाबेस आदि में प्रोसेसर कोर की तुलना में कई अधिक थ्रेड्स के साथ थ्रेड पूल होते हैं।
किलन फथ

2
"मुझे लगभग हर बार याद दिलाया जाता है कि मुझे प्रति प्रोसेसर एक थ्रेड का अधिक उपयोग नहीं करना चाहिए"? क्या आप लिंक या उदाहरण पोस्ट कर सकते हैं? लगभग हर बार?
S.Lott

2
"... लोग सलाह देते हैं कि आपको प्रति प्रक्रिया केवल एक थ्रेड का उपयोग करना चाहिए।" ये लोग कौन हैं? डार्क एज के बाद से शेड्यूलिंग काफी उन्नत हो गई है।
हेन हेनरिक्स

2
आपके पास प्रति प्रक्रिया एक से अधिक UI थ्रेड नहीं होना चाहिए ।
SLAKs

3
@ बिली ओनली, आपके संपादन ने प्रश्न को व्यर्थ कर दिया
SK-

जवाबों:


22

आपको प्रति प्रोसेसर केवल एक थ्रेड का उपयोग करना चाहिए,

संभवतः HPC में जहां आप अधिकतम efifciency चाहते हैं - लेकिन अन्यथा आज मैंने जो मूर्खतापूर्ण बात सुनी है!

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

एक वेब सर्वर के लिए प्रत्येक आने वाले कनेक्शन के लिए एक धागा फायर करना उचित हो सकता है (हालांकि बहुत भारी लोड वाले सर्वर के लिए बेहतर तरीके हैं)।

एक विचारधारा के लिए यह चल रहा है प्रत्येक उपकरण अनुचित नहीं है। मुझे लगता है कि .Net IDE के लिए रिपोर्ट किए गए थ्रेड्स में से कई लॉगिंग जैसी चीजें हैं और I / O कार्यों को अपने स्वयं के थ्रेड्स में शुरू किया जा रहा है ताकि वे अनब्लॉक जारी रख सकें।


9
अब आप मुझे सोच रहे हैं कि आपने जो मूर्खतापूर्ण बात सुनी है वह क्या है!
माइकल के

3
@ मिचेल - मैंने अंडरग्राउंड पढ़ाया है और रक्षा अनुबंधों पर काम किया है - आपने मेरे द्वारा सुनी गई बेवकूफी भरी बातों पर विश्वास नहीं किया होगा!
मार्टिन बेकेट

1
क्या हमने उन्हें TheDailyWTF.com पर देखा है?
FrustratedWithFormsDesigner

मैं वास्तव में उन्हें अब नहीं ढूँढ सकता, लेकिन इस लिंक को देखो social.msdn.microsoft.com/Forums/en-US/vbgeneral/thread/…
स्मिथ

2
है ज्यादा से ज्यादा आवेदन करने के लिए आवंटित प्रोसेसर प्रति एक सीपीयू बाध्य धागा। IO- बाउंड थ्रेड्स एक बड़ी समस्या नहीं हैं (उनके द्वारा उपयोग की जाने वाली मेमोरी के अलावा) और यह याद रखना महत्वपूर्ण है कि ऐप्स को सिस्टम के CPU के केवल सबसेट का उपयोग करने के लिए प्रतिबंधित किया जा सकता है; सब के बाद, यह (आमतौर पर) उपयोगकर्ता / व्यवस्थापक का कंप्यूटर है न कि प्रोग्रामर का।
डोनाल्ड फेलो

2

समानांतर निष्पादन के माध्यम से उद्देश्य की गति होने पर एक-धागा-प्रति-कोर सलाह लागू होती है।

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


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

2

आप प्रत्येक अभिकलन के लिए एक सूत्र चाहते हैं, जो अन्य संगणनाओं की तुलना में भिन्न दरों पर आगे बढ़ सकता है।

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

I / O बाध्य गणना के लिए, आप आम तौर पर प्रत्येक स्वतंत्र I / O "चैनल" के लिए एक धागा चाहते हैं क्योंकि वे विभिन्न दरों पर संवाद करते हैं, और चैनल पर अवरुद्ध धागे तब प्रगति करने के लिए अन्य थ्रेड्स को रोकते नहीं हैं।


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

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

1

धागे के लिए अंगूठे का नियम है, आप कंप्यूटर पर उपलब्ध प्रत्येक "निष्पादन इकाई" के लिए कम से कम एक "सक्रिय" (तुरंत सीपीयू समय दिए गए अपने आदेशों को निष्पादित करने में सक्षम) चाहते हैं। एक "निष्पादन इकाई" एक तार्किक अनुदेश प्रोसेसर है, इसलिए एक क्वाड-चिप, क्वाड-कोर एक्सॉन हाइपरथ्रेडेड सर्वर में 32 ईयू (4 चिप्स, 4 कोर प्रति चिप, प्रत्येक हाइपरथ्रेडेड) होगा। आपका औसत कोर i7 8 होगा।

ईयू के प्रति एक धागा सीपीयू की शक्ति का पूर्ण उपयोग है, बशर्ते कि धागे हमेशा चालू स्थिति में रहेंगे; यह लगभग कभी भी ऐसा नहीं होता है, क्योंकि थ्रेड्स को गैर-कैश्ड मेमोरी, हार्ड डिस्क, नेटवर्क पोर्ट आदि तक पहुंच की आवश्यकता होती है, जिसका उन्हें इंतजार करना चाहिए, और प्रदर्शन के लिए सक्रिय सीपीयू ध्यान की आवश्यकता नहीं है। इस प्रकार आप आगे बढ़ सकते हैं और अधिक धागे के साथ समग्र दक्षता बढ़ जाती है और जाने के लिए बढ़ते हैं। यह एक लागत पर आता है; जब एक सीपीयू एक थ्रेड को स्विच करता है, तो उसे थ्रेड के रजिस्टरों, निष्पादन पॉइंटर और अन्य राज्य की जानकारी को सामान्य रूप से यूरोपीय संघ के अंतरतम कामकाज में रखा जाना चाहिए और बहुत जल्दी एक्सेस किया जाना चाहिए, जिससे अन्य ईयूपी उस सीपीयू चिप में इसे उठा सकें। यह भी तय करने के लिए ओएस में थ्रेड्स की आवश्यकता होती है कि किस थ्रेड को स्विच किया जाना चाहिए। अंत में, जब यूरोपीय संघ ने थ्रेड स्विच किया, यह पाइपलाइनिंग के प्रदर्शन लाभ को खो देता है जो अधिकांश प्रोसेसर आर्किटेक्चर उपयोग करते हैं; थ्रेड्स स्विच करने से पहले पाइपलाइन को फ्लश करना होगा। लेकिन, चूंकि यह सब अभी भी औसत से कम समय लेता है, बस हार्ड ड्राइव या यहां तक ​​कि रैम की जानकारी के साथ वापस आने की प्रतीक्षा में, यह लागत के लायक है।

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

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


यदि एन थ्रेड्स की संख्या और यू इकाइयों की संख्या है, तो ओपी ने "एन = यू" नियम पर सवाल उठाया। आप इसे "U <= N <= 2 U" नियम में ढील दे रहे हैं। मैं थोड़ा और आगे जाऊंगा और कहूंगा कि "N <= c U" के लिए "यथोचित रूप से छोटा" स्थिरांक (प्रोग्रामर को ज्ञात) c स्वीकार्य है (यदि मानदंड उचित प्रदर्शन दिखाते हैं)। मुझे बहुत चिंता होगी यदि धागे की संख्या संभावित असीमित संख्या तक बढ़ सकती है।
5gon12eder 21

1

आपको एक सूत्र का उपयोग करना चाहिए:

प्रत्येक प्रोसेसर आपको व्यस्त रखने की आवश्यकता है।

प्रत्येक I / O आप उपयोगी रूप से समवर्ती रूप से पेंड कर सकते हैं जो आप गैर-अवरुद्ध तरीके से प्रदर्शन नहीं कर सकते हैं। (उदाहरण के लिए, एक स्थानीय डिस्क से पढ़ता है।)

प्रत्येक कार्य जिसके लिए एक समर्पित थ्रेड की आवश्यकता होती है, उदाहरण के लिए एक ऐसे पुस्तकालय में कॉल करना जिसका कोई गैर-अवरोधक इंटरफ़ेस नहीं है या जहां गैर-अवरोधक इंटरफ़ेस उपयुक्त नहीं हैं। इसमें सिस्टम घड़ी की निगरानी, ​​टाइमर की फायरिंग, और इसी तरह के कार्य शामिल हैं।

कुछ अनपेक्षित अवरोधों से बचाने के लिए कुछ अतिरिक्त जैसे पृष्ठ दोष।

गैर-महत्वपूर्ण कोड में उदाहरण के लिए, अपेक्षित अवरोधन से बचाने के लिए कुछ अतिरिक्त, जो अनुकूलन योग्य नहीं है। (उदाहरण के लिए, यदि आपको डीएनएस अनुरोध करने की बहुत कम आवश्यकता हो सकती है, तो संभवतः एसएनएस के एसिंक्रोनस को करने के प्रयास के लायक नहीं है। बस कुछ अतिरिक्त धागे बनाएं और अपने जीवन को आसान बनाएं।)

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


0

आप या तो प्रक्रियाओं और थ्रेड्स को एकल प्रोग्राम के लिए मल्टीकोर \ मल्टीप्रोसेसर सिस्टम के उपयोग को सक्षम करने के लिए कर सकते हैं, जिस स्थिति में आपको अधिक थ्रेड्स \ _ प्रक्रियाएं होने के बाद कोर से कोई लाभ नहीं मिलता है।

या आपके पास उस घटना के लिए मतदान हो सकता है जो आम तौर पर आगे के निष्पादन को अवरुद्ध करता है। इसके बजाय सीपीयू को मतदान के साथ जोड़ दें, आप इसके बजाय एक थ्रेड बना सकते हैं जो एक निष्क्रिय स्थिति में बैठेगा जब तक कि उचित घटना नहीं उठती। इस विधि का उपयोग आमतौर पर वेब सर्वर और GUI इवेंट कतारों में किया जाता है। अधिकांश कार्यक्रम चाहते हैं कि कुछ प्रकार के केंद्रीय डेटा स्टोर हों (भले ही इसका प्रोग्राम निष्पादन कोड) जो सभी थ्रेड तक पहुंच सकते हैं, इसलिए मुझे लगता है कि वे प्रक्रियाओं पर थ्रेडिंग का उपयोग करते हैं।


0

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.