2008-10-03 10 views
8

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

 
insert(triangle, bspnode) 
{ 
    .... 
    else if(triangle spans bspnode) 
    { 
    (frontpiece, backpiece) = plane_split(triangle, bspnode) 

    insert(frontpiece, bspnode.front) 
    insert(backpiece, bspnode.back) 
    } 
    .... 
} 

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

 
insert(triangle, bspnode) 
{ 
    .... 
    else if(triangle spans bspnode) 
    { 
    (frontpiece, backpiece) = split(triangle, bspnode) 

    handle = beginthread(insert(backpiece, bspnode.front)) 
    insert(frontpiece, bspnode.back) 
    if(handle) 
    { 
     waitforthread(handle) 
    } 
    else 
    { 
     insert(backpiece, bspnode.front) 
    } 
    } 
    .... 
} 

इस नई विधि समानांतर में इस कार्य को पूरा करने के लिए एक धागा बनाने का प्रयास करता है, लेकिन धागा नहीं बनाया जा सकता है, तो असफल नहीं होना चाहिए (यह केवल मूल एल्गोरिथ्म पर लौट जाएगा)।

क्या यह एक ध्वनि प्रोग्रामिंग अभ्यास है, या क्या मैं अनुचित रूप से धागे का उपयोग कर रहा हूं? मैं इस तकनीक पर कोई साहित्य नहीं ढूंढ पा रहा हूं। मुझे यह पसंद है कि यह मेरे सीपीयू को अपने पूर्ण (2 कोर) तक उपयोग करने का प्रयास करता है, और सैद्धांतिक रूप से उपलब्ध प्रोसेसर की किसी भी संख्या में स्केल करेगा। मुझे यह पसंद नहीं है कि यह सीपीयू और मेमोरी पर बेहद अपमानजनक हो सकता है।

उत्तर

11

थ्रेड बहुत बढ़िया हैं यदि प्रसंस्करण का कुछ हिस्सा कुछ बाहरी (उपयोगकर्ता इनपुट, आई/ओ, कुछ अन्य प्रसंस्करण) पर इंतजार कर रहा है - जो थ्रेड इंतजार कर रहा है, वह प्रतीक्षा कर सकता है, जबकि एक धागा जो कि फोर्ज पर इंतजार नहीं कर रहा है आगे।

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

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

+1

ओह और वह RHYMES! :) हहा नाइस! – Kiril

+0

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

2

आपकी सबसे अच्छी शर्त थ्रेडपूल बनाने के लिए होगी, और उसके बाद नोड्स जोड़ने के लिए इसे 'पारदर्शी' का उपयोग करें।

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

आपके ऐप का समग्र प्रदर्शन धीमा है क्योंकि आपके पास कतार में डेटा कॉपी करने और अतिरिक्त थ्रेड चलाने में अधिक ओवरहेड है, लेकिन यदि आप एक कोर पर चलते थे तो आप अब 2 पर चलेंगे। यह काम करता है सबसे अच्छा अगर थ्रेडेड प्रसंस्करण महंगा है।

0

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