2012-05-14 22 views
5

धागे बनाएं I OpenMP का उपयोग करके सरल एप्लिकेशन लिखने का प्रयास करें। दुर्भाग्य से मुझे गति के साथ समस्या है। इस एप्लिकेशन में मेरे पास एक लूप है। इस पाश के शरीर में कुछ निर्देश होते हैं जिन्हें क्रमशः किया जाना चाहिए और लूप के लिए एक होना चाहिए। मैं लूप समानांतर के लिए इसे बनाने के लिए #pragma omp parallel for का उपयोग करता हूं। इस लूप में ज्यादा काम नहीं है, लेकिन इसे अक्सर कहा जाता है।ओपनएमपी - केवल एक बार

मैं लूप के दो संस्करण तैयार करता हूं, और 1, 2 और 4cores पर एप्लिकेशन चलाता हूं।
संस्करण 1 (लूप के लिए 4 पुनरावृत्तियों): 22sec, 23sec, 26sec।
संस्करण 2 (लूप के लिए 100000 पुनरावृत्तियों): 20sec, 10sec, 6sec।

जैसा कि आप देख सकते हैं, जब लूप के पास अधिक काम नहीं होता है, तो 2 और 4 कोर पर समय 1core से अधिक होता है। मुझे लगता है कि कारण यह है कि #pragma omp parallel for लूप के प्रत्येक पुनरावृत्ति में नए धागे बनाता है। तो, मैं आपसे पूछना चाहता हूं - क्या एक बार थ्रेड बनाने के लिए कोई संभावना है (लूप से पहले), और सुनिश्चित करें कि लूप के दौरान कुछ नौकरी अनुक्रमिक रूप से की जाएगी?

#include <omp.h> 
#include <iostream> 
#include <math.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <time.h> 
int main(int argc, char* argv[]) 
{ 
    double sum = 0; 
    while (true) 
    { 
     // ... 
     // some work which should be done sequentially 
     // ... 

     #pragma omp parallel for num_threads(atoi(argv[1])) reduction(+:sum) 
     for(int j=0; j<4; ++j) // version 2: for(int j=0; j<100000; ++j) 
     { 
      double x = pow(j, 3.0); 
      x = sqrt(x); 
      x = sin(x); 
      x = cos(x); 
      x = tan(x); 
      sum += x; 

      double y = pow(j, 3.0); 
      y = sqrt(y); 
      y = sin(y); 
      y = cos(y); 
      y = tan(y); 
      sum += y; 

      double z = pow(j, 3.0); 
      z = sqrt(z); 
      z = sin(z); 
      z = cos(z); 
      z = tan(z); 
      sum += z; 
     } 

     if (sum > 100000000) 
     { 
      break; 
     } 
    } 
    return 0; 
} 

उत्तर

5

आप while (true) लूप के बाहर समानांतर क्षेत्र को स्थानांतरित करने और कोड के सीरियल हिस्सा केवल एक ही धागे में निष्पादित करने के लिए बनाने के लिए single निर्देश इस्तेमाल कर सकते हैं। यह फोर्क/मॉडल में शामिल होने के ऊपरी हिस्से को हटा देगा। ओपनएमपी बहुत ही कम संख्या में पुनरावृत्तियों (जैसे आपका संस्करण 1) के साथ वास्तव में उपयोगी नहीं है। आप मूल रूप से ओपनएमपी ओवरहेड को माप रहे हैं क्योंकि लूप के अंदर काम वास्तव में तेज़ किया जाता है - पारस्परिक कार्यों के साथ भी 100000 पुनरावृत्तियों को वर्तमान पीढ़ी के सीपीयू (2 गीगाहर्ट्ज़ पर और लगभग 100 चक्र प्रति एफपी इंस्ट्रुसिटन के अतिरिक्त) से कम लेते हैं, यह इसके अलावा ~ 100 एमएस ले लो)।

यही कारण है कि OpenMP if(condition) खंड है कि चुनिंदा छोटे छोरों के लिए parallelisation बंद करने के लिए इस्तेमाल किया जा सकता प्रदान करता है:

#omp parallel for ... if(loopcnt > 10000) 
for (i = 0; i < loopcnt; i++) 
    ... 

यह भी नियमित रूप से छोरों के लिए schedule(static) (कि छोरों के लिए है का प्रयोग उचित है जो हर में गणना करने के लिए एक ही समय में पुनरावृत्ति होती है)।

8

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

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

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