2012-03-31 14 views
6

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

#include <vector> 

int main(){ 

    vector<double> numbers; 
    vector<double> results(10); 
    double x; 

    //write 10 values in vector numbers 
    for (int i =0; i<10; i++){ 
     numbers.push_back(cos(i)); 
    } 

#pragma omp parallel for \ 
    private(x) \ 
    shared(numbers, results) 
     for(int j = 0; j < 10; j++){ 

      x = 2 * numbers[j] + 5; 
#pragma omp critical // do I need this ? 
      { 
       results[j] = x;  
      } 
     } 

    return 0; 

} 

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

लेखन ऑपरेशन के साथ वही प्रश्न: क्या मुझे महत्वपूर्ण प्रगति की आवश्यकता है या क्या कोई समस्या नहीं है क्योंकि प्रत्येक थ्रेड वेक्टर परिणामों के एक अलग तत्व में लिखता है? मैं जो भी मदद प्राप्त कर सकता हूं उससे खुश हूं और यह जानना अच्छा होगा कि ऐसा करने का कोई बेहतर तरीका है (शायद वैक्टर का उपयोग न करें, लेकिन सरल सरणी और पॉइंटर्स इत्यादि?) मैंने वेक्टर भी पढ़े हैं कुछ मामलों में सुरक्षित धागा नहीं है और यह सूचक का उपयोग करने की अनुशंसा की जाती है: OpenMP and STL vector

आपकी मदद के लिए बहुत बहुत धन्यवाद!

उत्तर

7

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

आप अपने सरणी का आकार बदलना नहीं कर रहे हैं, तो मैं समवर्ती पढ़ने के साथ किसी भी मुसीबत नहीं था पड़ा है वेक्टर में लिखते हैं (जाहिर है, जब तक कि मैं दो बार एक ही तत्व नहीं लिख रहा हूँ)

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

आप महत्वपूर्ण अनुभाग कथन को हटा सकते हैं (शर्तों के साथ दिमाग में ऊपर)।

+0

वह बिल्कुल वेक्टर आकार बदलने नहीं है। – eudoxos

+0

@ यूडॉक्सोस मुझे एहसास है कि कोड स्निपेट से, मैं बस यह सुनिश्चित करना चाहता था कि इसका उल्लेख किया गया था, खासकर जब से वह इस तथ्य को सामने लाए कि एसटीएल वैक्टर कुछ शर्तों के तहत थ्रेड-सुरक्षित नहीं हैं – SirGuy

+0

+1: यह वास्तव में नहीं आता है यहां, लेकिन आपको यह ध्यान रखना होगा कि वेक्टर-विशिष्ट संचालन जैसे कि संलग्न करना, आकार बदलना आदि थ्रेडसेफ नहीं है और शायद टूट जाएगा।लेकिन बस एक वेक्टर के तत्वों पर परिचालन ठीक है जब तक कि प्रत्येक तत्व केवल एक धागे द्वारा लिखा जा रहा है। –

5

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

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

(BTW आप पाश अंदर x घोषित private(x) से बचने के लिए कर सकते हैं और shared निर्देश IIRC (मैं इसे इस्तेमाल कभी नहीं)। निहित है)

+0

+1; यदि आप आकार बदल रहे हैं या आप में वेक्टर नहीं हैं, तो यह सिर्फ 1 डी सरणी है, और ओपनएमपी एरे पर परिचालन में बहुत अच्छा है। स्थिर, निजी, आदि के लिए, मुझे लगता है कि "सर्वोत्तम अभ्यास" डिफ़ॉल्ट (कोई भी नहीं) का उपयोग करना है और सबकुछ स्पष्ट रूप से निजी या साझा करना है, बस स्पष्ट होना चाहिए, और @Uudoxos बताते हैं, समानांतर के दायरे में परिभाषित चर अनुभाग उन्हें पूरी तरह से निजी बनाता है और फिर कोड का पालन करना थोड़ा आसान है। आपकी मदद के लिए –

+0

हाय धन्यवाद। क्या लूप के अंदर एक्स घोषित करना वास्तव में तेज़ है (प्रत्येक धागा इसे ऊपर बताएगा, दाएं) ऊपर की तरह लूप से पहले, या यह वही प्रदर्शन के अनुसार है, लेकिन सिर्फ देखने के लिए अच्छा है? इसका क्या अर्थ है कि स्मृति पहुंच रैखिक नहीं है और ऐसा क्यों है? – user1304680

+0

@ user1304680: घोषणा कंपाइलर के लिए है, यह सिर्फ इतना कहता है कि आप कुछ आकार की स्मृति का एक टुकड़ा रखना चाहते हैं और इसे बाद के कोड में किसी भी तरह से कॉल करना चाहते हैं। मुझे संदेह है कि किसी भी सभ्य, मामूली अनुकूलन कंपाइलर के लिए एक फर्क पड़ता है। गैर-रैखिक पहुंच: मेरा मतलब आसन्न स्मृति क्षेत्रों में धागे से तत्वों के लिए यादृच्छिक पहुंच था। रैम तब सीपीयू को स्मृति का एक हिस्सा प्रदान करता है, जो वेक्टर आइटम से बड़ा है। यदि 2 कोर पास के राम के टुकड़े तक पहुंचते हैं, तो यह एक ही कैश लाइन में हो सकता है और फिर उन्हें एचडब्ल्यू स्तर पर सिंक्रनाइज़ किया जाता है, लेकिन यह धीमा हो जाता है। जब तक आपको आवश्यकता न हो तब तक इसके बारे में चिंता न करें। – eudoxos

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