Thinking Different




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





alignment error(C4316) 는 무엇인가?



(MSDN 내용중에서)



위 경고는 __declspec(align(byte))로 정렬되야 하는 데이터를 멤버로 가지거나, 할당할 때 생기는 경고다.

오류나는 부분을 점검해보면 XMMATRIX 변수부분에 대한 에러가 발생이 되는데 이를 따라가 보면 다음과 같다




정의 부분을 보면 __declspec(align(16)) 으로 16 바이트 정렬을 사용한다고 명시하고 있는데, 이는 자주 사용되는 데이터를 특정 프로세서 캐시라인 크기로 정렬하여 한꺼번에 계산하여 CPU 캐시 처리 성능을 높혀주는 것이다.


게임 프로그래밍에 사용되는 행열 연산을 고속으로 한꺼번에 처리하기 위해서 SSE라는 새로운 명령어 집합이 생겨나게 되면서 이러한 바이트 정렬 연산이 사용되게 된 것이다.


그런데 이는 스택에서는 별 문제가 되지 않지만 HEAP에 할당할때에만 문제가 발생한다는 것이다. Visual Studio에 내장되어 사용되는 new 의 경우 8byte align 으로 할당되므로 우리는 16byte align으로 new, delete 를 새로 만들어서 사용가능하도록 보장해 주어야 된다. (MSDN 에서도 새롭게 _aligned_malloc 와 _aligned_free를 이용하여 new, delete 할당자를 만들라고 설명하고 있다)


즉, 'Visual studio 에서 제공되는 기본 new, delete 명령어는 8byte 정렬을 사용하는데, XMMATRIX 변수의 경우 16byte 정렬을 사용하도록 명시하고 있으므로, HEAP 할당시에 컴파일러는 보장하지 않을것이니 사용자 너가 알아서 처리해라' 라는 말이다.






C4316 해결하지 않으면?

CPU에서 SSE 명령어 연산을 처리할때 정렬되는 데이터를 안전하게 보장받을 수 없음(뒤죽박죽이 되버릴 가능성이 아주 높음




해결방법


new, delete 를 _aligned_malloc, _aligned_free 를 사용하여 재정의하여 사용하도록 하자.



AlignedAllocationPolicy.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#pragma once
 
// warning C4316 처리용
template<size_t T>
class AlignedAllocationPolicy
{
public:
    static void* operator new(size_t size)
    {
        return _aligned_malloc(size, T);
    }
 
    static void operator delete(void* memory)
    {
        _aligned_free(memory);
    }
};
cs

위와 같이 재정의 템플릿을 생성한 다음 아래와 같이 사용하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#pragma once
 
class CameraClass : public AlignedAllocationPolicy<16>
{
public:
    CameraClass();
    CameraClass(const CameraClass&);
    ~CameraClass();
 
    void SetPosition(floatfloatfloat);
    void SetRotation(floatfloatfloat);
 
    XMFLOAT3 GetPosition();
    XMFLOAT3 GetRotation();
 
    void Render();
    void GetViewMatrix(XMMATRIX&);
 
private:
    XMFLOAT3 m_position;
    XMFLOAT3 m_rotation;
    XMMATRIX m_viewMatrix;
};
cs





참고 사이트

1. Compiler Warning (level 3) C4316 (for MSDN)

2. C4316 alignment error 해결

3. __declspec(align(x)) 바이트 정렬

4. MMX, SSE란 무엇인가?