2012-01-30 23 views
5

मेरे पास एक सी कोड है जो नोड्स के दो सेट (प्रत्येक को तीन समन्वयित करता है) के बीच की दूरी की गणना करता है, भले ही मेरा कोड अभी तक पर्याप्त तेज़ हो गया है, मैं इसे थोड़ा और अधिक बढ़ा देना चाहता हूं समांतर कंप्यूटिंग। मुझे पहले से ही ओपनएमपी के बारे में कुछ जानकारी मिली है और मैं अभी इसका उपयोग करने की कोशिश कर रहा हूं, लेकिन कुछ अजीब बात है। Omp के बिना कोड cpu समय 20s है, दो प्रज्ञा लाइनों को 160s लेता है! यह कैसे हो सकता है?दूरी गणना के लिए समानांतर सी कोड

मैं अक्सर यहां मेरी कोड संलग्न

float computedist(float **vG1, float **vG2, int ncft, int ntri2, int jump, float *dist){ 
    int k = 0, i, j; 
    float min = 0; 
    float max = 0; 
    float avg = 0; 
    float *d = malloc(3*sizeof(float)); 
    float diff; 

    #pragma omp parallel 
    for(i=0;i<ncft;i+=jump){ 
     #pragma omp parallel 
     for(j=0;j<ntri2;j++){ 
      d[0] = vG1[i][0] - vG2[j][0]; 
      d[1] = vG1[i][1] - vG2[j][1]; 
      d[2] = vG1[i][2] - vG2[j][2]; 
      diff = sqrt(pow(d[0],2) + pow(d[1],2) + pow(d[2],2)); 
      if(j==0) 
       dist[k] = diff; 
      else 
       if(diff<dist[k]) 
        dist[k] = diff; 

     } 
     avg += dist[k]; 
     if(dist[k]>max) 
      max = dist[k]; 
     k++; 
    } 

    printf("max distance: %f\n",max); 
    printf("average distance: %f\n",avg/(int)(ncft/jump)); 

    free(d); 

    return max; 
} 

आप कोई मदद

+0

"यह कैसे हो सकता है?" - सामान्य कारण अनुचित समानांतर योजना है, या तो संदर्भ के इलाके या बहुत अधिक सिंक्रनाइज़ेशन (या दोनों) के माध्यम से। –

+1

आप 1 के लिए एक वातावरण चर OMP_NUM_THREADS निर्धारित करते हैं, और एक ही धागे के साथ अपने OpenMP कार्यक्रम चलाते हैं, कितना समय लगेगा? –

+0

@AlexeyKukanov यह ठीक डाल शून्य omp_set_num_threads (NUM_THREADS int) समानांतर पाश से पहले है? – Nicholas

उत्तर

5

(नीचे उत्तर प्रश्न में प्रारंभिक कोड है, जो तब से इन सुझावों को लागू करने के साथ सुधार किया गया था को संदर्भित करता है)


आप कैसे OpenMP का उपयोग करने के बारे में और अधिक पढ़ने की जरूरत है। विनिर्देश http://www.openmp.org पर उपलब्ध है; और ट्यूटोरियल और अन्य संसाधनों के लिंक हैं।

मैं आपके कोड में कुछ मुद्दों को इंगित करूंगा और सिफारिशें दूंगा कि उन्हें कैसे ठीक किया जाए।

float *d = malloc(3*sizeof(float)); 
    float diff; 

d एक अस्थायी चर के रूप में प्रयोग किया जाता है, तो (नीचे देखें) #pragma omp parallel for में private के रूप में चिह्नित किया जाना चाहिए डेटा दौड़ से बचने के लिए। इस बीच, गतिशील आवंटन के बजाय, मैं केवल 3 अलग-अलग फ्लोट का उपयोग करूंगा। diff में अस्थायी मान भी है, इसलिए private भी होना चाहिए।

#pragma omp parallel 
    for(i=0;i<ncft;i+=jump){ 
     #pragma omp parallel 
     for(j=0;j<ntri2;j++){ 

आप एक समानांतर क्षेत्र में, जहां प्रत्येक थ्रेड पूरे पाश कार्यान्वित (क्योंकि क्षेत्र किसी भी काम साझा करने निर्माणों शामिल नहीं है) बनाया है, और इसके अंदर आप एक नया के साथ एक नेस्टेड क्षेत्र नहीं बनाया गया (!) धागे की निर्धारित करते हैं, प्रत्येक भी आंतरिक आंतरिक पाश निष्पादित करता है। यह आपके कार्यक्रम में बहुत सारे ओवरहेड और अनावश्यक गणना को जोड़ता है। आपको क्या चाहिए #pragma omp parallel for, और केवल बाहरी पाश पर लागू होता है।

  d[0] = vG1[i][0] - vG2[j][0]; 
      d[1] = vG1[i][1] - vG2[j][1]; 
      d[2] = vG1[i][2] - vG2[j][2]; 
      diff = sqrt(pow(d[0],2) + pow(d[1],2) + pow(d[2],2)); 

समानांतरवाद से संबंधित नहीं है, लेकिन सिर्फ वर्गों की गणना करने के क्यों pow बुला? एक अच्छा पुराना गुणा संभवतः पढ़ने और तेज़ दोनों के लिए आसान होगा।

  if(j==0) 
       dist[k] = diff; 
      else 
       if(diff<dist[k]) 
        dist[k] = diff; 

के बाद कार्रवाई में एक ही (dist[k]=diff;) है, कोड के साथ || (तार्किक या) दो शर्तों के संयोजन के द्वारा सरल किया जा सकता।

 } 
     avg += dist[k]; 
     if(dist[k]>max) 
      max = dist[k]; 

यहाँ आप बाहरी पाश के एकत्रित मूल्यों की गणना।ओपनएमपी में, यह #pragma omp for के खंड के साथ किया जाता है।

 k++; 
    } 

वर्तमान में, आप प्रत्येक यात्रा पर k को बढ़ा देते हैं, इस प्रकार पुनरावृत्तियों के बीच एक अनावश्यक निर्भरता कि समानांतर कोड में एक डेटा जाति की ओर जाता है का निर्माण। अपने कोड के अनुसार, k सिर्फ एक सुविधाजनक i/jump के लिए "उर्फ" है - तो बस यात्रा की शुरुआत में इस तरह के रूप में निर्दिष्ट करें, और private बनाते हैं।

+0

मैंने आपके सभी सुझावों को लागू किया है लेकिन यह अभी भी ठीक से काम नहीं करता है – Nicholas

2

आप तुल्यकालन का एक बहुत का उपयोग के लिए बहुत बहुत धन्यवाद जब आप दोनों बाहरी पाश और भीतरी पाश पर #pragma omp parallel जोड़ें।

#pragma omp parallel का उपयोग करते समय, लूप के बाद barrier है, इसलिए सभी थ्रेड अंतिम थ्रेड समाप्त होने तक प्रतीक्षा करते हैं।
अपने मामले में, आपको आंतरिक लूप और दोनों बाहरी लूप दोनों में सभी थ्रेडों का इंतजार करना होगा, इस प्रकार आपको सिंक्रोनाइज़ेशन का उपयोग करने के लिए बहुत अधिक ओवरहेड मिल जाएगा।

बाधाओं की मात्रा को कम करने के लिए केवल बाहरी लूप पर #pragma omp parallel का उपयोग करना सबसे अच्छा होता है [माना जाता है कि वहां पर्याप्त काम है ...]।

+0

यदि मैं केवल बाहरी लूप में '#pragma omp समानांतर' डालता हूं तो प्रोग्राम मुझे बस त्रुटि देता है ... – Nicholas

+0

@ निकोलस: सुनिश्चित नहीं है, लेकिन मुझे लगता है कि अगर आप निजी (i) 'बाहरी के लिए समानांतर' pragma omp 'डालते हैं लूप आपको ठीक होना चाहिए। यह एक अलग मुद्दा है, इसलिए यदि आप काम नहीं करते हैं तो आप इस समस्या के बारे में अधिक जानकारी के साथ एक नया प्रश्न पोस्ट करना चाहेंगे। – amit

+0

मैंने निजी सामान का उपयोग करके और थोड़ा सा अध्ययन करने के बाद अपना प्रश्न अपडेट किया :) – Nicholas

0

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

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