WinCNT

메모리 정렬 본문

게임 프로그래밍(학습 내용 정리)/자료구조와 알고리즘

메모리 정렬

WinCNT_SSS 2022. 1. 11. 14:06

데이터는 0과 1(Bit)의 모음이지만

기본적으로 비트 단위로 데이터를 다루는 일은 없다

우리가 다루는 데이터의 최소 단위Byte이다

 

CPU의 레지스터가 가져가는 데이터의 단위 = WORD(2Byte)였다(16비트)

참고로 WORD는 윈도우즈에서만 썼던 단위이며 리눅스에는 없다(short를 씀)

 

멀티 플랫폼으로 개발할 경우에는

다루는 단위들이 다 다르니 type 재정의를 하는 경우가 많음

 

일반적으로 데이터는 CPU, 캐시, RAM를 오고 간다

변수는 메모리에 보관하며 메모리 => 캐시 => CPU로 데이터가 이동(Move)할 때

특정 단위로 오고 가고 할 것이다

 

캐시 <=> 메모리에서 이동하는 데이터의 단위를 캐시 라인이라고 한다

(CPU <=> 메모리에서는 프레임(?)이라고 하는 것 같다...아마)

만일 메모리에 있는 1Byte의 데이터가 필요하다고 해도
캐시로 이동하는 데이터는 1Byte가 아니라 캐시 라인의 사이즈만큼 가져온다

캐시 라인의 크기는 캐시마다 다르다(하드웨어 종속)

요즘은 64bit의 배수가 많을 것이다(CPU 친화적이여야 효율이 좋으니까)

 

코드가 캐시 친화적일수록 성능은 향상될 것이다(게임 개발에는 특히 중요함)

캐시가 효율적으로 동작하려면, 캐시에 저장할 데이터가 지역성을 가져야 한다

지역성이란 데이터 접근이 시간적, 혹은 공간적으로 가깝게 일어나는 것을 의미한다

 

메모리 정렬

가져오는 데이터가 캐시 라인에 걸쳐 있으면 여러 귀찮은 처리가 늘어난다

 

그래서 그러한 상태를 방지하기 위해 구조체나 클래스의 사이즈를

2의 배수 바이트로 정렬하는데 이것을 메모리 정렬(=구조체 정렬)이라고 한다(1은 예외)

이러한 정렬을 통해 캐시 친화적인 데이터를 만들 수 있다

 

데이터 정렬은 코딩으로 명시적으로 지정(alignas)할 수 있지만 VS의 설정으로도 변경할 수 있다

VS에서 디폴트로 4byte의 단위가 되도록 되어 있는 것으로 보인다

그리고 alignof 키워드를 통해 해당 구조체의 메모리 정렬의 단위를 알 수 있다

#include <iostream>

using namespace std;

class A
{
    char a;
    int b;
};

class alignas(alignof(long double)) A2 {
    char a;
    int b;
};

class Empty {};
class alignas(64) Empty64 {};

int main()
{
    cout << "sizeof(A): " << sizeof(A) << endl;
    cout << "sizeof(Empty): " << sizeof(Empty) << endl;

    cout << "Alignment of"  "\n"
        "- char             : " << alignof(char) << "\n"
        "- pointer          : " << alignof(int*) << "\n"
        "- class A          : " << alignof(A) << "\n"
        "- class A2         : " << alignof(A2) << "\n"
        "- empty class      : " << alignof(Empty) << "\n"
        "- alignas(64) Empty: " << alignof(Empty64) << "\n";
}

 

메모리 정렬의 문제

네트워크에서 리틀 엔디안, 빅 엔디안 말고도 문제가 생길 수 있는 게 메모리 정렬이다

 

플랫폼마다 타입의 크기도 다른 것도 문제지만

메모리 정렬 방식이 다르면 같은 데이터를 주고 받아도 데이터를 잘못 해석할 수 있기 때문이다

 

그리고 구조체 자체로 보내면 패킷이 낭비 될 수 있다

그럴 때는 상황에 따라서 1byte로 재정렬하거나 시리얼라이즈를 쓰는 방식이 있다

시리얼라이즈
간단히 말해, 데이터를 바이트 상태로 저장해서 보내는 것을 의미한다
메모리 친화적 <=> CPU 친화적을 왔다 갔다 하는 것을 시리얼라이즈, 디시리얼라이즈라고 한다

 

C의 포인터의 3대장

댕글링

메모리 침범

특히나 제일 어려운 놈은

mcpy: size

string 카피 - 버퍼 잘못 써서 끝이 없어 계속 침범하는 경우, 진짜 엄청난 문제가 발생한다

등등...

 

참고 사이트

https://en.cppreference.com/w/cpp/language/alignof

 

alignof operator (since C++11) - cppreference.com

Queries alignment requirements of a type [edit] Syntax Returns a value of type std::size_t. [edit] Explanation Returns the alignment, in bytes, required for any instance of the type indicated by type-id, which is either complete object type, an array type

en.cppreference.com

https://copynull.tistory.com/241

 

[DirectX11] Warning - warning C4316 에러 문제

DirectX SDK 듀토리얼을 진행하면서 컴파일 과정에서 문제점을 하나 발견하게 되었습니다. 아래와 같이 컴파일시에 warning C4316 을 뱉어낸다는 문제점입니다. alignment error(C4316) 는 무엇인가? (MSDN 내

copynull.tistory.com

 

SSS