2012-08-23 14 views
9

मैं यहां नया हूं और सी में एक शुरुआती स्तर प्रोग्रामर हूं। मुझे फॉर-लूप को गति देने के लिए ओपनएमपी का उपयोग करने में कुछ समस्या है। नीचे सरल उदाहरण है:लूप के लिए ओपनएमपी और सी समानांतर: OpenMP का उपयोग करते समय मेरा कोड धीमा क्यों होता है?

#include <stdlib.h> 
#include <stdio.h> 
#include <gsl/gsl_rng.h> 
#include <omp.h> 

gsl_rng *rng; 

main() 
{ 
int i, M=100000000; 
double tmp; 

/* initialize RNG */ 
gsl_rng_env_setup(); 
rng = gsl_rng_alloc (gsl_rng_taus); 
gsl_rng_set (rng,(unsigned long int)791526599); 

// option 1: parallel   
    #pragma omp parallel for default(shared) private(i, tmp) schedule(dynamic) 
    for(i=0;i<=M-1;i++){ 
    tmp=gsl_ran_gamma_mt(rng, 4, 1./3); 
    } 


// option 2: sequential  
    for(i=0;i<=M-1;i++){ 
    tmp=gsl_ran_gamma_mt(rng, 4, 1./3); 
    } 
} 

कोड एम पुनरावृत्तियों के लिए गामा यादृच्छिक वितरण से खींचता है। यह openmp (विकल्प 1) के साथ समानांतर दृष्टिकोण को लगभग 1 मिनट लेता है जबकि अनुक्रमिक दृष्टिकोण (विकल्प 2) केवल 20 सेकंड लेता है। ओपनएमपी के साथ चलते समय, मैं देख सकता हूं कि सीपीयू उपयोग 800% है (जिस सर्वर का मैं उपयोग कर रहा हूं वह 8 सीपीयू है)। और सिस्टम जीसीसी 4.1.3 के साथ लिनक्स है। मैं संकलित कमांड का उपयोग कर रहा हूं gcc-fopenmp -lgsl -lgslcblas -lm (मैं जीएसएल का उपयोग कर रहा हूं)

क्या मैं कुछ गलत कर रहा हूं? कृपया मेरी मदद करें! धन्यवाद!

पीएस जैसा कि कुछ उपयोगकर्ताओं द्वारा इंगित किया गया है, यह आरएनजी के कारण हो सकता है। लेकिन फिर भी अगर मैं की जगह

tmp=gsl_ran_gamma_mt(rng, 4, 1./3); 

से कहना

tmp=1000*10000; 

समस्या अभी भी वहाँ ...

+0

आपको अपना लूप वैरिएबल मैं निजी नहीं बनाना चाहिए - ओपनएमपी इसका ख्याल रखेगा। मुझे नहीं पता कि यह निष्पादन को प्रभावित करता है, लेकिन आपको इसे ठीक करना चाहिए और पुनः स्थापित करना चाहिए। –

+0

इसके अलावा, ध्यान दें कि tmp = 1000 * 10000 शायद कंपाइलर द्वारा एक नोप पर अनुकूलित हो जाता है, जिससे आपका समय समाप्त हो जाएगा। –

+0

क्या आप वाकई 8 सीपीयू हैं? क्या यह हाइपरथ्रेडिंग के साथ क्वाड-कोर हो सकता है? –

उत्तर

12

gsl_ran_gamma_mt शायद rng पर ताले संगामिति मुद्दों को रोकने के लिए (यदि ऐसा नहीं है, अपने समानांतर कोड में शायद दौड़ की स्थिति होती है और इस प्रकार गलत परिणाम मिलते हैं)। तब समाधान प्रत्येक थ्रेड के लिए एक अलग rng उदाहरण होगा, इस प्रकार लॉकिंग से परहेज करेगा।

+1

बहुत बहुत धन्यवाद! लेकिन समस्या तब भी बनी हुई है जब मैं tmp = gsl_ran_gamma_mt (rng, 4, 1./3) को tmp = 1000 * 10000 – user1620200

+0

@ user1620200 विषम के साथ बदलता हूं, वहां एक कठोर कमी होनी चाहिए। बेशक, समान गणना के लिए अभी भी एक विशाल ओवरहेड है, क्योंकि वास्तविक गणना बहुत तेज है, यहां तक ​​कि बहुत सारे पुनरावृत्तियों के साथ भी। गतिशील अनुसूची मदद नहीं करता है (एक स्थिर कोशिश करें, यहां गतिशील अनुसूची का कोई कारण नहीं है क्योंकि कार्यों के सभी आकार समान हैं)। अंत में, स्टीफन की सलाह आज़माएं लेकिन मुझे आश्चर्य होगा अगर यह मुद्दा था क्योंकि इसे छोटा रूप से अनुकूलित किया जाना चाहिए। –

+0

धन्यवाद। मुझे पता चला कि अगर मैं अनुसूची (गतिशील) से छुटकारा पाता हूं, तो समस्या खत्म हो गई है! मुझे आश्चर्य है क्योंकि? – user1620200

5

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

+0

बहुत बहुत धन्यवाद! लेकिन समस्या तब भी बनी हुई है जब मैं tmp = gsl_ran_gamma_mt (rng, 4, 1./3) को tmp = 1000 * 10000 कहता हूं; – user1620200

1

फिर से मदद करने के लिए सभी को धन्यवाद। मुझे अभी पता चला है कि अगर मैं कोड में

schedule(dynamic) 

से छुटकारा पाता है, तो समस्या खराब हो जाती है। लेकिन वह क्यों है?

+1

'गतिशील 'शेड्यूलिंग काफी महंगी है और केवल उन मामलों में उपयोग की जानी चाहिए जहां पुनरावृत्तियों को पूरा करने में काफी समय लगता है लेकिन यह समय प्रत्येक पुनरावृत्ति के साथ काफी भिन्न हो सकता है। 'निर्देशित' और भी महंगा है क्योंकि यह पुनरावृत्ति को छोटे और छोटे ब्लॉक बनाता है। गणना समय के साथ पुनरावृत्तियों के लिए 'स्थिर 'शेड्यूलिंग का उपयोग करें। –

+0

बहुत धन्यवाद Hristo Iliev! – user1620200

+1

मुझे लगता है कि आप अपना जवाब स्वीकार कर सकते हैं, क्योंकि आप इस मुद्दे को हल करने वाले थे। –

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