मेमोरी एलाइनमेंट: एलायफ / एलायंस का उपयोग कैसे करें?


82

मैं अभी साझा मेमोरी के साथ काम करता हूं।

मैं नहीं समझ सकता alignofऔर alignas

cppreference स्पष्ट नहीं है: alignof"संरेखण" देता है लेकिन "संरेखण" क्या है? अगले ब्लॉक को संरेखित करने के लिए जोड़ने के लिए बाइट्स की संख्या? गद्देदार आकार? ढेर अतिप्रवाह / ब्लॉग प्रविष्टियाँ अस्पष्ट भी हैं।

क्या कोई स्पष्ट रूप से alignofऔर समझा सकता है alignas?


1
cppreference एक ट्यूटोरियल के बजाय एक संदर्भ बनने की कोशिश कर रहा है
Cub21

1
@ कुब्बी: आप cplusplus.com पर भी चेक कर सकते हैं, डिबेट विच साइट बेहतर है, कुछ विषयों के लिए कॉस्प्लस बेहतर है, अन्य cppreference के लिए बेहतर है, मैंने पाया कि दोनों साइट निश्चित समय eonugh नहीं हैं
CoffeDeveloper

2
@DarioOO मैं केवल इस बात का जवाब दे रहा था कि alignofपृष्ठ पर संरेखण की अवधारणा की व्याख्या क्यों नहीं करता है (यह अब-कार्य प्रगति पृष्ठ पर है )। मैं नहीं देखता कि कैसे cplusplus.com प्रासंगिक है।
क्यूबाई

जवाबों:


82

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

16 के संरेखण का मतलब है कि स्मृति पते जो कि 16 के कई हैं, केवल मान्य पते हैं।

alignas

बाइट्स की आवश्यक संख्या के लिए बल संरेखण। आप केवल 2: 1, 2, 4, 8, 16, 32, 64, 128, ... की शक्तियों के लिए संरेखित कर सकते हैं।

#include <cstdlib>
#include <iostream>

int main() {
    alignas(16) int a[4];
    alignas(1024) int b[4];
    printf("%p\n", a);
    printf("%p", b);
}

उदाहरण आउटपुट:

0xbfa493e0
0xbfa49000  // note how many more "zeros" now.
// binary equivalent
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2

दूसरा कीवर्ड

alignof

बहुत सुविधाजनक है, आप ऐसा कुछ नहीं कर सकते

int a[4];
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error

लेकिन आप कर सकते हैं

assert(alignof(a) == 16);
assert(alignof(b) == 1024);

ध्यान दें कि वास्तव में यह एक सरल "%" (मापांक) ऑपरेशन की तुलना में अधिक सख्त है। वास्तव में हम जानते हैं कि 1024 बाइट्स से जुड़ी कुछ चीजों को 1, 2, 4, 8 बाइट्स से जोड़ दिया जाता है

 assert(alignof(b) == 32); // fail.

तो अधिक सटीक होने के लिए, "एलायडॉफ़" 2 की सबसे बड़ी शक्ति देता है जो कि कुछ संरेखित है।

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

अभी भी कानूनी:

alignas(alignof(float)) float SqDistance;

16 के संरेखण के साथ कुछ तब अगले उपलब्ध पते पर रखा जाएगा जो कि 16 का गुणक है (अंतिम उपयोग किए गए पते से एक अंतर्निहित पैडिंग हो सकती है)।


10
इसके विपरीत sizeof, alignofकेवल एक पर लागू किया जा सकता है type-id
कभी नहीं

है alignof()(और समकक्ष alignas()) संकलन समय पर मूल्यांकन किया जाता है, इसलिए कोई क्रम भूमि के ऊपर?
३०'१४ को बकवास

नहीं। यह संभव नहीं है, कंपाइलर बहुत कम मामलों में अनुकूलन के रूप में ऐसा कर सकता है, लेकिन सामान्य तौर पर यह नहीं पता होगा कि 2 कार्यों का मूल्यांकन करने से पहले मेमोरी एड्रेस को कैसे संरेखित किया जाता है। मेरे उदाहरण से उत्पन्न विधानसभा को देखें: goo.gl/ZbemBF
CoffeDeveloper

1
@Serthy स्पष्ट करने के alignof लिए एक संकलन-समय स्थिर है। alignasनहीं है, और new(मानक की आवश्यकता) के अपने कार्यान्वयन के द्वारा समर्थित किया जाना चाहिए , या एक कस्टम अनुसूचित जनजाति के आवंटनकर्ता द्वारा
इदियाकापी

अच्छा जवाब है, लेकिन इसे structऔर उस संरचना के सदस्यों के उपचार की आवश्यकता है static। क्लैंग जैसे संकलकों के तहत, alignasबहुत अधिक बारीकियों से बाहर निकल रहा है __attribute__((aligned))
jww

11

संरेखण पैडिंग नहीं है (हालांकि संरेखण आवश्यकताओं को पूरा करने के लिए पैडिंग को कभी-कभी पेश किया जाता है)। यह C ++ प्रकार की एक आंतरिक संपत्ति है। इसे मानक रूप में रखने के लिए ( 3.11[basic.align])

ऑब्जेक्ट प्रकारों की संरेखण आवश्यकताएँ (3.9.1, 3.9.2) उन पतों पर प्रतिबंध लगाती हैं जिन पर उस प्रकार की कोई वस्तु आवंटित की जा सकती है। एक संरेखण एक कार्यान्वयन-परिभाषित पूर्णांक मान है जो क्रमिक बाइट्स के बीच बाइट्स की संख्या का प्रतिनिधित्व करता है जिस पर किसी दिए गए ऑब्जेक्ट को आवंटित किया जा सकता है। एक वस्तु प्रकार उस प्रकार की प्रत्येक वस्तु पर एक संरेखण आवश्यकता लगाता है; संरेखण विनिर्देशक (7.6.2) का उपयोग करके सख्त संरेखण का अनुरोध किया जा सकता है।


1
बहुत ही रोचक। क्या आप कुछ उदाहरण देना चाहेंगे? संरेखित करता है (संरचना X) == आकार (संरचना X)? क्यों नहीं ?
ऑफिरमो

1
@ ऑर्फो नो, सिवाय कॉन्फिडेंस के: struct X { char a; char b}साइज 2 और एलाइनमेंट की जरूरत 1 है, साने सिस्टम पर (इसे किसी भी पते पर आबंटित किया जा सकता है क्योंकि किसी भी पते पर एक
चार्ट

1 का संरेखण पुनरावृत्ति ???? ओह, मैं समझ गया: मैंने सोचा था कि संरेखण हमेशा "प्राकृतिक" 32 बिट्स / 64 बिट्स की सीमाओं पर था लेकिन स्पष्ट रूप से नहीं। यह चीजें समझाती हैं ... इसलिए सामान्य मशीनों पर, संरेखण () परिणाम हमेशा अधिकतम 4 (32 बिट्स) या 8 (64 बिट्स) होगा I सही?
ओप्पोर्मो

@ ऑफीर्मो "नेचुरल" एल्डोफ़ अधिकतम होगा alignof(std::max_align_t), जो 16मेरे लिनक्स पर है (फिर चाहे वह संकलन -m32 या -m64 हो), लेकिन आप इसे कड़े बना सकते हैंalignas
Cubbi

7

प्रत्येक प्रकार की एक संरेखण आवश्यकता होती है। आम तौर पर, यह प्रकार का वैरिएबल कुशलता से एक्सेस किया जा सकता है, बिना सीपीयू के किसी भी दिए गए सदस्य तक पहुंचने के लिए एक से अधिक रीड / राइट एक्सेस उत्पन्न करने का कारण बनता है। इसके अलावा, यह पूरे चर की कुशल नकल भी सुनिश्चित करता है। alignofदिए गए प्रकार के लिए संरेखण आवश्यकता को वापस करेगा।

alignasडेटाटाइप पर एक संरेखण को बाध्य करने के लिए उपयोग किया जाता है (इसलिए जब तक यह कम कठोर न हो कि क्या alignofकहा गया डेटाटाइप वापस आ जाएगा)


3

संरेखण स्मृति पते से संबंधित एक संपत्ति है। बस हम यह कह सकते हैं कि यदि कोई पता X Z से संरेखित है तो x, Z का एक गुणक है, जो कि X = Zn + 0 है। यहाँ महत्वपूर्ण बात Z हमेशा 2 की शक्ति है।

संरेखण स्मृति पते की एक संपत्ति है, जिसे संख्यात्मक पता modulo 2 की शक्ति के रूप में व्यक्त किया जाता है। उदाहरण के लिए, पता 0x0001103F modulo 4 है। यह पता 4n + 3 से संरेखित किया जाता है, जहां 4 संकेतित शक्ति को दर्शाता है। 2. एक एड्रेस का अलाइनमेंट चुने गए पॉवर पर निर्भर करता है। एक ही एड्रेस मोडुलो 8 है। 7. एक एड्रेस को X से एलाइन किया जाना कहा जाता है अगर उसका एलाइनमेंट Xn + 0 है।

उपरोक्त कथन Microsoft c ++ संदर्भ पर पाया जाता है।

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

संकलक हमेशा गलतफहमी से बचने की कोशिश करता है। सरल डेटाटिप्स के लिए पतों को इस तरह चुना जाता है कि यह बाइट्स में चर के आकार का एक गुणक हो। प्राकृतिक संरेखण और पहुंच के लिए संरचनाओं के मामले में उपयुक्तता भी उपयुक्त है। संरचना संरचना में अलग-अलग डेटा आइटमों के आकारों के अधिकतम के लिए गठबंधन की जाएगी।

    struct abc
   {
        int a;
        char b;
   };

यहां संरचना एबीसी 4 से जुड़ा हुआ है जो कि अंतर सदस्य का आकार है जो स्पष्ट रूप से 1 बाइट (चार सदस्य का आकार) से अधिक है।

संरेखित करें

इस विनिर्देशन का उपयोग उपयोगकर्ता परिभाषित प्रकारों जैसे संरचना, वर्ग आदि को एक विशेष मान के लिए संरेखित करने के लिए किया जाता है जो 2 की शक्ति है।

संरेखित करें

यह मूल्य प्राप्त करने के लिए एक प्रकार का ऑपरेटर है जिसके लिए संरचना या वर्ग प्रकार गठबंधन किया जाता है। उदाहरण के लिए:

#include <iostream>
struct alignas(16) Bar
{
    int i; // 4 bytes
    int n; // 4 bytes
    short s; // 2 bytes
};
int main()
{
    std::cout << alignof(Bar) << std::endl; // output: 16
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.