2016-02-05 16 views
7

में लागू की जा सकती है यह मेरी पहली पोस्ट है। मैं इसे छोटा रखने की कोशिश करूंगा क्योंकि मैं आपके समय का महत्व देता हूं। यह समुदाय मेरे लिए अविश्वसनीय रहा है।क्या यह समांतरता ओपनसीएल

मैं ओपनसीएल सीख रहा हूं और नीचे एल्गोरिदम से समानांतरता को निकालना चाहता हूं। मैं केवल आपको वह हिस्सा दिखाऊंगा जिस पर मैं काम कर रहा हूं, जिसे मैंने जितना संभव बनाया उतना सरल बना दिया है।

1) इनपुट: दो 1 डी सरणी लंबाई (एन): ए, बी, और एन का मान। सी [0], डी [0] भी मानता है।

2) आउटपुट: लंबाई के दो -1 डी सरणियों (एन): सी, डी

C[i] = function1(C[i-1]) 
D[i] = function2(C[i-1],D[i-1]) 

तो इन पुनरावर्ती परिभाषा, एक दिया मैं मूल्य के लिए सी & डी की लेकिन गणना में किया जा सकता है समानांतर (वे स्पष्ट रूप से अधिक जटिल हैं, इसलिए समझने के लिए)। दो काम आइटम (संख्या 0,1) में से प्रत्येक के

__kernel void test (__global float* A, __global float* B, __global float* C, 
        __global float* D, int n, float C0, float D0) { 
    int i, j=get_global_id(0); 

    if (j==0) { 
     C[0] = C0; 
     for (i=1;i<=n-1;i++) { 
      C[i] = function1(C[i-1]); 
      [WAIT FOR W.I. 1 TO FINISH CALCULATING D[i]]; 
     } 
     return; 
    } 
    else { 
     D[0] = D0; 
     for (i=1;i<=n-1;i++) { 
      D[i] = function2(C[i-1],D[i-1]); 
      [WAIT FOR W.I. 0 TO FINISH CALCULATING C[i]]; 
     } 
     return; 
    } 
} 

आदर्श रूप में एक प्रारंभिक तुलना करना होगा और उसके बाद अपने-अपने पाश में प्रवेश, प्रत्येक यात्रा के लिए सिंक्रनाइज़ किया जा रहा है: एक अनुभवहीन सोचा निम्नलिखित कर्नेल के लिए दो काम आइटम बनाने की जाएगी । अब GPUs के सिम कार्यान्वयन को देखते हुए, मुझे लगता है कि यह काम नहीं करेगा (काम आइटम सभी कर्नेल कोड के लिए इंतजार कर रहे हैं), हालांकि क्या इस प्रकार के काम को दो सीपीयू कोरों में असाइन करना संभव है और यह अपेक्षा के अनुसार काम करता है? इस मामले में बाधा क्या होगी?

+1

क्या आपको आवश्यकता है कि सी और डी के सभी मूल्यों को बचाया जाए, या आप केवल अंतिम परिणाम की परवाह करते हैं? – mfa

+1

क्या आप कृपया 'function1' और' function2' को परिभाषित कर सकते हैं? –

उत्तर

0

आपके मामले में निर्भरता पूरी तरह रैखिक/पुनरावर्ती है (मुझे i-1 की आवश्यकता है)। अन्य समस्याओं की तरह logaritmic भी नहीं (कमी, योग, क्रम, आदि)। और इसलिए यह समस्या एक सिम डिवाइस में अच्छी तरह से फिट नहीं है।

सबसे अच्छा आप कर सकते हैं सीपीयू में 2 धागे दृष्टिकोण। थ्रेड 1 डेटा (सी मूल्य) "उत्पादन" होगा, धागा 2.

उदाहरण के लिए एक बहुत ही सरल दृष्टिकोण के लिए:

Thread 1: 
for(){ 
    ProcessC(i); 
    atomic_inc(counter); //This function should unlock 
} 

Thread 2: 
for(){ 
    atomic_dec(counter); //This function should lock 
    ProcessD(i); 
} 

कहाँ atomic_inc और atomic_dec उदाहरण के लिए संकेतबाहु गिनती के साथ लागू किया जा सकता है।

+0

इसके अलावा, सभी वैश्विक कार्य आइटम भी एक साथ निष्पादित नहीं होते हैं (वे ब्लॉक में किए जा सकते हैं जो अगले सेट से पहले पूरी तरह से खत्म हो जाना चाहिए), इसलिए प्रतीक्षा एक विकल्प नहीं है। – Dithermaster

+0

ठीक है, तो मेरा कर्नेल अनिवार्य रूप से उन परमाणु कार्यों को छोड़कर वही रहेगा जो आपने उल्लेख किया है? (कहना होगा, मैं अभी भी ओपनसीएल सिंक्रनाइज़ेशन के बारे में पढ़ रहा हूं, इसलिए यह समझ नहीं सकता कि ये कार्य क्या करते हैं)। और यदि एक सीपीयू पर चलाया जाता है तो कोड अपेक्षित जैसे कथन पर शाखा करेगा? – user5887077

1

इसे ओपनक्ल में कार्यान्वित किया जा सकता है, लेकिन दूसरे उत्तर की तरह, आप 2 धागे तक सीमित होने जा रहे हैं।

आपके फ़ंक्शन का मेरा संस्करण दो कार्य आइटम वाले एकल कार्य समूह के साथ बुलाया जाना चाहिए।

__kernel void test (__global float* A, __global float* B, __global float* C, __global float* D, int n, float C0, float D0) 
{ 
    int i; 
    int gid = get_global_id(0); 

    local float prevC; 
    local float prevD; 

    if (gid == 0) { 
     C[0] = prevC = C0; 
     D[0] = prevD = D0; 
    } 

    barrier(CLK_LOCAL_MEM_FENCE); 

    for (i=1;i<=n-1;i++) { 
     if(gid == 0){ 
      C[i] = function1(prevC); 
     }else if (gid == 1){ 
      D[i] = function2(prevC, prevD); 
     } 

     barrier(CLK_LOCAL_MEM_FENCE); 
     prevC = C[i]; 
     prevD = D[i]; 
    } 
} 

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

तो क्या GPU पर इसे चलाने का कोई मुद्दा है? समांतरता के लिए नहीं। आप 2 धागे से फंस गए हैं। लेकिन अगर आपको सी और डी के सभी मूल्यों की आवश्यकता नहीं है, तो संभवतः आप GPUs की तेज़ी से स्मृति के कारण एक महत्वपूर्ण गति देखेंगे।

यह सब मानते हैं कि function1 और function2 अत्यधिक जटिल नहीं हैं। यदि वे हैं, तो बस सीपीयू के साथ चिपके रहें - और शायद ओपनएमपी जैसी अन्य मल्टीप्रोसेसिंग तकनीक।

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