मुझे किसी प्रोजेक्ट के लिए अनुकूलित नीयन कोड लिखने की आवश्यकता है और मैं असेंबली भाषा लिखने में पूरी तरह से खुश हूं, लेकिन पोर्टेबिलिटी/रखरखाव के लिए मैं नीयन इंस्टीटिक्स का उपयोग कर रहा हूं। इस कोड को यथासंभव तेज़ी से होने की आवश्यकता है, इसलिए मैं एआरएम ऑप्टिमाइज़ेशन में अपने अनुभव का सही ढंग से अंतराल निर्देशों और पाइप स्टालों से बचने के लिए उपयोग कर रहा हूं। कोई फर्क नहीं पड़ता कि मैं क्या करता हूं, जीसीसी मेरे खिलाफ काम करता है और स्टालों से भरा धीमा कोड बनाता है।जीसीसी को मेरे नीयन इंट्रिनिक्स को तोड़ने से कैसे रोकें?
क्या कोई जानता है कि जीसीसी किस तरह से बाहर निकलता है और केवल मेरे अंतर्निहित कोड को कोड में अनुवादित करता है?
यहां एक उदाहरण दिया गया है: मेरे पास एक साधारण लूप है जो फ़्लोटिंग पॉइंट मानों को अस्वीकार करता है और कॉपी करता है। यह स्मृति के लोड होने के लिए कुछ समय और निष्पादित करने के निर्देशों को अनुमति देने के लिए 4 समय के 4 सेट के साथ काम करता है। बहुत से रजिस्टरों को छोड़ दिया गया है, इसलिए चीजों को इतनी बुरी तरह उलझाने का कोई कारण नहीं है।
vld1.32 {d18-d19}, [r5]
vneg.f32 q9,q9 <-- GCC intentionally causes stalls
add r7,r7,#16
vld1.32 {d22-d23}, [r8]
add r5,r1,r4
vneg.f32 q11,q11 <-- all of my interleaving is undone (why?!!?)
add r8,r3,#256
vld1.32 {d20-d21}, [r10]
add r4,r1,r3
vneg.f32 q10,q10
add lr,r1,lr
vld1.32 {d16-d17}, [r9]
add ip,r1,ip
vneg.f32 q8,q8
और जानकारी:: Raspbian
- जीसीसी 4.9.2:
-c -fPIE -march=armv7-a -Wall -O3 -mfloat-abi=hard -mfpu=neon
जब
float32x4_t f32_0, f32_1, f32_2, f32_3;
int x;
for (x=0; x<n-15; x+=16)
{
f32_0 = vld1q_f32(&s[x]);
f32_1 = vld1q_f32(&s[x+4]);
f32_2 = vld1q_f32(&s[x+8]);
f32_3 = vld1q_f32(&s[x+12]);
__builtin_prefetch(&s[x+64]);
f32_0 = vnegq_f32(f32_0);
f32_1 = vnegq_f32(f32_1);
f32_2 = vnegq_f32(f32_2);
f32_3 = vnegq_f32(f32_3);
vst1q_f32(&d[x], f32_0);
vst1q_f32(&d[x+4], f32_1);
vst1q_f32(&d[x+8], f32_2);
vst1q_f32(&d[x+12], f32_3);
}
इस कोड उत्पन्न है मैं वें लिखता हूँ एएसएम कोड में ई लूप बिल्कुल मेरे इंट्रिनिक्स के रूप में पैटर्न किया गया है (कुछ मुफ्त एआरएम चक्र प्राप्त करने के लिए अतिरिक्त स्रोत/dest रजिस्टरों का उपयोग किए बिना), यह अभी भी जीसीसी के कोड से तेज़ है।
अद्यतन: मैं जेम्स के उत्तर की सराहना करता हूं, लेकिन चीजों की योजना में, यह वास्तव में समस्या से मदद नहीं करता है। मेरे कार्यों का सबसे सरल कॉर्टेक्स-ए 7 विकल्प के साथ थोड़ा बेहतर प्रदर्शन करता है, लेकिन बहुमत में कोई बदलाव नहीं आया। दुखी सच यह है कि जीसीसी का आंतरिक ज्ञान का अनुकूलन बहुत अच्छा नहीं है। जब मैंने कुछ साल पहले माइक्रोसॉफ्ट एआरएम कंपाइलर के साथ काम किया था, तो लगातार एनईओएन इंट्रिनिक्स के लिए अच्छी तरह तैयार किए गए आउटपुट का निर्माण हुआ, जबकि जीसीसी लगातार ठोकर खाई। जीसीसी 4.9.एक्स के साथ, कुछ भी नहीं बदला है। मैं निश्चित रूप से जीसीसी की एफओएसएस प्रकृति और अधिक जीएनयू प्रयास की सराहना करता हूं, लेकिन इंटेल, माइक्रोसॉफ्ट या यहां तक कि एआरएम के कंपाइलर्स के रूप में यह अच्छा काम नहीं करता है।
मुझे कोई जानकारी नहीं है। एक कंपाइलर बग या सीधे असेंबली लिखने पर विचार करें। आम तौर पर, आंतरिक अंतर्निहित कार्यों की तरह इंट्रिनिक्स को संभाला जाता है। इस बात की कोई गारंटी नहीं है कि संकलक उसी क्रम में निर्देशों को उत्सर्जित करता है जिसमें अंतर्निहित लिखा गया है। – fuz
उपयोगी जानकारी जीसीसी का संस्करण होगा जिसका उपयोग आप सीपीयू के साथ कर रहे हैं (-mcpu = ??? या -mtune = ???) के लिए। आम तौर पर जवाब यह है, क्योंकि जीसीसी का मानना है कि इंटरलेविंग के परिणामस्वरूप आप इंटरसेविंग के बेहतर प्रोसेसर उपयोग में परिणामों का उपयोग कर रहे हैं। एक और सवाल यह होगा कि आप कैसे पता लगा रहे हैं कि स्टॉल हैं? –
@ जेम्स कंपाइलर जानकारी के लिए ऊपर देखें। मैंने अपनी शैली में एएसएम कोड लिखा है और यह जीसीसी के कोड से तेज़ है। लक्ष्य सीपीयू कॉर्टेक्स-ए 7 है। – BitBank