2011-06-05 19 views
6

के लिए समांतर योग कृपया कोई सुझाव दे सकता है कि मैं मल्टीथ्रेडिंग के माध्यम से लूप के रनटाइम के लिए निम्न को कैसे कम कर सकता हूं? मान लीजिए कि मेरे पास 'ए' और 'बी' नामक दो वैक्टर भी हैं।वेक्टर

for (int j = 0; j < 8000; j++){ 
    // Perform an operation and store in the vector 'a' 
    // Add 'a' to 'b' coefficient wise 
} 

लूप के लिए यह मेरे कार्यक्रम में कई बार निष्पादित किया जाता है। उपरोक्त लूप में दो ऑपरेशन पहले ही अनुकूलित किए गए हैं, लेकिन वे केवल एक कोर पर चलते हैं। हालांकि, मेरे पास 16 कोर उपलब्ध हैं और उनका उपयोग करना चाहते हैं।

मैंने निम्नानुसार लूप को संशोधित करने का प्रयास किया है। वेक्टर 'ए' रखने के बजाय, मेरे पास 16 वैक्टर हैं, और मान लीजिए कि i-th को एक [i] कहा जाता है। मेरे लिए पाश अब लग रहा है

तरह
for (int j = 0; j < 500; j++){ 
    for (int i = 0; i < 16; i++){ 
     // Perform an operation and store in the vector 'a[i]' 
    } 
    for (int i = 0; i < 16; i++){ 
     // Add 'a[i]' to 'b' coefficient wise 
    } 

} 

मैं OpenMP में से प्रत्येक पर छोरों के लिए अंदर 'के लिए #pragma omp समानांतर' जोड़कर का उपयोग आंतरिक छोरों से प्रत्येक से पहले। मेरे सभी प्रोसेसर उपयोग में हैं लेकिन मेरा रनटाइम केवल महत्वपूर्ण रूप से बढ़ता है। क्या किसी के पास इस लूप के रनटाइम को कम करने के बारे में कोई सुझाव है? पहले ही, आपका बहुत धन्यवाद।

+0

क्या आपने यह पता लगाने के लिए अपना कोड प्रोफाइल किया है कि बाधाएं कहां हैं? – GWW

+0

ऐसा इसलिए हो सकता है क्योंकि शायद आपको अनुकूलित करने के बाद कोड को छोटे टुकड़ों में तोड़ा नहीं जा सकता है, यदि आपका मूल केवल 'a [i] + = b [i]' जैसा कुछ कर रहा था तो आप उस प्रगामा टैग को उसके ठीक पहले जोड़ सकते हैं के लिये। यह आपके प्रदर्शन को बढ़ावा देगा जैसा आप चाहते थे। – Ali1S232

+0

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

उत्तर

5

omp आपके प्रोग्राम व्हीवर के लिए थ्रेड बनाता है जो आप प्रगा टैग डालते हैं, इसलिए यह आंतरिक टैग के लिए थ्रेड बना रहा है लेकिन समस्या 16 धागे बनाई गई है, प्रत्येक एक 1 ऑपरेशन करता है और फिर उन सभी को आपकी विधि का उपयोग करके नष्ट कर दिया जाता है। थ्रेड बनाने और नष्ट करने में काफी समय लगता है, इसलिए आपके द्वारा उपयोग की जाने वाली विधि आपकी प्रक्रिया के अत्यधिक समय को बढ़ाती है हालांकि यह सभी 16 कोर का उपयोग करती है। आपको अपने 8000 लूप से पहले #pragma omp parallel for टैग डालने के लिए आंतरिक फोर्स बनाने की ज़रूरत नहीं थी, यह ट्रेड के बीच अलग-अलग मूल्यों के लिए ओंप तक है, इसलिए आपने दूसरा लूप बनाने के लिए क्या किया है, ओएमपी का काम है। कि जिस तरह से omp केवल एक बार धागे बनाने और उसके बाद 500 प्रत्येक थ्रेड कि का उपयोग संख्या की प्रक्रिया और उसके बाद (का उपयोग कर 499 कम धागा निर्माण और विनाश) उन सभी को खत्म

+0

यह ओपनएमपी का उपयोग करने वाला मेरा पहला समय है, लेकिन मैं अपनी मुख्य विधि में 'omp_set_num_threads (16)' करता हूं। क्या यह थ्रेडपूल के रूप में कार्य नहीं करता है और किसी भी धागे को नष्ट नहीं करता है? –

+0

धागे फ़ंक्शंस की तरह हैं, आप उनकी सूची में किसी भी ऑपरेशन को जोड़ या हटा नहीं सकते हैं। बस थ्रेड बनाने के फ़ंक्शन के बारे में सोचें जो इनपुट के रूप में कार्य करने के लिए एक सूचक है। रास्ते में 'omp_set_num_threads' कुछ वैकल्पिक है, यदि आप इसे नहीं डालते हैं तो ओएमपी स्वयं चुनता है कि इसे आपके कोड को सबसे अधिक अनुकूलित करने के लिए कितने धागे बनाना चाहिए, यह सेटिंग केवल निर्दिष्ट उपयोग राशि का उपयोग करने के लिए ओंप को मजबूर कर रही है। – Ali1S232

+0

[ओएमपी के लिए विकी पेज] (http://en.wikipedia.org/wiki/OpenMP) में एक साधारण ओम्प प्रोग्राम बनाने के लिए लगभग सभी आवश्यक डेटा शामिल हैं जो आप किसी भी डीबगिंग से पहले इसे पढ़ सकते हैं। – Ali1S232

0

Does anyone have any suggestions on how I can decrease the runtime of this loop?

for (int j = 0; j < 500; j++){ // outer loop 
    for (int i = 0; i < 16; i++){ // inner loop 

हमेशा बाहरी बनाने की कोशिश लूपआंतरिक लूप से कम पुनरावृत्तियों। यह आपको आंतरिक लूप प्रारंभिक से कई बार बचाएगा। उपरोक्त कोड में आंतरिक लूप i = 0;500 बार प्रारंभ किया गया है। अब,

for (int i = 0; j < 16; i++){ // outer loop 
    for (int j = 0; j < 500; j++){ // inner loop 

अब, भीतरी पाश j = 0; केवल 16 बार आरंभ नहीं हो जाता! तदनुसार अपना कोड संशोधित करने का प्रयास करें, अगर इससे कोई प्रभाव पड़ता है।

+3

एक आधुनिक सीपीयू पर, यह सलाह बिल्कुल पीछे की तरफ है। _small_ आंतरिक लूप का अनुक्रम एल 1 कैश में डेटा पर काम करने की अधिक संभावना है, जो लूप काउंटर को शुरू करने के ओवरहेड से 100-1000 गुना अधिक महत्वपूर्ण है। – Nemo

+0

@ नीमो, धन्यवाद, मुझे इससे अनजान था। हालांकि, यहां आप शायद * आंतरिक * लूप के बजाय * छोटे * पाश का मतलब है? यह कैश आकार पर भी निर्भर करेगा। यदि कैश आकार वास्तव में * बड़ा * लूप को समायोजित करने में सक्षम है, तो अभी भी स्थिरता के बारे में तर्क है। – iammilind

+0

हां। कुंजी कैश-अनुकूल है, और एक सामान्य एल 1 कैश इन दिनों 32K की तरह कुछ है। तो आप यह सुनिश्चित करना चाहते हैं कि आपके आंतरिक लूप उस से कम डेटा स्पर्श करें ... – Nemo

3

दरअसल, मैं इन टिप्पणियों को एक उत्तर में डाल रहा हूं।

तुच्छ संचालन के लिए फोर्जिंग थ्रेड केवल ओवरहेड जोड़ता है।

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

gcc -O3 -march=native ... 

पता लगाने के लिए किया जाए या नहीं यह अपने पाश और क्यों ऑटो vectorized -ftree-vectorizer-verbose=2 जोड़ें:

अपने संकलक मान लिया जाये साथ यह आह्वान एक यथोचित आधुनिक जीसीसी है।

यदि आप पहले ही वेक्टर निर्देशों का उपयोग कर रहे हैं, तो यह संभव है कि आप अपनी मेमोरी बैंडविड्थ को संतृप्त कर रहे हों। आधुनिक सीपीयू कोर बहुत तेज हैं ... यदि हां, तो आपको लूप के प्रत्येक पुनरावृत्ति के अंदर अधिक संचालन करने के लिए उच्च स्तर पर पुनर्गठन करने की आवश्यकता है, एल 1 कैश के अंदर फिट होने वाले ब्लॉकों पर बहुत से संचालन करने के तरीके ढूंढ रहे हैं।

+0

आपकी टिप्पणी के लिए धन्यवाद। मेरे पास एसएसई 2 सक्षम है और मैं विजुअल स्टूडियो 2010 आईडीई के साथ माइक्रोसॉफ्ट के कंपाइलर का उपयोग कर रहा हूं। मैं इसे ध्यान में रखूंगा और देख सकता हूं कि मैं कुछ और कर सकता हूं या नहीं। –

+0

मैं सलाह देता हूं कि असेंबली को देखने के लिए एसएस के साथ चल रहा है और सुनिश्चित करें कि यह एसएसई 2 निर्देशों का उपयोग कर रहा है। – Nemo