2015-12-25 5 views
9

में समकालिक समांतर प्रक्रिया में मेरे पास एक सरणी x [] डेटा है। इसके अलावा "सिस्टम स्टेटस" सी [] की एक सरणी है। प्रक्रिया:सी #/सी ++

for(i = 1; i < N; i++) 
{ 
    a = f1(x[i] + c[i-1]); 
    b = f2(x[i] + c[i-1]); 
    c[i] = a + b; 
} 

2 समानांतर धागे का उपयोग कर 2-कोर प्रणाली पर f1 और f2 के मूल्यों को खोजने के लिए किसी भी कारगर तरीका है? मेरा मतलब है निम्नलिखित (छद्म कोड में):

thread_1 
{ 
    for(i = 1; i < N; i++) 
     a = f1(x[i] + c[i-1]);  
} 
thread_2 
{ 
    for(i = 1; i < N; i++) 
    { 
     b = f2(x[i] + c[i-1]); 
     c[i] = a + b; //here we somehow get a{i} from thread_1 
    } 
} 

f1 और f2 समय तपेदिक़ नहीं हैं, लेकिन कई बार की गणना की जा करने के लिए है, इसलिए वांछित speedup x2 बारे में है। चित्रमय प्रतिनिधित्व के लिए चित्र देखें:

desired parallel process

विंडोज के लिए कोड उदाहरण के लिए देख रहे हैं।

+1

यह केवल प्रभावशाली हो सकता है अगर एफ 1 और एफ 2 बहुत भारी हैं और सिंक्रनाइज़ेशन ओवरहेड समांतर रन – gabba

+0

के लाभ से कम होगा, यह टैग क्यों किया गया है # ** और ** सी ++? आप किस भाषा का उपयोग कर रहे हैं? –

+0

भाषा का विकल्प इस बात पर निर्भर करता है कि कार्य को और अधिक कुशलता से हल कर सकते हैं – carimus

उत्तर

4

अगर मैं तुम्हें सही समझते हैं,

  • a[i] केवल गणना की जा सकती है जब c[i-1] उपलब्ध है
  • b[i] केवल गणना की जा सकती है जब c[i-1] उपलब्ध है
  • c[i] ही उपलब्ध है a[i] और b[i] गणना कर रहे हैं जब

इसका मतलब है कि एकमात्र प्रक्रिया जिसे आप अलग से कर सकते हैं a[i] और b[i] की गणना कर रहा है।

कि मैं इसे कैसे सी # में देखें:

for (int i = 1; i < N; i++) 
{ 
    Task<double> calcA = Task.Factory.StartNew(() => { return f1(x[i] + c[i-1]); }); 
    Task<double> calcB = Task.Factory.StartNew(() => { return f2(x[i] + c[i-1]); }); 

    // .Result will block the execution and wait for both calculations to complete 
    c[i] = calcA.Result + calcB.Result; 
} 

यह दो अलग-अलग धागे, जो क्रमशः f1 और f2 की गणना करेगा चलेंगे। f1 और f2 दोनों की गणना के बाद, यह c[i] मान सेट करेगा, और अगले पुनरावृत्ति को चलाएगा।

ध्यान दें कि:

  • मैं double उपयोग करते हैं, यह सोचते हैं कि आपके f1 और f2 वापसी double
  • पाश 1 से शुरू होता है, यह मानते हुए आप कुछ प्रारंभिक a[0] और b[0] मूल्यों है। अन्यथा, c[i-1] संसाधन लेने वाली और लंबे समय तक, अन्य गणना
  • Task.Factory.StartNew की तुलना में (विपरीत Thread का प्रयोग करके) ThreadPool का उपयोग करता है जिसका अर्थ है कि यह नहीं करता है 'अगर f1 और f2 की गणना वास्तव में है एक अपवाद
  • यह केवल सुधार लाना होगा फेंक टी हर बार एक नया धागा बनाते हैं, लेकिन पूल से मौजूदा का पुन: उपयोग करते हैं। यह विशेष रूप से उपरि को कम कर देता है।
+0

यह गलत काम करेगा, क्योंकि लूप वैरिएबल को बंद करने में उपयोग किया जाता है। आपको स्थानीय प्रतिलिपि बनाने की आवश्यकता है – VMAtm

+0

@VMAtm चूंकि कार्य घोषित किया गया है, उसी लूप पुनरावृत्ति के भीतर चलाया और समाप्त हो गया है, मुझे 'i' संशोधन की कोई संभावना नहीं दिखाई देती है। मैं गलत हो सकता हूं, निश्चित रूप से ... –

+1

यह केवल efficien हो सकता है अगर f1 और f2 बहुत भारी हैं और सिंक्रनाइज़ेशन ओवरहेड समांतर रन – gabba

2

कोड समाधान में जाने के बिना, आप किसी प्रकार की बाधा का उपयोग करना चाहते हैं। यह जांचने की अनुमति देता है कि क्या सभी प्रतिभागियों ने घोषणा की है कि वे कार्य के साथ समाप्त हो गए हैं।थ्रेड 2 इस उदाहरण में धागा एक के लिए प्रतीक्षा करने

https://en.wikipedia.org/wiki/Barrier_(computer_science) Example of C++ "Memory barrier"

3

इस एल्गोरिथ्म में केवल समानांतर हिस्सा F1 और F2 की गणना है होगा, लेकिन आप का कहना है कि F1 और F2 समय तपेदिक़, इसलिए नहीं कर रहे हैं सिम वेक्टरेशन (उदाहरण के लिए System.Numerics.Vectors में सी #) का उपयोग करना और इसे एक कोर पर चलाने के लिए बेहतर हो सकता है (जो कैश मिस को भी कम करता है)। या शायद आप समानांतर होने के लिए अपने एल्गोरिदम को संशोधित कर सकते हैं (लेकिन इसे कड़ी मेहनत की आवश्यकता हो सकती है)।