일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- ASW(Application SpaceWarp)
- Windows Build
- Three(Two) Tone Shading
- Private Bytes
- OculusMotionVectorPass
- 개인 바이트
- working set
- C언어
- 가상 바이트
- Cartoon Rendering
- Cell Look
- Cell Shader
- URP
- Rim Light
- VR
- ColorGradingLutPass
- URP로 변경
- 작업 집합
- 게임 수학
- Virtual Byte
- 메모리 누수
- 벡터
- AppSW
- 프로그래밍 기초
- 3d
- Toon Shader
- Specular
- Today
- Total
WinCNT
메모리 정렬 본문
데이터는 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
https://copynull.tistory.com/241
SSS
'게임 프로그래밍(학습 내용 정리) > 자료구조와 알고리즘' 카테고리의 다른 글
자료 구조에 대해서(보충) (0) | 2022.01.18 |
---|---|
자료구조 - 그래프 (0) | 2022.01.17 |
자료 구조 - Hash (0) | 2022.01.03 |
페이지 교체와 알고리즘 (0) | 2022.01.03 |
B Tree와 Red-Black Tree (0) | 2021.12.27 |