2009-09-09 16 views
7

मैं वर्तमान में एक बहुप्रचारित अनुप्रयोग की समीक्षा/पुन: सक्रिय कर रहा हूं जिसे सभी उपलब्ध कोरों का उपयोग करने में सक्षम होने के लिए बहुसंख्यक माना जाता है और सैद्धांतिक रूप से बेहतर/बेहतर प्रदर्शन प्रदान करता है (बेहतर बेहतर व्यावसायिक शब्द बेहतर होता है: पी)मल्टीथ्रेड कोड में प्रदर्शन कारणों से क्या बचें?

मल्टीथ्रेड किए गए एप्लिकेशन प्रोग्रामिंग करते समय मुझे क्या पता होना चाहिए?

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

क्या मुझे ताले पर सवाल पूछना चाहिए और लॉक-फ्री रणनीति की तलाश करना चाहिए या क्या अन्य बिंदुएं अधिक महत्वपूर्ण हैं जो चेतावनी प्रकाश को प्रकाश देनी चाहिए?

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

मैं डेल्फी 7 का उपयोग कर रहा हूं, हालांकि आवेदन अगले वर्ष के लिए .NET (C#) में पोर्ट/रीमेक किया जाएगा, इसलिए मैं सामान्य अभ्यास के रूप में लागू होने वाली टिप्पणियां सुनूंगा, और यदि वे विशिष्ट होना चाहिए या तो उन भाषाओं में से एक

उत्तर

6

निश्चित रूप से बचने के लिए एक चीज धागे से समान कैश लाइनों तक पहुंचने के लिए बहुत सी चीजें हैं।

उदाहरण के लिए: यदि आप सभी धागे द्वारा संसाधित वस्तुओं की संख्या की गणना करने के लिए काउंटर वैरिएबल का उपयोग करते हैं, तो यह वास्तव में प्रदर्शन को नुकसान पहुंचाएगा क्योंकि जब भी अन्य CPU चरम पर लिखता है तो CPU कैश लाइनों को सिंक्रनाइज़ करना पड़ता है।

+1

अच्छा! मुझे यह नहीं पता था कि, मुझे एक ऐसा अनुभाग मिला है जहां मैं एक इंटरलॉक वृद्धि करता हूं (असल में: असेंबलर में "लॉक इंक") और मैंने कभी भी कैश लाइनों के बारे में सोचना बंद नहीं किया है। +1, मुझे लगता है कि मैं एक +2 –

+0

दे सकता हूं @Zan Lynx यह सच है भले ही आपने परमाणु चर का उपयोग किया हो? जॉर्ज की ओर से +1। :) –

+1

@ काज़र्क: हाँ।परमाणु पहुंच (इंटेल पर LOCK के साथ) कुछ हार्डवेयर में भी धीमी है। –

0

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

जैसा कि आप दोनों कोर का उपयोग करना चाहते हैं, आपको एक उपकरण के साथ कोर का उपयोग जांचना चाहिए जो आपके आवेदन के लिए दोनों कोर पर प्रोसेसर उपयोग को ग्राफ़ कर सकता है, या केवल यह सुनिश्चित कर लें कि आपका कंप्यूटर जितना संभव हो उतना निष्क्रिय हो।

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

लॉक-फ्री रणनीति की तलाश में बहुत मदद मिल सकती है, लेकिन लॉक-फ्री तरीके से अपना एप्लिकेशन प्राप्त करना हमेशा संभव नहीं होता है।

4

अधिक धागे तो कोर हैं, आमतौर पर इसका मतलब है कि कार्यक्रम बेहतर प्रदर्शन नहीं कर रहा है।

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

+1

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

+0

उस स्थिति में, एसिंक्रोनस आर्किटेक्चर का उपयोग करना बहुत अच्छा है और थ्रेड पर भरोसा नहीं है। – Toad

1

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

जब यह बहु-थ्रेडेड अनुप्रयोग के रूप में चल रहा है, तो आप यह देखने के लिए सिस्टम के प्रदर्शन-निगरानी उपकरण का उपयोग कर सकते हैं कि ताले एक समस्या है या नहीं। यह मानते हुए कि आपके धागे व्यस्त-प्रतीक्षा के बजाए लॉक हो जाएंगे, फिर कई धागे के लिए 100% सीपीयू होना एक संकेत है कि लॉकिंग कोई समस्या नहीं है। इसके विपरीत, एक दोहरी प्रोसेसर मशीन पर 50% कुल CPU उपयोगिता की तरह दिखने वाला कुछ ऐसा संकेत है कि केवल एक थ्रेड चल रहा है, और हो सकता है कि आपकी लॉकिंग एक ऐसी समस्या है जो एक से अधिक समवर्ती थ्रेड को रोक रही हो (जब CPU की संख्या की गणना हो आपकी मशीन, बहु-कोर और हाइपरथ्रेडिंग से सावधान रहें)।

ताले न केवल आपके कोड में बल्कि आपके द्वारा उपयोग किए जाने वाले एपीआई में भी हैं: उदा। ढेर प्रबंधक (जब भी आप का आवंटन और स्मृति हटाना), हो सकता है आपके लकड़हारा कार्यान्वयन में, हे में से कुछ में हो सकता है/एस एपीआई, आदि

मैं ताले पूछताछ और एक ताला मुक्त रणनीति के लिए तलाश शुरू कर देना चाहिए

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

5

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

+1

यह एक ट्रेडऑफ है। यदि प्रक्रिया डिस्क के संबंध में बहुत सी CPU का उपयोग करती है, तो यह एक जीत हो सकती है। यह आमतौर पर मल्टीमीडिया थंबनेल पीढ़ी में एक जीत है। हालांकि यह ** ** एक जीत नहीं है जब डेटा स्रोत एक सीडी-रोम है। :) –

2

प्रदर्शन को मारता है जब दो या दो से अधिक धागे समान संसाधन साझा करते हैं। यह एक ऑब्जेक्ट हो सकता है जो दोनों उपयोग करते हैं, या दोनों फाइल जो दोनों का उपयोग करते हैं, एक नेटवर्क दोनों उपयोग या एक प्रोसेसर जो दोनों उपयोग करते हैं। आप साझा संसाधनों पर इन निर्भरताओं से बच नहीं सकते हैं, लेकिन यदि संभव हो, तो संसाधनों को साझा करने से बचने का प्रयास करें।

5

लॉक होने पर ध्यान में रखना कुछ: जितना संभव हो सके उतना समय तक लॉक करें। उदाहरण के लिए, बजाय इस के लिए:

lock(syncObject) 
{ 
    bool value = askSomeSharedResourceForSomeValue(); 
    if (value) 
     DoSomethingIfTrue(); 
    else 
     DoSomtehingIfFalse(); 
} 

ऐसा करें (यदि संभव हो):

bool value = false; 

lock(syncObject) 
{ 
    value = askSomeSharedResourceForSomeValue(); 
} 

if (value) 
    DoSomethingIfTrue(); 
else 
    DoSomtehingIfFalse(); 
बेशक

, इस उदाहरण ही काम करता है DoSomethingIfTrue() अगर और DoSomethingIfFalse() तुल्यकालन की आवश्यकता नहीं है, लेकिन यह इस बिंदु दिखाता : जितना संभव हो उतना कम समय तक लॉक करना, जबकि शायद आपके प्रदर्शन में सुधार न हो, आपके कोड की सुरक्षा में सुधार होगा जिससे यह सिंक्रनाइज़ेशन समस्याओं के लिए सतह क्षेत्र को कम कर देगा।

और कुछ मामलों में, यह प्रदर्शन में सुधार करेगा। लंबे समय तक लॉक रहना मतलब है कि कुछ संसाधनों के लिए इंतजार कर रहे अन्य धागे लंबे समय तक इंतजार कर रहे हैं।

1

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

+1

और जावा में यह java.util.concurrent.locks.ReentrantReadWriteLock –

3

आपको पहले Amdahl's law से परिचित होना चाहिए।

यदि आप जावा का उपयोग कर रहे हैं, तो मैं Java Concurrency in Practice पुस्तक की अनुशंसा करता हूं; हालांकि, इसकी अधिकांश सहायता जावा भाषा (जावा 5 या बाद में) के लिए विशिष्ट है।

सामान्य रूप से, साझा स्मृति की मात्रा को कम करने से समांतरता की मात्रा बढ़ जाती है, और प्रदर्शन के लिए जो एक प्रमुख विचार होना चाहिए।

जीयूआई के साथ थ्रेडिंग एक और बात है, लेकिन ऐसा लगता है कि यह इस विशेष समस्या के लिए प्रासंगिक नहीं है।

1

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

एक मशीन पर कई प्रक्रियाओं के बीच काम को विभाजित करने का लाभ यह है कि एक सर्वर से अधिक प्रदर्शन की आवश्यकता होने पर सर्वर की संख्या में वृद्धि करना आसान होता है।

आप जटिल मल्टीथ्रेड किए गए अनुप्रयोगों से जुड़े जोखिमों को भी कम करते हैं जहां डेडलॉक्स, बाधाएं आदि कुल प्रदर्शन को कम करते हैं।

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

+0

कई प्रक्रियाओं के लिए बहुत सारी "समस्याएं" हैं। सबसे पहले तथ्य यह है कि प्रक्रियाएं समान मेमोरी स्पेस को धागे के रूप में साझा नहीं करती हैं, मैं धागे के बीच बहुत सारी जानकारी साझा करता हूं ताकि धागे से प्रक्रियाओं तक जा सकें, –

+0

पर आसान नहीं होगा कैश की बात आने पर स्मृति साझा करना लाभ नहीं हो सकता एसएमपी में सहारे, लेकिन एकाधिक कोर के साथ मेमोरी साझा करना संभवतः टेबल लुकअप, सर्च-पेड़ इत्यादि को साझा करना बेहतर है फिर भी यह एप्लिकेशन पर निर्भर करता है, यह कैसे डिज़ाइन किया गया है। एक सामान्य नियम यह है कि यह बहुत कठिन है समस्याओं में भाग दिए बिना एक थ्रेडेड एप्लिकेशन को एक बहु थ्रेडेड में बदलने के लिए या इतने सारे ताले डालें कि यह व्यावहारिक रूप से एक थ्रेडेड ऐप के रूप में चलता है। इसे शुरुआत से एमटी होने के लिए डिजाइन किया जाना है। – Ernelli

1

मैं डेल्फी 7

उपयोग कर रहा हूँ आप COM ऑब्जेक्ट का उपयोग किया जा सकता है, तो, स्पष्ट या परोक्ष; यदि आप हैं, तो COM ऑब्जेक्ट्स की अपनी जटिलताओं और थ्रेडिंग पर प्रतिबंध हैं: Processes, Threads, and Apartments

+0

मैं नहीं हूं, लेकिन यह जानना अच्छा है। –

+0

मैंने डेल्फी का उपयोग नहीं किया है, लेकिन मैंने सोचा कि वीसीएल को COM: http://en.wikipedia.org/wiki/Visual_Component_Library का उपयोग करके कार्यान्वित किया गया था - इसके अलावा भी, आपका बहु थ्रेडेड कोड और आपका यूआई निश्चित रूप से होना चाहिए एक दूसरे से अलग। – ChrisW

0

थ्रेड हमेशा प्रदर्शन के बराबर नहीं होते हैं।

चीजों को कुछ ऑपरेटिंग सिस्टम में दूसरों के विपरीत के रूप में बहुत बेहतर है, लेकिन यदि आप कुछ समय तक सो सकते हैं या इसके समय को छोड़कर इसे छोड़ सकते हैं ... या लगभग हर चीज के लिए एक नई प्रक्रिया शुरू नहीं करते हैं, तो आप स्वयं को बचा रहे हैं संदर्भ स्विचिंग में आवेदन को कम करने से।

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