메모리 정렬 : alignof / alignas를 사용하는 방법? 명확하지 않습니다. alignof”alignment”를 반환하지만 “alignment”는 무엇입니까? 정렬

저는 지금 공유 메모리로 작업합니다.

나는 이해할 수 없다 alignof하고 alignas.

cppreference 가 명확하지 않습니다. alignof“alignment”를 반환하지만 “alignment”는 무엇입니까? 정렬 할 다음 블록을 위해 추가 할 바이트 수? 패딩 사이즈? 스택 오버플로 / 블로그 항목도 명확하지 않습니다.

사람이 명확하게 설명 할 수 alignofalignas?



답변

정렬은 값의 첫 번째 바이트가 저장 될 수있는 메모리 위치에 대한 제한입니다. (프로세서의 성능을 향상시키고 특정 정렬이있는 데이터에서만 작동하는 특정 명령어의 사용을 허용하는 데 필요합니다. 예를 들어 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.

더 정확하게 말하자면, “alignof”는 어떤 것이 정렬 될 때 가장 큰 2의 거듭 제곱을 반환합니다.

또한 alignof는 기본 데이터 유형에 대한 최소 정렬 요구 사항을 미리 알 수있는 좋은 방법입니다 (아마도 문자의 경우 1, 부동의 경우 4를 반환합니다).

여전히 합법적 :

alignas(alignof(float)) float SqDistance;

16으로 정렬 된 항목은 16의 배수 인 다음 사용 가능한 주소에 배치됩니다 (마지막으로 사용 된 주소에서 암시 적 패딩이있을 수 있음).


답변

정렬은 패딩이 아닙니다 (정렬 요구 사항을 충족하기 위해 패딩이 도입되는 경우도 있음). C ++ 유형의 intrisic 속성입니다. 표준에 넣으려면 ( 3.11[basic.align])

객체 유형에는 해당 유형의 객체가 할당 될 수있는 주소에 제한을 두는 정렬 요구 사항 (3.9.1, 3.9.2)이 있습니다. 정렬은 주어진 객체가 할당 될 수있는 연속 주소 사이의 바이트 수를 나타내는 구현 정의 정수 값입니다. 개체 유형은 해당 유형의 모든 개체에 대해 정렬 요구 사항을 부과합니다. 더 엄격한 정렬은 정렬 지정자 (7.6.2)를 사용하여 요청할 수 있습니다.


답변

각 유형에는 정렬 요구 사항이 있습니다. 일반적으로 이것은 데이터 유형의 주어진 구성원에 도달하기 위해 CPU가 둘 이상의 읽기 / 쓰기 액세스를 생성하지 않고도 유형의 변수에 효율적으로 액세스 할 수 있기 때문입니다. 또한 전체 변수를 효율적으로 복사 할 수 있습니다. alignof주어진 유형에 대한 정렬 요구 사항을 반환합니다.

alignas데이터 유형에 대한 정렬을 강제하는 데 사용됩니다 (해당 alignof데이터 유형이 반환 하는 것보다 덜 엄격하지 않은 한 ).


답변

정렬은 메모리 주소와 관련된 속성입니다. 주소 X가 Z에 정렬되면 x는 Z의 배수, 즉 X = Zn + 0입니다. 여기서 중요한 것은 Z가 항상 2의 제곱이라는 것입니다.

정렬은 메모리 주소의 속성으로, 2의 거듭 제곱 모듈로 숫자 주소로 표현됩니다. 예를 들어, 주소 0x0001103F 모듈로 4는 3입니다.이 주소는 4n + 3으로 정렬됩니다. 여기서 4는 선택한 전원을 나타냅니다. 2. 주소의 정렬은 선택한 2의 거듭 제곱에 따라 달라집니다. 동일한 주소 모듈로 8은 7입니다. 주소가 Xn + 0이면 X에 정렬된다고합니다.

위의 문은 Microsoft C ++ 참조에서 찾을 수 있습니다.

데이터 항목이 크기에 맞는 주소로 메모리에 저장되면 해당 데이터 항목은 자연스럽게 정렬 된다고합니다. 되고 그렇지 않으면 잘못 . 예를 들어, 크기가 4 바이트 인 정수 변수가 4로 정렬 된 주소에 저장되면 변수가 자연적으로 정렬된다고 말할 수 있습니다. 즉, 변수의 주소는 4의 배수 여야합니다.

컴파일러는 항상 오정렬을 피하기 위해 노력합니다. 단순 데이터 유형의 경우 주소는 변수 크기 (바이트)의 배수가되도록 선택됩니다. 컴파일러는 또한 자연적인 정렬과 접근을위한 구조의 경우 적절하게 채 웁니다. 여기에서 구조는 구조에있는 서로 다른 데이터 항목의 최대 크기로 정렬됩니다.

    struct abc
   {
        int a;
        char b;
   };

여기서 구조 abc는 1 바이트 (char 멤버의 크기)보다 분명히 큰 int 멤버의 크기 인 4에 정렬됩니다 .

정렬

이 지정자는 structure, class 등과 같은 사용자 정의 유형을 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
}