2017-05-10 8 views
5

g++ -fopenmp main.cpp द्वारा तर्क पारित नहीं कर सकता std::vector के अनिर्धारित संदर्भ के बारे में शिकायत करता है। इसे कैसे ठीक करें?ओपनएमपी कार्य: संदर्भ

मैंने उबंटू पर libomp-dev पैकेज स्थापित किया है।

main.cpp

#include<vector> 
#include<iostream> 

template<typename T, typename A> 
T recursiveSumBody(std::vector<T, A> &vec) { 
    T sum = 0; 
    #pragma omp task shared(sum) 
    { 
     sum = recursiveSumBody(vec); 
    } 
    return vec[0]; 
} 

int main() { 
    std::vector<int> a; 
    recursiveSumBody(a); 
    return 0; 
} 

अपरिभाषित संदर्भ

/tmp/ccTDECNm.o: In function `int recursiveSumBody<int, std::allocator<int> >(std::vector<int, std::allocator<int> >&) [clone ._omp_cpyfn.1]': 
main.cpp:(.text+0x148): undefined reference to `std::vector<int, std::allocator<int> >::vector(std::vector<int, std::allocator<int> > const&)' 
collect2: error: ld returned 1 exit status 
+0

किसी ने भी ऐसा कुछ देखा है? मुझे लगता है कि मैं 'std :: vector' की बजाय वेक्टर के 0 वें तत्व में पॉइंटर का उपयोग कर सकता हूं, लेकिन यदि संभव हो तो मैं सीधे पॉइंटर्स का उपयोग नहीं करूंगा। –

+0

ध्यान दें कि 'libomp-dev' एलएलवीएम ओपनएमपी रनटाइम है जो 'gomp' से असंबंधित है, जो' gcc' द्वारा बंडल ओपनएमपी रनटाइम है। – Zulan

उत्तर

3

समस्या को ठीक करने के लिए, आप मैन्युअल रूप से shared(sum, vec) निर्दिष्ट कर सकते हैं (दृढ़ता से यह मानते हुए कि आप इसे साझा करना चाहते हैं)।

दिलचस्प बात यह पुराने जीसीसी संस्करणों (जैसे 5.4.0) एक और अधिक उपयोगी त्रुटि संदेश दे:

error: 'vec' implicitly determined as 'firstprivate' has reference type 

इंटेल संकलक icpc 17.0.1 जबकि एक "internal error : 0_1855" देता है।

मैन्युअल रूप से firstprivate या private निर्दिष्ट करना - जो आपके मामले में कम समझ में आता है - परिणामस्वरूप अन्य वर्णनात्मक त्रुटियां होती हैं। नोट, जैसा कि हिस्टो इलिव ने अन्य टिप्पणियों में समझाया, firstprivate का अर्थ यह होगा कि वेक्टर की एक प्रति प्रत्येक धागे के लिए बनाई जाती है।

प्रति वर्तमान (4.5) मानक के रूप में:

एक अनाथ काम पैदा निर्माण में, यदि कोई डिफ़ॉल्ट खंड मौजूद है, औपचारिक संदर्भ द्वारा पारित तर्क firstprivate हैं।

मुझे लगता है कि यहां लागू होता है। इसके अलावा,

एक चर है कि एक firstprivate खंड में प्रकट होता है एक अधूरी C/C++ प्रकार है या एक अधूरी प्रकार के लिए एक संदर्भ नहीं होना चाहिए। यदि किसी कार्यशाला निर्माण पर firstprivate खंड में कोई सूची आइटम संदर्भ प्रकार है तो उसे टीम के सभी थ्रेड के लिए एक ही ऑब्जेक्ट से बांधना होगा।

यह एक खंड में प्रकट नहीं होता है, लेकिन मुझे लगता है कि यह अभी भी मानक साधन है।

अब मुझे नहीं लगता कि std::vector<T, A> टेम्पलेट के भीतर एक अपूर्ण प्रकार है, जब तक कि मुझे टेम्पलेट्स को तुरंत चालू करने के बारे में कुछ याद नहीं आ रहा है। तो मुझे लगता है कि आपका कोड मान्य होना चाहिए और यह दिया गया है कि प्रत्येक धागा सिर्फ उसी वस्तु से जुड़ा होता है, यह वास्तव में समझ में आता है।

तो मुझे लगता है कि यह हाल ही में gcc संस्करणों के साथ-साथ इंटेल कंपाइलर में एक बग है।ऐसा लगता है कि संकलक टेम्पलेट के लिए कुछ चीजों को तुरंत चालू करने में विफल रहता है।

इसके अलावा, जोड़ने:

if (0) std::vector<T, A> wtf = vec; 
समारोह की शुरुआत में

कोड संकलन और gcc साथ लिंक बनाता है। लेकिन अगर firstprivate मैन्युअल रूप से जोड़ा गया है, तो gcc शिकायत जारी रखता है कि 'vec' has incomplete type

पीएस .: डेटा साझाकरण विशेषता खंडों में संदर्भ प्रकारों को अनुमति देना ओपनएमपी 4.5 में जोड़ा गया था, यह पुराना जीसीसी एक अलग त्रुटि देता है।

+0

इंटेल 18.0 बी शिकायत करता है कि 'vec' एक अपूर्ण या संदर्भ प्रकार है यदि स्पष्ट रूप से' firstprivate' खंड में निर्दिष्ट किया गया है और अन्यथा समस्याओं के बिना संकलित करता है। अनंत रिकर्सन के कारण चलने पर प्रोग्राम क्रैश हो जाता है। –

1

समस्या गायब हो जाता है, तो आप भी एक साझा चर के रूप में vec घोषित:

#pragma omp task shared(sum, vec) 

ऐसा लगता है कि के लिए डिफ़ॉल्ट दृश्यता taskfirstprivate है, अपेक्षित के रूप में साझा नहीं किया जाएगा। आप this forum entry में अधिक जानकारी प्राप्त कर सकते हैं।

+0

कार्य कोड के टुकड़े हैं जो भविष्य के क्षण में (और संभवतः) निष्पादित कर सकते हैं। चूंकि उनको आमतौर पर समान चर में प्रदान किए गए इनपुट मानों के विभिन्न सेट पर काम करने की अपेक्षा की जाती है, इसलिए उन लोगों की अपेक्षा करना अधिक स्वाभाविक है कि वे 'पहले क्रेडिट' हों और साझा नहीं हों। एसिंक्रोनस बंद सोचो। –

+0

@HristoIliev मुझे संदर्भों पर 'फर्स्टप्राइवेट' के अर्थशास्त्र मिले, तुरंत सहज नहीं (सोचें 'ऑटो फर्स्टप्रिवेट = संदर्भ')। क्या आप इस बात से सहमत होंगे कि संदर्भ के लिए 'firstprivate' और' साझा' के बीच कोई अर्थपूर्ण अंतर नहीं है? – Zulan

+0

@ जुलान, संदर्भ कुछ स्मृति वस्तु के वैकल्पिक नाम हैं और पॉइंटर्स नहीं हैं, इसलिए 'निजी 'के अर्थशास्त्र के बाद,' प्रथम क्रेडिट ', पूरे ऑब्जेक्ट की एक प्रति बनाता है और न केवल इसके लिए एक और संदर्भ बनाता है। –

1

यह जीसीसी में एक बग जैसा दिखता है, जो std::vector<int, std::allocator<int> > के लिए एक प्रतिलिपि बनाने में विफल रहता है। ध्यान दें कि त्रुटि लिंकर से आती है और संकलन चरण के दौरान नहीं होती है। कॉपी कन्स्ट्रक्टर का उपयोग कॉपी फ़ंक्शन में किया जाता है जो उल्लिखित कार्य फ़ंक्शन के firstprivate पैरामीटर प्रारंभ करता है। संकलक को उत्पन्न करने के लिए मजबूर करना, उदा।

std::vector<int> a; 

बदलते

std::vector<int> a, b(a); 

समस्या फिक्स करने के लिए।

यहां एक और विस्तृत विवरण दिया गया है।

struct omp_data_a data_o; 

data_o.vec = vec; 
data_o.sum = &sum; 
GOMP_task(omp_fn_0, &data_o, omp_cpyfn_1, 32, 8, 1, 0, 0, 0); 

// --- outlined task body --- 
void omp_fn_0(struct omp_data_s & restrict data_i) 
{ 
    struct vector & vec = &data_i->vec; 
    *data_i->sum = recursiveSumBody<int>(vec); 
    std::vector<int>::~vector(vec); 
} 

// --- task firstprivate initialisation function --- 
void omp_cpyfn_1(struct omp_data_s *data_o, struct omp_data_a *data_i) 
{ 
    data_o->sum = data_i->sum; 
    struct vector &d40788 = data_i->vec; 
    struct vector *this = &data_o->vec; 
    std::vector<int>::vector(this, d40788); // <--- invocation of the copy constructor 
} 

omp_cpyfn_1 आदेश firstprivate तर्क आरंभ करने के लिए GOMP_task() से बुलाया जाता है: जीसीसी की तरह कुछ में निम्न कोड बदल देती है

#pragma omp task shared(sum) 
{ 
    sum = recursiveSumBody(vec); 
} 

। यह std::vector<int> की कॉपी कन्स्ट्रक्टर को कॉल करता है, क्योंकि (first-)private टी को टाइप टी के रूप में टाइप करने के संदर्भों का व्यवहार करता है, लेकिन कन्स्ट्रक्टर उत्पन्न नहीं होता है, इसलिए ऑब्जेक्ट कोड लिंक करने में विफल रहता है। यह शायद gimplifier कोड में एक बग है के रूप में प्रति निर्माता इस तरह जब एक गैर संदर्भ std::vector<T, A> निजीकरण हो जाता है बनाया जाता है, उदाहरण के लिए, कोड के साथ:

... 
std::vector<T, A> b; 
#pragma omp task shared(sum) 
{ 
    sum = recursiveSumBody(b); 
} 
... 

कोड इंटेल 18.0b साथ संकलित करता है। स्पष्ट रूप से vec को firstprivate के रूप में निर्दिष्ट करना जीसीसी के साथ उसी तरह टूट जाता है (आईसीपीसी vec एक अधूरा प्रकार होने के बारे में शिकायत करता है)। निम्नलिखित तरीके को इस्तेमाल किया जा सकता:

template<typename T, typename A> 
T recursiveSumBody(std::vector<T, A> &vec) { 
    T sum = 0; 
    std::vector<T, A> *ptr = &vec; 
    #pragma omp task shared(sum) 
    { 
     sum = recursiveSumBody(*ptr); 
    } 
    return vec[0]; 
} 

इस मामले ptr में सूचक है। इसका firstprivate संस्करण एक और सूचक है जो एक ही स्थान पर इंगित करता है, यानी वेक्टर उदाहरण। अर्थशास्त्र मूल कोड से अलग है क्योंकि यहां पूरे वेक्टर की कोई निजी प्रति नहीं बनाई गई है, बल्कि मूल वेक्टर का उपयोग किया जाता है।

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