2012-10-17 31 views
8

मैं निम्नलिखित समस्या पर ठोकर खाई है। नीचे दिए कोड स्निपेट किसी भी Xcode मैंने कोशिश की (4.4, 4,5)संकलन मैक ओएस एक्स शेर (memcpy और एसएसई intrinsics) पर ओपनएमपी के साथ विफल रहता है

#include <stdlib.h> 
#include <string.h> 
#include <emmintrin.h> 

int main(int argc, char *argv[]) 
{ 
    char *temp; 
#pragma omp parallel 
    { 
    __m128d v_a, v_ar; 
    memcpy(temp, argv[0], 10); 
    v_ar = _mm_shuffle_pd(v_a, v_a, _MM_SHUFFLE2 (0,1)); 
    } 
} 

कोड सिर्फ एक उदाहरण के रूप में प्रदान की जाती है और SEGFAULT जब आप इसे चलाते हैं साथ मैक ओएस एक्स पर जुड़ा नहीं है। मुद्दा यह है कि यह संकलित नहीं करता है। संकलन निम्न पंक्ति

/Applications/Xcode.app/Contents/Developer/usr/bin/gcc test.c -arch x86_64 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.7.sdk -mmacosx-version-min=10.7 -fopenmp 

Undefined symbols for architecture x86_64: 
"___builtin_ia32_shufpd", referenced from: 
    _main.omp_fn.0 in ccJM7RAw.o 
"___builtin_object_size", referenced from: 
    _main.omp_fn.0 in ccJM7RAw.o 
ld: symbol(s) not found for architecture x86_64 
collect2: ld returned 1 exit status 

कोड ठीक संकलित जब नहींgcc को -fopenmp ध्वज का उपयोग कर का उपयोग किया जाता है। अब, मैंने चारों ओर गुगल किया और memcpy से जुड़ी पहली समस्या का समाधान मिला, जो -fno-builtin, या -D_FORTIFY_SOURCE=0gcc तर्क सूची जोड़ रहा है। मैं दूसरी समस्या (एसएसई आंतरिक) को हल करने का प्रबंधन नहीं किया था।

क्या कोई इसे हल करने में मेरी सहायता कर सकता है? सवाल:

  • सबसे महत्वपूर्ण बात: कैसे "___builtin_ia32_shufpd" त्रुटि से छुटकारा पाने के लिए?
  • memcpy समस्या का कारण क्या है, और -D_FORTIFY_SOURCE=0 ध्वज अंततः क्या करता है?
+0

-fopenmp -O1 (या उच्च, लेकिन नहीं -O0) का उपयोग करते समय मेरे लिए ठीक (ओएसएक्स 10.8.2, एक्सकोड 4.5, मैकपोर्ट जीसीसी 4.7.1) संकलित करता है: यह '___ gxx_personality_v0' गायब होने के साथ लिंकर त्रुटि देता है)। हालांकि कोड चलाने पर segfault पैदा करता है। -fopenmp के बिना संकलन करते समय, कोड किसी भी के लिए संकलित करता है, लेकिन फिर से sefafaults (-O0: बस त्रुटि को छोड़कर)। – Walter

+0

@ वाल्टर धन्यवाद। segfault कोई समस्या नहीं है, कोड सिर्फ एक उदाहरण है - बेशक यह गलत है। आप जीसीसी 4.7.1 का उपयोग कर रहे हैं, इसलिए एक्सकोड कंपाइलर्स नहीं, है ना? क्या आप दी गई कमांडलाइन के साथ संकलित कर सकते हैं? अनुकूलन स्तर को बदलने में मदद नहीं मिली .. – angainor

+1

यह 'llvm-gcc' कंपाइलर में एक बग है जो एक्सकोड जहाजों के साथ है। यह जीसीसी फ्रंटेंड के साथ एक एलएलवीएम कंपाइलर है। ओपनएमपी चरण कुछ बिल्टिन उत्पन्न कर रहा है जो बैकएंड पहचानने में सक्षम नहीं है। चूंकि एक्सकोड लगातार 'क्लैंग' के साथ जीसीसी को बदलने की ओर बढ़ रहा है, बग शायद कभी तय नहीं होगा। बस वास्तविक जीसीसी को स्रोत से या किसी अन्य विधि के माध्यम से स्थापित करें और इसे OpenMP कोड संकलित करने के लिए उपयोग करें। –

उत्तर

15

यह ऐप्पल के एलएलवीएम समर्थित बैक जीसीसी() में ओपनएमपी क्षेत्रों को बदलता है और इनके अंदर अंतर्निर्मित कॉल को संभालता है। इंटरमीडिएट पेड़ डंप की जांच करके समस्या का निदान किया जा सकता है (को gcc पर तर्क देकर प्राप्त किया जा सकता है)। बिना OpenMP सक्षम निम्नलिखित अंतिम कोड प्रतिनिधित्व (test.c.016t.fap से) उत्पन्न होता है:

main (argc, argv) 
{ 
    D.6544 = __builtin_object_size (temp, 0); 
    D.6545 = __builtin_object_size (temp, 0); 
    D.6547 = __builtin___memcpy_chk (temp, D.6546, 10, D.6545); 
    D.6550 = __builtin_ia32_shufpd (v_a, v_a, 1); 
} 

यह कैसे संकलक सभी परिवर्तनों के बाद आंतरिक रूप से कोड को देखता है की एक सी की तरह प्रतिनिधित्व है। यह तब होता है जब असेंबली निर्देशों में बदल जाता है। (केवल उन पंक्तियों कि बनाया-इन का उल्लेख यहां दिए गए हैं)

OpenMP सक्षम होने के साथ समानांतर क्षेत्र, खुद समारोह में निकाला जाता है main.omp_fn.0:

main.omp_fn.0 (.omp_data_i) 
{ 
    void * (*<T4f6>) (void *, const <unnamed type> *, long unsigned int, long unsigned int) __builtin___memcpy_chk.21; 
    long unsigned int (*<T4f5>) (const <unnamed type> *, int) __builtin_object_size.20; 
    vector double (*<T6b5>) (vector double, vector double, int) __builtin_ia32_shufpd.23; 
    long unsigned int (*<T4f5>) (const <unnamed type> *, int) __builtin_object_size.19; 

    __builtin_object_size.19 = __builtin_object_size; 
    D.6587 = __builtin_object_size.19 (D.6603, 0); 
    __builtin_ia32_shufpd.23 = __builtin_ia32_shufpd; 
    D.6593 = __builtin_ia32_shufpd.23 (v_a, v_a, 1); 
    __builtin_object_size.20 = __builtin_object_size; 
    D.6588 = __builtin_object_size.20 (D.6605, 0); 
    __builtin___memcpy_chk.21 = __builtin___memcpy_chk; 
    D.6590 = __builtin___memcpy_chk.21 (D.6609, D.6589, 10, D.6588); 
} 

फिर मैं केवल कोड को छोड़ दिया है कि बिल्टिन को संदर्भित करता है। क्या स्पष्ट है (लेकिन इसका कारण मुझे तुरंत स्पष्ट नहीं है) यह है कि ओपनएमपी कोड trasnformer वास्तव में फ़ंक्शन पॉइंटर्स के माध्यम से सभी अंतर्निर्मित कॉल को कॉल करने पर जोर देता है। ये सूचक asignments:

__builtin_object_size.19 = __builtin_object_size; 
__builtin_ia32_shufpd.23 = __builtin_ia32_shufpd; 
__builtin_object_size.20 = __builtin_object_size; 
__builtin___memcpy_chk.21 = __builtin___memcpy_chk; 

प्रतीक हैं, जो वास्तव में प्रतीकों बल्कि ऐसे नाम हैं जो संकलक द्वारा विशेष उपचार प्राप्त नहीं कर रहे हैं करने के लिए बाहरी संदर्भ उत्पन्न करते हैं। लिंकर तब उन्हें हल करने का प्रयास करता है लेकिन कोड के साथ जुड़े किसी भी ऑब्जेक्ट फ़ाइलों में से __builtin_* नामों में से कोई भी नाम नहीं ढूंढ पा रहा है।

LBB2_1: 
    movapd -48(%rbp), %xmm0 
    movl $1, %eax 
    movaps %xmm0, -80(%rbp) 
    movaps -80(%rbp), %xmm1 
    movl %eax, %edi 
    callq ___builtin_ia32_shufpd 
    movapd %xmm0, -32(%rbp) 

यह मूल रूप से एक समारोह कॉल है कि 3 तर्क लेता है: यह भी विधानसभा कोड है कि एक गुजर -Sgcc करने से प्राप्त कर सकते हैं में मानने योग्य है %xmm0 में %eax और दो XMM बहस में एक पूर्णांक और %xmm1, साथ परिणाम %xmm0 में वापस किया जा रहा है (SysV AMD64 एबीआई फ़ंक्शन कॉलिंग सम्मेलन के अनुसार)। इसके विपरीत, -fopenmp बिना उत्पन्न कोड आंतरिक का एक निर्देश स्तर के विस्तार के रूप में यह हो जाता है है:

LBB1_3: 
    movapd -64(%rbp), %xmm0 
    shufpd $1, %xmm0, %xmm0 
    movapd %xmm0, -80(%rbp) 

क्या होता है जब आप पारित -D_FORTIFY_SOURCE=0 है कि memcpy "दृढ़" जाँच संस्करण से बदल नहीं है और इसके बजाय memcpy पर एक नियमित कॉल का उपयोग किया जाता है। यह object_size और __memcpy_chk के संदर्भों को समाप्त करता है लेकिन कॉल को ia32_shufpd अंतर्निहित में हटा नहीं सकता है।

यह स्पष्ट रूप से एक कंपाइलर बग है। क्या तुम सच में वास्तव में बहुत कोड को संकलित करने के एप्पल के जीसीसी का उपयोग करना चाहिए, तो एक अंतरिम समाधान एक बाहरी कार्य करने के लिए अपमानजनक कोड नहीं ले जाने के लिए किया जाएगा के रूप में बग जाहिरा तौर पर केवल कोड parallel क्षेत्रों से निकाला जाता है कि प्रभावित करता है:

void func(char *temp, char *argv0) 
{ 
    __m128d v_a, v_ar; 
    memcpy(temp, argv0, 10); 
    v_ar = _mm_shuffle_pd(v_a, v_a, _MM_SHUFFLE2 (0,1)); 
} 

int main(int argc, char *argv[]) 
{ 
    char *temp; 
#pragma omp parallel 
    { 
    func(temp, argv[0]); 
    } 
} 

parallel क्षेत्र में प्रवेश करने और निकालने के ऊपरी हिस्से की तुलना में एक अतिरिक्त फ़ंक्शन कॉल का ओवरहेड अस्वीकार्य है। आप func के अंदर ओपनएमपी प्रागमा का उपयोग कर सकते हैं - वे parallel क्षेत्र की गतिशील स्कॉइंग के कारण काम करेंगे।

ऐप्पल भविष्य में एक निश्चित कंपाइलर प्रदान करेगा, हो सकता है कि वे क्लैंग के साथ जीसीसी को बदलने की अपनी प्रतिबद्धता न दें।

+0

मुझे पूरी तरह से समझाते हुए धन्यवाद कि यह काम नहीं करेगा;) मैंने 'एक्सकोड' पर छोड़ दिया और मैक्सपोर्ट जीसीसी 4.7 स्थापित किया, जैसा कि पहले वाल्टर द्वारा उल्लेख किया गया था। यह कोई समस्या के साथ काम किया।एकमात्र परेशान बात यह है कि मैकपोर्ट्स का उपयोग करने के लिए आपको Xcode ** और ** कमांड लाइन टूल्स इंस्टॉल करने की आवश्यकता है, और आपको शीर्ष पर कंपाइलर्स का एक नया सेट मिलता है। बस वाह। – angainor