यह ऐप्पल के एलएलवीएम समर्थित बैक जीसीसी() में ओपनएमपी क्षेत्रों को बदलता है और इनके अंदर अंतर्निर्मित कॉल को संभालता है। इंटरमीडिएट पेड़ डंप की जांच करके समस्या का निदान किया जा सकता है (को 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 तर्क लेता है: यह भी विधानसभा कोड है कि एक गुजर -S
gcc
करने से प्राप्त कर सकते हैं में मानने योग्य है %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
क्षेत्र की गतिशील स्कॉइंग के कारण काम करेंगे।
ऐप्पल भविष्य में एक निश्चित कंपाइलर प्रदान करेगा, हो सकता है कि वे क्लैंग के साथ जीसीसी को बदलने की अपनी प्रतिबद्धता न दें।
-fopenmp -O1 (या उच्च, लेकिन नहीं -O0) का उपयोग करते समय मेरे लिए ठीक (ओएसएक्स 10.8.2, एक्सकोड 4.5, मैकपोर्ट जीसीसी 4.7.1) संकलित करता है: यह '___ gxx_personality_v0' गायब होने के साथ लिंकर त्रुटि देता है)। हालांकि कोड चलाने पर segfault पैदा करता है। -fopenmp के बिना संकलन करते समय, कोड किसी भी के लिए संकलित करता है, लेकिन फिर से sefafaults (-O0: बस त्रुटि को छोड़कर)। – Walter
@ वाल्टर धन्यवाद। segfault कोई समस्या नहीं है, कोड सिर्फ एक उदाहरण है - बेशक यह गलत है। आप जीसीसी 4.7.1 का उपयोग कर रहे हैं, इसलिए एक्सकोड कंपाइलर्स नहीं, है ना? क्या आप दी गई कमांडलाइन के साथ संकलित कर सकते हैं? अनुकूलन स्तर को बदलने में मदद नहीं मिली .. – angainor
यह 'llvm-gcc' कंपाइलर में एक बग है जो एक्सकोड जहाजों के साथ है। यह जीसीसी फ्रंटेंड के साथ एक एलएलवीएम कंपाइलर है। ओपनएमपी चरण कुछ बिल्टिन उत्पन्न कर रहा है जो बैकएंड पहचानने में सक्षम नहीं है। चूंकि एक्सकोड लगातार 'क्लैंग' के साथ जीसीसी को बदलने की ओर बढ़ रहा है, बग शायद कभी तय नहीं होगा। बस वास्तविक जीसीसी को स्रोत से या किसी अन्य विधि के माध्यम से स्थापित करें और इसे OpenMP कोड संकलित करने के लिए उपयोग करें। –