मेमोरी एलाइनमेंट कितना महत्वपूर्ण है? क्या यह अब भी मायने रखता है?


15

कुछ समय से, मैंने मेमोरी संरेखण के बारे में बहुत कुछ खोजा और पढ़ा है कि यह कैसे काम करता है और इसका उपयोग कैसे करना है। मेरे लिए अब तक का सबसे प्रासंगिक लेख यह है

लेकिन इसके साथ ही मेरे पास अभी भी इसके बारे में कुछ सवाल हैं:

  1. एम्बेडेड सिस्टम से बाहर, हमारे कंप्यूटर में अक्सर मेमोरी का एक बहुत बड़ा हिस्सा होता है, जो मेमोरी मैनेजमेंट को बहुत कम आलोचक बनाता है, मैं पूरी तरह से अनुकूलन में हूं, लेकिन अब, क्या यह वास्तव में कुछ ऐसा है जिससे हम उसी प्रोग्राम की तुलना कर सकते हैं या इसके बिना स्मृति को पुनर्व्यवस्थित और संरेखित किया जाता है?
  2. क्या मेमोरी एलाइनमेंट के अन्य फायदे हैं? मैंने कहीं पढ़ा है कि सीपीयू संरेखित मेमोरी के साथ बेहतर / तेज़ काम करता है क्योंकि यह प्रक्रिया के लिए कम निर्देश लेता है (यदि आप में से किसी के पास लेख / बेंचमार्क के लिए लिंक है?), उस मामले में, क्या अंतर वास्तव में महत्वपूर्ण है? क्या इन दोनों से ज्यादा फायदे हैं?
  3. अध्याय 5 में, लेख लिंक में, लेखक कहता है:

    खबरदार: C ++ में, जो क्लासेज़ दिखती हैं, वे इस नियम को तोड़ सकती हैं! (वे करते हैं या नहीं, यह निर्भर करता है कि बेस क्लास और वर्चुअल मेंबर फंक्शन कैसे लागू होते हैं, और कंपाइलर द्वारा भिन्न होता है।)

  4. लेख ज्यादातर संरचनाओं के बारे में बात करता है, लेकिन क्या स्थानीय चर घोषणा भी इस आवश्यकता से प्रभावित होती है?

    क्या आपके पास कोई विचार है कि मेमोरी संरेखण सी ++ में बिल्कुल कैसे काम करता है क्योंकि ऐसा लगता है कि कुछ अंतर हैं?

इस पूर्व प्रश्न में "संरेखण" शब्द शामिल है, लेकिन यह ऊपर दिए गए प्रश्नों का कोई उत्तर प्रदान नहीं करता है।


C ++ कंपाइलर ऐसा करने के लिए अधिक इच्छुक होते हैं (आपके लिए जहाँ यह आवश्यक या लाभदायक है, वहां पैडिंग सम्मिलित करें)। आपके द्वारा बताए गए लिंक से, आप जिन चीजों का उपयोग कर सकते हैं, उनके लिए अनुभाग 12 "टूल" देखें।
rwong

जवाबों:


11

हां, आपके डेटा के संरेखण और व्यवस्था दोनों प्रदर्शन में बड़ा अंतर ला सकते हैं, न केवल कुछ प्रतिशत बल्कि कुछ सैकड़ों से कई प्रतिशत तक।

यदि आप पर्याप्त लूप चलाते हैं, तो यह लूप, दो निर्देश द्रव्य लें।

.globl ASMDELAY
ASMDELAY:
    subs r0,r0,#1
    bne ASMDELAY
    bx lr

कैश के साथ और उसके बिना, और शाखा भविष्यवाणी में कैश के साथ और बिना संरेखण के साथ और आप एक महत्वपूर्ण राशि (टाइमर टिक) द्वारा उन दो निर्देशों के प्रदर्शन को भिन्न कर सकते हैं:

min      max      difference
00016DDE 003E025D 003C947F

एक प्रदर्शन परीक्षण आप बहुत आसानी से खुद कर सकते हैं। परीक्षण के तहत कोड के आसपास नोड्स जोड़ें या निकालें, समय की सटीक कार्य करें, कैश लाइनों के किनारों को छूने के लिए पते की एक विस्तृत श्रृंखला के साथ परीक्षण के तहत निर्देशों को स्थानांतरित करें, आदि।

डेटा एक्सेस के साथ एक ही तरह की बात। कुछ आर्किटेक्चर आपको बिना डेटा एक्सेस के (बिना उदाहरण के लिए पता 0x1001 पर एक 32 बिट रीड का प्रदर्शन) के बारे में शिकायत करते हैं। उनमें से कुछ आप गलती को अक्षम कर सकते हैं और प्रदर्शन को हिट कर सकते हैं। अन्य लोग जो बिना किसी पहुंच के अनुमति देते हैं, आपको केवल प्रदर्शन हिट मिलता है।

यह कभी-कभी "निर्देश" होता है लेकिन अधिकांश समय यह घड़ी / बस चक्र होता है।

विभिन्न लक्ष्यों के लिए gcc में मेम्पेकी कार्यान्वयन देखें। मान लीजिए कि आप एक संरचना की नकल कर रहे हैं जो 0x43 बाइट्स है, तो आप एक कार्यान्वयन पा सकते हैं जो एक बाइट को 0x42 से कॉपी करता है, फिर 0x40 बाइट को बड़े कुशल चंक्स में कॉपी करता है, फिर अंतिम 0x2 यह दो अलग-अलग बाइट्स के रूप में या 16 बिट ट्रांसफर के रूप में हो सकता है। संरेखण और लक्ष्य खेल में आते हैं यदि स्रोत और गंतव्य पते 0x1003 और 0x2003 एक ही संरेखण पर हैं, तो आप एक बाइट कर सकते हैं, फिर 0x40 बड़े विखंडू में तो 0x2, लेकिन यदि एक 0x1002 और दूसरा 0x1003 है, तो यह हो जाता है असली बदसूरत और असली धीमी।

ज्यादातर समय यह बस चक्र है। या तबादलों की संख्या बदतर। एआरएम की तरह 64 बिट वाइड डेटा बस के साथ एक प्रोसेसर लें, और 0x1004 पते पर चार शब्द स्थानांतरण (पढ़ें या लिखें, एलडीएम या एसटीएम) करें, यह एक शब्द संरेखित पता है, और पूरी तरह से कानूनी है, लेकिन अगर बस 64 है बिट्स वाइड यह संभावना है कि एकल निर्देश इस मामले में तीन स्थानान्तरण में बदल जाएगा 0x1004 पर 32 बिट, 0x1008 पर 64 बिट और 0x100A पर 32 बिट। लेकिन अगर आपके पास एक ही निर्देश था, लेकिन 0x1008 पते पर यह 0x1008 पते पर एक एकल चार शब्द हस्तांतरण कर सकता है। प्रत्येक हस्तांतरण में एक सेटअप समय जुड़ा हुआ है। तो 0x1004 से 0x1008 पते का अंतर अपने आप में कई बार तेज हो सकता है, यहां तक ​​कि / esp जब कैश का उपयोग करते हैं और सभी कैश हिट होते हैं।

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

आप अपना डेटा स्ट्रिपिंग समाप्त कर सकते हैं जैसे कि आप डेटा को संसाधित करते हैं जिससे आप बेदखली पैदा कर सकते हैं, आप वास्तविक बदकिस्मत प्राप्त कर सकते हैं और अपने कैश के केवल एक अंश का उपयोग करके समाप्त कर सकते हैं और जैसे ही आप इसके माध्यम से कूदते हैं डेटा का अगला बूँद एक पूर्व बूँद के साथ टकराता है । स्रोत कोड आदि में अपने डेटा या पुन: व्यवस्थित कार्यों को मिलाकर, आप टकराव पैदा कर सकते हैं या हटा सकते हैं, क्योंकि सभी कैश नहीं बनाए जाते हैं क्योंकि संकलक आपकी मदद करने के लिए नहीं जा रहा है। यहां तक ​​कि प्रदर्शन हिट या सुधार का पता लगाने के लिए आप पर है।

प्रदर्शन में सुधार करने के लिए हमने जो भी चीजें जोड़ी हैं, वे व्यापक डेटा busses, पाइपलाइनों, कैश, शाखा भविष्यवाणी, कई निष्पादन इकाइयों / रास्तों आदि में सबसे अधिक बार मदद करेंगे, लेकिन इन सभी में कमजोर स्पॉट होते हैं, जिनका जानबूझकर या आकस्मिक रूप से शोषण किया जा सकता है। इसके बारे में संकलक या पुस्तकालय बहुत कम कर सकते हैं, यदि आप प्रदर्शन में रुचि रखते हैं तो आपको ट्यून करने की आवश्यकता है और सबसे बड़ी ट्यूनिंग कारकों में से एक कोड और डेटा का संरेखण है, न कि केवल 32, 64, 128, 256 पर संरेखित करना। थोड़ी सी सीमाएँ, लेकिन यह भी कि जहाँ चीजें एक-दूसरे के सापेक्ष होती हैं, आप भारी मात्रा में उपयोग किए जाने वाले डेटा या फिर से उपयोग किए गए डेटा को उसी कैश तरीके से लैंड नहीं करना चाहते हैं, वे प्रत्येक अपना स्वयं का चाहते हैं। कम्पाइलर एक सुपर स्केलर आर्किटेक्चर के लिए निर्देशों के आदेश देने में मदद कर सकते हैं, एक-दूसरे के सापेक्ष निर्देशों को फिर से व्यवस्थित कर सकते हैं और न ही,

सबसे बड़ी निगरानी यह धारणा है कि प्रोसेसर अड़चन है। एक दशक या उससे अधिक के लिए सच नहीं है, प्रोसेसर को खिलाना समस्या है और यही वह जगह है जहां संरेखण प्रदर्शन हिट, कैश थ्रेशिंग, आदि जैसे मुद्दे खेलने में आते हैं। स्रोत कोड स्तर पर भी थोड़ा काम करने के साथ, एक संरचना में डेटा को फिर से व्यवस्थित करना, चर / संरचना की घोषणाओं का आदेश देना, स्रोत कोड के भीतर कार्यों का क्रम और डेटा को संरेखित करने के लिए थोड़ा अतिरिक्त कोड, कई बार प्रदर्शन में सुधार कर सकते हैं या अधिक।


+1 यदि केवल आपके अंतिम पैराग्राफ के लिए। मेमोरी बैंडविड्थ आज किसी के लिए सबसे महत्वपूर्ण मुद्दा है तेज कोड लिखने का प्रयास करना, न कि निर्देश गणना। और इसका मतलब है कि कैश मिस को कम करने के लिए चीजों का अनुकूलन, जो कई परिस्थितियों में संरेखण को संशोधित करके किया जा सकता है, बेहद महत्वपूर्ण है।
जूल्स

यदि आपका कोड और डेटा कैश्ड हो जाता है और आप उस डेटा पर पर्याप्त लूप / साइकल का प्रदर्शन करते हैं तो इंस्ट्रक्शन काउंट और जहां निर्देश एक लाईन लाइन के भीतर होते हैं, जहाँ वे जिस पाइप पर निर्भर होते हैं उसके सापेक्ष शाखाएँ भूमि के भीतर पहुँच जाती हैं, जो मायने रखती हैं। लेकिन ड्रामा और / या फ्लैश आधारित सिस्टम में आपको सबसे पहले प्रोसेसर को हाँ खिलाने की चिंता करनी होगी।
old_timer

15

हाँ, मेमोरी संरेखण अभी भी मायने रखता है।

कुछ प्रोसेसर वास्तव में गैर-संरेखित पते पर रीड नहीं कर सकते हैं। यदि आप ऐसे हार्डवेयर पर चल रहे हैं, और आप अपने पूर्णांक को गैर-संरेखित करते हैं, तो आपको उन्हें दो निर्देशों के साथ पढ़ने की संभावना है, विभिन्न बाइट्स को सही स्थानों पर लाने के लिए कुछ और निर्देशों का पालन करना होगा ताकि आप वास्तव में इसका उपयोग कर सकें। । इसलिए संरेखित डेटा प्रदर्शन-महत्वपूर्ण है।

अच्छी खबर यह है कि आपको वास्तव में परवाह नहीं है। लगभग किसी भी भाषा के लिए लगभग कोई भी कंपाइलर मशीन कोड का उत्पादन करेगा जो लक्ष्य प्रणाली के संरेखण आवश्यकताओं का सम्मान करता है। आपको केवल इसके बारे में सोचना शुरू करने की आवश्यकता है यदि आप अपने डेटा के इन-मेमोरी प्रतिनिधित्व का प्रत्यक्ष नियंत्रण ले रहे हैं, जो कि कहीं भी पास के रूप में अक्सर एक बार में आवश्यक नहीं था। यह जानना एक दिलचस्प बात है, और यह जानना महत्वपूर्ण है कि क्या आप विभिन्न संरचनाओं से स्मृति उपयोग को समझना चाहते हैं, और संभवत: अधिक कुशल होने के लिए चीजों को पुनर्गठित करें (गद्दी से बचने से)। लेकिन जब तक आपको उस तरह के नियंत्रण की आवश्यकता नहीं होती है (और अधिकांश प्रणालियों के लिए जो आप अभी नहीं करते हैं), तो आप खुशी से पूरे करियर के बारे में जान सकते हैं या नहीं।


1
विशेष रूप से, एआरएम गैर-संरेखित पहुंच का समर्थन नहीं करता है। और वह सीपीयू है जो लगभग सभी मोबाइल का उपयोग करता है।
Jan Hudec

यह भी ध्यान दें कि लिनक्स कुछ रनटाइम लागत पर गैर-संरेखित पहुंच का अनुकरण करता है, लेकिन विंडोज (सीई और फोन) गैर-संरेखित पहुंच पर प्रयास नहीं करते हैं और बस एप्लिकेशन को क्रैश कर देंगे।
Jan Hudec

2
हालांकि यह ज्यादातर सच है, ध्यान दें कि कुछ प्लेटफार्मों (x86 सहित) में अलग-अलग संरेखण की आवश्यकताएं होती हैं , जो इस बात पर निर्भर करती है कि कौन से निर्देशों का उपयोग किया जा रहा है , जो संकलक के लिए स्वयं काम करना आसान नहीं है, इसलिए आपको कभी-कभी यह सुनिश्चित करने के लिए पैड करने की आवश्यकता होती है कुछ संचालन (जैसे SSE निर्देश, जिनमें से कई को 16-बाइट संरेखण की आवश्यकता होती है) का उपयोग कुछ कार्यों के लिए किया जा सकता है। इसके अलावा, अतिरिक्त गद्दी जोड़ना ताकि एक ही कैश लाइन (16 बाइट्स) पर एक साथ अक्सर उपयोग किए जाने वाले दो आइटम कुछ मामलों में प्रदर्शन पर भारी प्रभाव डाल सकें, और स्वचालित भी नहीं है।
जूल्स

3

हां, यह अभी भी मायने रखता है, और कुछ प्रदर्शन महत्वपूर्ण एल्गोरिदम में, आप संकलक पर भरोसा नहीं कर सकते।

मैं केवल कुछ उदाहरणों को सूचीबद्ध करने जा रहा हूं:

  1. से इस उत्तर :

आम तौर पर, माइक्रोकोड मेमोरी से उचित 4-बाइट मात्रा प्राप्त करेगा, लेकिन अगर यह संरेखित नहीं है, तो इसे मेमोरी से दो 4-बाइट स्थान प्राप्त करना होगा और दो स्थानों के उपयुक्त बाइट्स से वांछित 4-बाइट मात्रा का पुनर्निर्माण करना होगा।

  1. निर्देशों के एसएसई सेट को विशेष संरेखण की आवश्यकता होती है। यदि यह पूरा नहीं होता है, तो आपको डेटा को अनलॉग्ड मेमोरी में लोड और स्टोर करने के लिए विशेष फ़ंक्शन का उपयोग करना होगा। इसका मतलब है कि दो अतिरिक्त निर्देश।

यदि आप एक प्रदर्शन महत्वपूर्ण एल्गोरिदम पर काम नहीं कर रहे हैं, तो बस मेमोरी संरेखण के बारे में भूल जाएं। यह वास्तव में सामान्य प्रोग्रामिंग के लिए आवश्यक नहीं है।


1

हम उन स्थितियों से बचते हैं जहां यह मायने रखता है। अगर यह मायने रखता है, तो यह मायने रखता है। द्विआधारी डेटा को संसाधित करते समय अनलगनेटेड डेटा उदाहरण के लिए होता था, जिसे आजकल टाला जाता है (लोग XML या JSON का बहुत उपयोग करते हैं)।

यदि आप किसी तरह पूर्णांक का एक अनलिंकड ऐरे बनाते हैं, तो एक विशिष्ट इंटेल प्रोसेसर पर आपका कोड प्रोसेसिंग उस एरे को संरेखित डेटा की तुलना में थोड़ा धीमा चलाएगा। एआरएम प्रोसेसर पर यह थोड़ा धीमा चलता है यदि आप कंपाइलर को डेटा अनलग्ड बताते हैं। यह प्रोसेसर मॉडल और ऑपरेटिंग सिस्टम पर निर्भर करता है, यदि आप संकलित डेटा का उपयोग किए बिना कंपाइलर का उपयोग करते हैं, तो यह एक भयानक, भयानक बहुत धीमा या गलत परिणाम दे सकता है।

C ++ का संदर्भ बताते हुए: C में, एक स्ट्रक्चर के सभी फील्ड्स को आरोही मेमोरी ऑर्डर में स्टोर किया जाना चाहिए। इसलिए यदि आपके पास चार / डबल / चार फ़ील्ड हैं और आप सब कुछ संरेखित करना चाहते हैं, तो आपके पास एक बाइट चार, सात बाइट अप्रयुक्त, आठ बाइट डबल, एक बाइट चार, सात बाइट अप्रयुक्त होंगे। C ++ स्ट्रक्चर्स में यह कम्पैटिबिलिटी के लिए समान है। लेकिन स्ट्रक्चर्स के लिए, कंपाइलर फ़ील्ड्स को रीऑर्डर कर सकता है, इसलिए आपके पास एक बाइट चार, एक बाइट चार, छह बाइट अप्रयुक्त, 8 बाइट डबल हो सकते हैं। 24 बाइट्स के बजाय 16 का उपयोग करना। सी संरचनाओं में, डेवलपर्स आमतौर पर उस स्थिति से बचते हैं और पहली जगह में एक अलग क्रम में फ़ील्ड होते हैं।


1
Unalign डेटा स्मृति में होता है। वे प्रोग्राम जिनमें उचित रूप से पैक्ड डेटा संरचनाएँ नहीं होती हैं, वे मूल्यों के उचित रूप से असंगत क्रम के लिए बड़े पैमाने पर प्रदर्शन दंड का सामना कर सकते हैं। उदाहरण के लिए, कोड में, एक कैश लाइन में दो मान बड़े पैमाने पर पाइपलाइन स्टॉल का कारण बनेंगे जब दो धागे एक ही समय में उन तक पहुंचते हैं (थ्रेड सुरक्षा मुद्दों की अनदेखी, निश्चित रूप से)।
ग्रेफेड

C ++ कंपाइलर केवल कुछ शर्तों के तहत फ़ील्ड्स को पुन: क्रमित कर सकता है, यदि आप उन नियमों से अवगत नहीं हैं, जो संभव नहीं हैं। उस शीर्ष पर, मुझे किसी भी C ++ कंपाइलर के बारे में पता नहीं है जो वास्तव में इस स्वतंत्रता का उपयोग करता है।
सोज़ेरड

1
मैंने कभी सी कंपाइलर री-ऑर्डर फ़ील्ड नहीं देखी। मैंने उदाहरण के लिए
चार्ट्स

1

उपरोक्त उत्तर में कई अच्छे बिंदु पहले से ही बताए गए हैं। बस गैर-एम्बेडेड सिस्टम में भी जोड़ने के लिए जो डेटा सर्च / माइनिंग से निपटने के लिए मेमोरी के मामलों का प्रदर्शन और एक्सेस टाइम इतना महत्वपूर्ण है कि एलाइनमेंट असेंबली कोड के अलावा अन्य के लिए भी लिखा जाता है।

मैं एक सार्थक पढ़ने की भी सलाह देता हूं: http://dewaele.org/~robbe/thesis/writing/references/what-every-programmer-should-know-about-memory.2007.pdf


1

मेमोरी एलाइनमेंट कितना महत्वपूर्ण है? क्या यह अब भी मायने रखता है?

हाँ। नहीं, यह निर्भर करता है।

एम्बेडेड सिस्टम से बाहर, हमारे कंप्यूटर में अक्सर मेमोरी का एक बहुत बड़ा हिस्सा होता है, जो मेमोरी मैनेजमेंट को बहुत कम आलोचक बनाता है, मैं पूरी तरह से अनुकूलन में हूं, लेकिन अब, क्या यह वास्तव में कुछ ऐसा है जिससे हम उसी प्रोग्राम की तुलना कर सकते हैं या इसके बिना स्मृति को पुनर्व्यवस्थित और संरेखित किया जाता है?

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

क्या मेमोरी एलाइनमेंट के अन्य फायदे हैं? मैंने कहीं पढ़ा है कि सीपीयू संरेखित मेमोरी के साथ बेहतर / तेज़ काम करता है क्योंकि यह प्रक्रिया के लिए कम निर्देश लेता है (यदि आप में से किसी के पास लेख / बेंचमार्क के लिए लिंक है?), उस मामले में, क्या अंतर वास्तव में महत्वपूर्ण है? क्या इन दोनों से ज्यादा फायदे हैं?

यह हो सकता है। यह संभवतः (संभवतः) कोड लिखते समय ध्यान में रखना है, लेकिन ज्यादातर मामलों में यह बस मायने नहीं रखना चाहिए (यानी, मैं अभी भी स्मृति फुटप्रिंट और एक्सेस फ़्रीक्वेंसी द्वारा अपने सदस्य चर की व्यवस्था करता हूं - जो कैशिंग को कम करना चाहिए - लेकिन मैं ऐसा करता हूं उपयोग में आसानी / पढ़ना और कोड को रीक्रिएट करना, कैशिंग उद्देश्यों के लिए नहीं)।

क्या आपके पास कोई विचार है कि मेमोरी संरेखण सी ++ में बिल्कुल कैसे काम करता है क्योंकि ऐसा लगता है कि कुछ अंतर हैं?

मैंने इसके बारे में पढ़ा जब एलायडफ सामान बाहर आया (सी ++ 11?) मैं इससे परेशान नहीं हुआ (मैं इन दिनों ज्यादातर डेस्कटॉप एप्लिकेशन और बैकेंड सर्वर डेवलपमेंट कर रहा हूं)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.