2011-10-17 13 views
10

हमारे शीर्षलेख हमारे अधिकांश structs (नेट और फ़ाइल I/O के लिए उपयोग किए जाने वाले) के आसपास #pragma pack(1) का उपयोग करते हैं। मैं समझता हूं कि यह 1 बाइट के संरेखण के लिए 8 बाइट्स के डिफ़ॉल्ट से structs के संरेखण को बदलता है।प्रगामा पैक (1) का उपयोग करते समय प्रदर्शन समस्याएं हैं?

मानते हैं कि सब कुछ 32-बिट लिनक्स (शायद विंडोज़ भी) में चलाया जाता है, क्या इस पैकिंग संरेखण से कोई प्रदर्शन हिट होती है?

मैं पुस्तकालयों के लिए पोर्टेबिलिटी के बारे में चिंतित नहीं हूं, लेकिन फ़ाइल और नेटवर्क I/O की संगतता के साथ अलग #pragma पैक, और प्रदर्शन समस्याओं के साथ अधिक।

+0

मुझे यह भी नहीं पता था कि जीसीसी '#pragma पैक' का समर्थन करता है। ऐसा नहीं है कि मैं अब इसका उपयोग करने जा रहा हूं। –

+0

@ लार्समैन हाँ विंडोज़ के कारण ऐसा करता है: http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas।एचटीएमएल – Nicolas

उत्तर

11

शब्द-संरेखित स्मृति पते पर होने पर मेमोरी एक्सेस सबसे तेज़ है। ,

struct sample { 
    char a; 
    int b; 
}; 

डिफ़ॉल्ट रूप से, जीसीसी गद्दी सम्मिलित करता है तो एक है पर 0 ऑफसेट, और ख पर 4 ऑफसेट है (शब्द गठबंधन): सबसे सरल उदाहरण निम्नलिखित struct (जो @Didier भी प्रयोग किया जाता) है। पैडिंग के बिना, बी शब्द-संरेखित नहीं है, और पहुंच धीमी है।

कितना धीमा?

  • 32-बिट x86 के लिए, Intel 64 and IA32 Architectures Software Developer's Manual के अनुसार:
    प्रोसेसर की आवश्यकता है दो स्मृति एक असंरेखित स्मृति पहुँच बनाने के लिए पहुँचता; गठबंधन के उपयोग के लिए केवल एक मेमोरी एक्सेस की आवश्यकता होती है। एक शब्द या डबलवर्ड ऑपरेंड जो 4-बाइट सीमा पार करता है या क्वाडवर्ड ऑपरेंड जो 8-बाइट सीमा पार करता है उसे असाइन नहीं माना जाता है और को एक्सेस के लिए दो अलग मेमोरी बस चक्र की आवश्यकता होती है।
    अधिकांश प्रदर्शन प्रश्नों के साथ, आपको यह देखने के लिए अपने आवेदन को बेंचमार्क करना होगा कि यह कितना मुद्दा है।
  • Wikipedia के अनुसार, एसएसई 2 जैसे x86 एक्सटेंशन शब्द संरेखण की आवश्यकता है।
  • कई अन्य आर्किटेक्चरों को शब्द संरेखण की आवश्यकता होती है (और यदि डेटा संरचनाएं शब्द-संरेखित नहीं हैं तो सिगबुस त्रुटियां उत्पन्न करेंगी)।

पोर्टेबिलिटी के बारे में: मुझे लगता है कि आप #pragma pack(1) उपयोग कर रहे हैं, ताकि आप विभिन्न compilers या प्लेटफार्मों पैकिंग structs अलग ढंग के बारे में चिंता किए बिना तार के पार और करने के लिए और डिस्क से structs भेज सकते हैं मान। यह मान्य है, हालांकि, ध्यान में रखने के लिए कुछ मुद्दे हैं:

  • यह छोटे एंडियन मुद्दों के विरुद्ध बड़े एंडियन मुद्दों को संभालने के लिए कुछ भी नहीं करता है। आप अपने structs में किसी भी इंक, हस्ताक्षरित इत्यादि पर htons फ़ंक्शन के परिवार को कॉल करके इन्हें संभाल सकते हैं।
  • मेरे अनुभव में, पैक कोड के साथ काम करना, आवेदन कोड में धारावाहिक structs बहुत मजेदार नहीं है। पिछली संगतता को तोड़ने के बिना उन्हें संशोधित करना और विस्तार करना बहुत मुश्किल है, और जैसा कि पहले से ही उल्लेख किया गया है, प्रदर्शन दंड हैं। प्रसंस्करण के लिए समेकित गैर-पैक, एक्स्टेंसिबल structs में अपने पैक किए गए, धारावाहिक structs की सामग्री को स्थानांतरित करने पर विचार करें, या Protocol Buffers (जिसमें C bindings है) की पूर्ण सीरियलाइजेशन लाइब्रेरी का उपयोग करने पर विचार करें।
+1

+1 और यह इंगित करने के लिए कि कुछ गैर-x86 आर्किटेक्चर वास्तव में * कुछ डेटा प्रकारों के लिए उचित संरेखण की आवश्यकता है। –

+0

एंडिननेस वास्तव में संभाला नहीं जाता है, लेकिन यह "ठीक है" क्योंकि हमारा पूरा बैकऑफिस लिनक्स संचालित है। मैं वास्तव में एक बेंचमार्क चलाऊंगा, और शायद इसे यहां रिपोर्ट कर सकता हूं। जवाब के लिए धन्यवाद। – Nicolas

3

जब आप एक struct की घोषणा, compilers के सबसे सुनिश्चित करें कि वे (आमतौर पर पैडिंग बाइट्स प्रकार के आकार की एक बहु कर रहे हैं) स्मृति में उचित पतों पर गठबंधन कर रहे हैं के सदस्यों के बीच पैडिंग बाइट्स डालें। यह संकलक को इन सदस्यों को प्राप्त करने में अनुकूलित पहुंच प्राप्त करने में सक्षम बनाता है।

#pragma pack(1) विशेष संरेखण के साथ संरचना सदस्यों को पैक करने के लिए संकलक को निर्देश देता है। 1 यहां संकलक को सदस्यों के बीच कोई पैडिंग डालने के लिए नहीं कहता है।

तो हाँ, एक निश्चित प्रदर्शन दंड है जब से तुम क्या यह स्वाभाविक रूप से प्रदर्शन optimization.Also के लिए क्या करना होगा परे कुछ करने के लिए संकलक मजबूर, कुछ प्लेटफॉर्म मांग है कि वस्तुओं विशिष्ट सीमा पर और unalighed का उपयोग कर गठबंधन किया संरचनाएं आपको सेगमेंटेशन दोष दे सकती हैं।

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

उदाहरण के लिए:

//push current alignment rules to internal stack and force 1-byte alignment boundary 
#pragma pack(push,1) 

/* definition of structures that require tight packing go in here */ 

//restore original alignment rules from stack  
#pragma pack(pop) 
+1

या बेहतर, केवल मौजूदा संरचना को चिह्नित करने के लिए जीसीसी के मूल ['संरेखित 'विशेषता] (http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Type-Attributes.html) का उपयोग करें। –

2

यह अंतर्निहित संरचना पर निर्भर करता है और जिस तरह से यह असंरेखित पतों को संभालती है।

86, शान से असंरेखित पतों संभालती है, हालांकि एक प्रदर्शन कीमत पर है, जबकि इस तरह के एआरएम के रूप में अन्य आर्किटेक्चर एक संरेखण गलती (SIGBUS) आह्वान कर सकते हैं, या "दौर" निकटतम सीमा को गलत संरेखित पता, में जो मामले अपने कोड होगा एक भयंकर तरीके से असफल हो जाओ।

नीचे की रेखा है, केवल तभी पैक करें जब आप सुनिश्चित हों कि अंतर्निहित आर्किटेक्चर अनचाहे पते को संभालेगा, और यदि नेटवर्क I/O की लागत प्रसंस्करण लागत से अधिक है।

+0

यह वास्तव में x86 है। – Nicolas

+0

आपका सुझाव क्या है, यदि डेटा एआरएम और एक्स 86 मशीन के बीच भेजा जाना है, तो मुझे किस पैक प्रारूप का उपयोग करना चाहिए? उत्कृष्ट उत्तर के लिए – Benny

6

हां। बिल्कुल वहाँ हैं।

उदाहरण के लिए, यदि आप एक struct को परिभाषित करता है, तो:

struct dumb { 
    char c; 
    int i; 
}; 

तो आप सदस्य मैं, सीपीयू धीमी कर दी है का उपयोग जब भी, क्योंकि 32 बिट मूल्य मैं एक देशी, गठबंधन तरह से सुलभ नहीं है। इसे सरल बनाने के लिए, कल्पना करें कि सीपीयू को स्मृति से 3 बाइट प्राप्त करना है, और फिर अगले स्थान से 1 अन्य बाइट को स्मृति से मूल्य को CPU रजिस्टरों में स्थानांतरित करना है।

0

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

0

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

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

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