게임 엔진 아키텍쳐
Chapter3
게임을 위한
소프트웨어 엔지니어링
기초
초중급 게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 1
2.
3.1.1 객체지향 프로그래밍
초중급게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 2
1. 클래스와 객체 개념
•클래스(Class): 데이터와 코드를 묶은 추상적 개념
•객체(Object, 인스턴스): 클래스를 기반으로 생성된 실제 존재하는 개체
•예: 개라는 클래스가 있다면 스누피는 개 클래스의 객체
2. 캡슐화 (Encapsulation)
•객체 내부 상태와 구현을 숨기고, 인터페이스만 공개하는 개념
•클래스 사용자는 내부 동작을 몰라도 인터페이스만 알면 사용 가능
•장점: 논리적으로 일관된 상태 유지, 유지보수 용이
3. 상속 (Inheritance)
•기존 클래스를 확장하여 새로운 클래스를 생성하는 개념
•부모 클래스 → 자식 클래스 관계
•UML에서 사각형 + 속이 빈 삼각형 화살표로 표현
•예: Circle 클래스가 Shape 클래스를 상속
4. 다중 상속 (Multiple Inheritance)
•한 클래스가 여러 부모 클래스를 가질 수 있는 개념
•문제점: 다이아몬드 문제 발생 (부모 클래스가 중복될 가능성)
•C++ 해결법: 가상 상속(Virtual Inheritance) 사용
3.
다형성
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 3
3.1.1.4 다형성 (Polymorphism)
•서로 다른 객체들을 하나의 공통 인터페이스로 다룰 수 있는 개념
•코드 관점에서 서로 다른 객체를 동일한 형태로 취급 가능
1. 정적 접근 방식 (switch문 활용)
•각 도형의 형태를 switch문으로 구분하여 그리는 방식
•새로운 도형을 추가할 때 코드 수정이 필요하여 유지보수가 어려움
2. 동적 접근 방식 (가상 함수 활용)
•Shape 클래스를 만들고, 각 도형 클래스는 Shape을 상속
•Draw() 가상 함수를 선언하여 각 도형이 원하는 방식으로 구현
장점: 도형을 추가할 때 기존 코드 변경 없이 확장 가능
4.
합성과 집합
초중급 게임개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 4
3.1.1.5 합성과 집합 (Composition & Aggregation)
•여러 객체를 조합하여 복잡한 기능을 구현하는 방법
•합성 (Composition): 클래스 간 "has-a" 관계 형성 (예: 자동차는 엔진을
포함)
•집합 (Aggregation): "uses-a" 관계 형성 (예: 우주선은 연료탱크를 사용)
• 유지보수 용이
• 코드 간결화
• 재사용성과 디버깅 효율 증가
5.
C++ 표준화 요약
초중급게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 5
1. C++ 표준화 역사
•1979년 개발, 1983년 C++로 명명
•1998년 국제 표준화 완료
•이후 주기적으로 새로운 기능 추가 및 개선
2. 주요 C++ 버전 및 특징
•C++98 (1998년 표준화): 최초의 공식 표준
•C++03 (2003년 발표): C++98의 문제 수정 및 개선
•C++11 (2011년 승인): 강력한 기능 추가
• 널 포인터용 nullptr 도입
• 자동 타입 추론을 위한 auto, decltype 키워드 추가
• 후위 리턴 타입 문법 추가
• 가상 함수 재정의를 명확히 하는 override, final
키워드 추가
• 컴파일 타임 상수 계산을 위한 constexpr 키워드
도입
• 람다 함수 지원
• rvalue 참조 및 이동语의 도입
• 표준 속성 지정자 추가
•C++14 (2014년 승인): C++11 개선
•auto를 함수 리턴 타입으로 사용 가능
•제네릭 람다 지원
•이진 리터럴 표기 지원
•숫자 구분 기호 추가
•C++17 (2017년 승인): 기능 삭제 및 개선
•register 키워드 제거
•auto_ptr 스마트 포인터 제거
•복사 생략 보장
•noexcept 명세 강화
•UTF-8 문자 리터럴 추가
•구조적 바인딩 도입
•switch 문에서 의도적 생략을 명시하는
fallthrough 속성 추가
6.
합성과 집합
초중급 게임개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 6
3.1.1.5 합성과 집합 (Composition & Aggregation)
•여러 객체를 조합하여 복잡한 기능을 구현하는 방법
•합성 (Composition): 클래스 간 "has-a" 관계 형성 (예: 자동차는 엔진을 포함)
•집합 (Aggregation): "uses-a" 관계 형성 (예: 우주선은 연료탱크를 사용)
• 유지보수 용이
• 코드 간결화
• 재사용성과 디버깅 효율 증가
7.
언어의 어떤 기능을쓸것인가
초중급 게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 7
1. 모든 기능을 사용할 필요는 없다
•C++의 최신 기능이 많지만, 무조건 엔진이나 게임에 적용할 필요는 없음
•코드 표준을 유지하면서 필요한 기능만 신중하게 선택해야 함
2. 최신 기능의 지원 부족
•일부 최신 기능이 컴파일러에서 완전히 지원되지 않을 수 있음
•특정 플랫폼에서는 오래된 C++ 표준을 사용해야 하는 경우가 많음
3. 표준 간 전환 비용
•코드베이스를 새로운 표준으로 바꾸는 데는 높은 비용과 시간이 소요됨
•게임 스튜디오는 최신 표준을 선택하면 일정 기간 해당 표준을 유지해야 함
4. 특정 기능의 위험성과 게임 개발
•모든 기능이 좋은 것은 아님
•nullptr 같은 기능은 유용하지만, 일부 기능은 코드의 복잡성을 증가시킬 수 있음
•auto 키워드는 가독성을 높이지만 과도하게 사용하면 코드 이해가 어려워질 수 있음
•템플릿 메타프로그래밍은 코드 가독성을 해치고 유지보수를 어렵게 만들 수 있음
5. 유지보수 가능한 코드가 중요
•새로운 기능이 있다고 해서 무조건 도입하는 것이 아니라, 유지보수성과 디버깅 용이성을 고려해야 함
•신중한 기능 선택이 코드의 안정성과 품질을 보장함
8.
코딩 규칙
초중급 게임개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 8
1. 코딩 규칙이 필요한 이유
•코드 이해와 유지보수가 쉬워지고 비용 절감 효과가 있음
•실수를 방지하고, 테스트 및 디버깅이 용이해짐
•C++는 복잡한 기능이 많아 명확한 규칙이 특히 중요
2. 중요한 코딩 규칙
•인터페이스를 최대한 단순하게 유지: 코드의 복잡성을 줄이고 이해하기 쉽게 만듦
•이름을 명확하게 짓기: 클래스, 변수, 함수의 목적이 명확하도록 직관적인 이름 사용
•네임스페이스를 정리하여 관리: 불필요한 네임스페이스 사용을 자제하여 충돌 방지
•잘 알려진 C++ 사용법을 따르기: 신뢰할 수 있는 전문가들의 권장사항을 참고
•코딩 규칙을 일관성 있게 적용: 코드 스타일을 통일하여 협업과 유지보수를 용이하게 함
•오류를 유발하지 않는 방식으로 코드 작성: 가독성이 높고 실수를 줄일 수 있도록 구조화
9.
3.2 에러 감지와처리
초중급 게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 9
1. 에러 감지 방법의 중요성
•게임 엔진에서 에러를 감지하고 처리하는 방법은 여러 가지가 있음
•각각의 방법에는 차이점이 있으며, 장점과 단점을 파악하고 적절한 방법을 선택해야 함
2. 에러의 종류
•사용자 에러: 사용자의 잘못된 입력이나 조작으로 인해 발생하는 문제
• 예: 잘못된 입력 값, 비정상적인 파일 접근 등
• 프로그램이 정상적으로 동작하도록 예방적 조치를 취해야 함
•프로그래머 에러: 코드의 버그로 인해 발생하는 문제
• 예: 잘못된 메모리 접근, 논리적 오류 등
• 충분한 테스트와 디버깅을 통해 사전에 방지해야 함
3. 게임 개발 과정에서의 에러 구분
•플레이어가 게임을 하면서 발생하는 에러
•게임 개발자가 개발 과정에서 만드는 에러
•에러를 처리할 때, 어느 유형의 사용자가 영향을 받는지 기록하고 이에 맞게 대응해야 함
4. 협업에서의 에러 처리 문제
•여러 개발자가 협업하는 경우, 사용자 에러와 프로그래머 에러의 경계가 모호해질 수 있음
•예를 들어, 한 개발자가 작성한 함수가 다른 개발자에 의해 잘못 호출되었을 때, 어느 쪽의 에러인지 판단하기 어려움
•따라서, 명확한 코드 문서화와 협업 규칙이 필요
10.
예외 처리
초중급 게임개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 10
1. 예외 처리의 개념
•프로그램 실행 중 발생하는 예외적인 상황을 감지하고 적절히 대응하는 기법
•주로 try-catch 구문을 사용하여 예외를 잡고 처리
2. 예외 처리의 장점
•코드의 가독성과 유지보수성이 향상됨
•오류가 발생한 즉시 감지하고 적절한 조치를 취할 수 있음
•일반적인 오류 처리 코드보다 흐름을 깔끔하게 유지
3. 예외 처리의 단점
•실행 비용이 높을 수 있으며, 성능이 중요한 게임 엔진에서는 주의가 필요
•예외를 남용하면 코드가 복잡해지고 디버깅이 어려워질 수 있음
•예외를 어디에서 잡을지 명확히 정의하지 않으면 프로그램 흐름이 예측 불가능해질 수 있음
4. 게임 엔진에서의 예외 처리 전략
•게임 엔진에서는 성능을 고려해 예외 처리를 최소화하거나 사용하지 않는 경우가 많음
•대신, 오류 코드 반환 방식이나 어서션을 활용하는 경우가 많음
•예외 처리는 주로 툴링이나 에디터 개발에서 더 자주 사용됨
11.
Assertion
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 11
1. 어서션의 개념
코드 실행 중 특정 조건이 충족되는지 확인하는 디버깅 기법
주로 개발 단계에서만 활성화되며, 예상치 못한 오류를 조기에 감지
2. 어서션의 역할과 장점
프로그램이 잘못된 상태로 실행되는 것을 방지
논리적 오류를 조기에 발견하고 디버깅을 용이하게 함
실행 중 특정 조건이 충족되지 않으면 즉시 프로그램을 중단하여 문제를 파악
3. 어서션 사용의 한계
릴리스 빌드에서는 성능 문제로 인해 일반적으로 비활성화
어서션을 남용하면 코드가 지나치게 복잡해질 수 있음
어서션 실패 시 적절한 대응이 없으면 프로그램이 강제 종료될 가능성이 있음
4. 게임 엔진에서의 활용
주로 디버깅과 개발 중 오류 감지에 사용
런타임 성능에 영향을 주지 않도록 릴리스 빌드에서는 제거
중요한 시스템 검증이나 API 사용 규칙 강제에 활용
수 표현
초중급 게임개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 13
1. 이진수와 16진수 표현
•컴퓨터는 모든 수를 이진수로 저장하며, 0과 1의 조합으로 표현됨
•16진수는 이진수를 더 간결하게 표현하는 방법으로, C/C++에서는 0x 접두사를 사용하여 표기
2. 정수 표현
•부호 없는 정수: 0 이상의 값을 표현하는 정수 (예: 32비트 정수는 0 ~ 4,294,967,295)
•부호 있는 정수: 2의 보수 표현을 사용하여 양수와 음수를 저장 (예: 32비트 정수는 -2,147,483,648 ~ 2,147,483,647)
3. 고정소수점 표현
•정수부와 소수부를 고정된 비트 수로 나누어 표현하는 방식
•연산이 빠르고 간단하지만, 정밀도와 표현 범위가 제한적
4. 부동소수점 표현
•소수점의 위치를 지수로 표현하는 방식으로, IEEE 754 표준을 따름
•정밀도가 높고 넓은 범위를 표현할 수 있지만, 부동소수점 오차가 발생할 수 있음
5. 게임 엔진에서의 활용
•고정소수점은 빠른 연산이 필요할 때 사용되며, 일부 임베디드 시스템이나 모바일 게임에서 활용
•부동소수점은 정밀도가 중요한 그래픽 연산이나 물리 시뮬레이션에서 사용
14.
기본적인 데이터 타입
초중급게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 14
1. 문자형 데이터
•char: 8비트 크기의 문자 데이터를 저장
•ASCII 또는 UTF-8 문자를 표현할 수 있음
2. 정수형 데이터
•int, short, long: 플랫폼에 따라 크기가 다를 수 있음
•일반적으로 short는 16비트, int는 32비트, long은 32비트 또는 64비트
•부호 없는 정수 타입(unsigned)도 존재
3. 부동소수점 데이터
•float: 32비트 IEEE-754 부동소수점 수
•double: 64비트 정밀도 부동소수점 수
4. 불리언 데이터
•bool: 참 또는 거짓 값을 나타내는 데이터 타입
•일부 시스템에서는 1비트가 아닌 8비트 또는 32비트를 사용할 수도 있음
5. 이식 가능한 크기 타입
•int8_t, int16_t, int32_t, int64_t: 크기가 고정된 정수 타입
•uint8_t, uint16_t, uint32_t, uint64_t: 부호 없는 정수 타입
6. 게임 엔진에서의 활용
•성능 최적화를 위해 특정 크기의 데이터 타입을 직접 정의하기도 함
•예를 들어, F32는 32비트 부동소수점, U8, U16은 각각 8비트, 16비트 정수
•SIMD 연산을 활용할 때 128비트 레지스터를 사용하기 위해 특정 데이터 타입을 정의할 수도 있음
15.
킬로바이트 vs 키비바이트
초중급게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 15
1. 기존의 혼란
•메모리 용량을 표현할 때 국제단위계(SI)에서는 킬로바이트(kB), 메가바이트(MB)를 사용
•하지만 컴퓨터에서는 이진법을 기반으로 하여 1킬로바이트가 1024바이트로 해석됨
•SI 단위에서는 1킬로바이트를 1000바이트로 정의하기 때문에 혼동이 발생
2. IEC 표준 단위 도입
•국제전기기술위원회(IEC)는 1998년에 새로운 단위 체계를 제안
•1024바이트를 의미하는 새로운 단위 키비바이트(KiB), 메비바이트(MiB) 등을 도입
•1000 단위를 사용하는 SI 표준과 1024 단위를 사용하는 IEC 표준이 구분됨
16.
선언, 정의, 연결성
초중급게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 16
1. 번역 단위와 목적 파일
•C/C++ 프로그램은 여러 개의 번역 단위로 나뉘며, 컴파일러는 각 cpp 파일을 독립적으로 번역
•각 cpp 파일이 컴파일되면 목적 파일이 생성되며, 여기에는 정의된 함수와 전역 변수가 포함됨
•목적 파일에는 선언만 있고 정의가 없는 외부 참조가 존재할 수 있음
2. 링커의 역할
•모든 목적 파일을 결합하여 실행 가능한 프로그램을 생성
•미확정 상태인 외부 참조를 해결하여 최종적으로 모든 함수와 변수의 주소를 확정
3. 링커 관련 주요 오류
•미확정 심볼 오류: extern으로 선언된 변수나 함수를 찾을 수 없는 경우 발생
•중복 정의 심볼 오류: 동일한 변수나 함수가 여러 번 정의된 경우 발생
17.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 17
1. 선언과 정의의 개념
•선언: 데이터 객체나 함수의 형태를 나타내며, 변수나 함수의 이름과 데이터 타입을 컴파일러에 알림
•정의: 프로그램 내에서 메모리를 할당하여 변수나 함수의 실제 내용을 구현
2. 선언과 정의의 차이
•선언은 어떤 개념에 대한 참조 역할을 하며, 정의는 해당 개념의 본체를 제공
•모든 정의는 선언이지만, 모든 선언이 정의는 아님
•C/C++에서는 정의가 아닌 순수한 선언이 존재할 수 있음
3. 함수 선언과 정의의 예시
•함수 서명 뒤에 중괄호로 함수 본체를 작성하면 정의됨
•세미콜론으로 끝나는 선언은 해당 함수를 참조할 수 있도록 만듦
4. 선언과 정의의 중복 문제
•C/C++에서는 동일한 데이터나 함수에 대해 여러 번 선언할 수 있지만, 정의는 한 번만 가능
•동일한 번역 단위에서 여러 번 정의가 나타나면 컴파일러가 오류를 발생
5. 헤더 파일에서의 정의와 인라인 함수
•일반적으로 함수 정의를 헤더 파일에 두는 것은 바람직하지 않음
•인라인 함수는 예외적으로 헤더 파일에 정의될 수 있으며, 여러 번역 단위에서 사용 가능
6. 템플릿과 헤더 파일
•템플릿 클래스와 함수의 정의는 모든 번역 단위에서 확인할 수 있어야 하므로 헤더 파일에 포함
•템플릿의 선언과 정의는 따로 나뉠 수 없으며, 반드시 같은 파일에 존재해야 함
18.
연결성
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 18
1. 연결성의 개념
•모든 정의는 연결성을 가지며, 이는 링커가 번역 단위 간 정의를 어떻게 연결하는지를 결정
•외부 연결성: 정의가 여러 번역 단위에서 참조될 수 있음
•내부 연결성: 정의가 해당 번역 단위 내에서만 사용될 수 있음
2. 외부 연결성과 내부 연결성
•기본적으로 모든 정의는 외부 연결성을 가짐
•static 키워드를 사용하면 내부 연결성으로 변경되어 해당 번역 단위에서만 사용 가능
•여러 cpp 파일에서 동일한 static 정의가 있어도 서로 다른 존재로 인식됨
3. 선언과 연결성
•선언 자체는 메모리를 차지하지 않으며, 연결성과 관계없음
•선언이 있는 번역 단위 내에서만 적용되므로 항상 내부 연결성을 가진다고 볼 수 있음
•여러 cpp 파일에서 동일한 선언이 있어도 각 번역 단위에서만 사용됨
4. 인라인 함수와 연결성
•인라인 함수는 기본적으로 내부 연결성을 가짐
•여러 번역 단위에서 동일한 인라인 함수를 정의해도 문제가 발생하지 않음
•인라인 함수가 포함된 헤더 파일을 여러 번 포함해도 중복 정의 심볼 오류가 발생하지 않음
19.
C/C++ 프로그램의 메모리
구조
초중급게임 개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 19
1. 실행 파일 개요
•C/C++ 프로그램은 링커에 의해 실행 파일로 변환됨
•유닉스 계열에서는 ELF, 윈도우에서는 exe 형식을 사용
•실행 파일에는 실행에 필요한 메모리 이미지가 포함되며, 실행 중 추가적인 메모리가 할당됨
2. 실행 파일의 주요 세그먼트
1.텍스트 세그먼트
1. 코드 세그먼트라고도 하며, 프로그램의 실행 코드를 저장
2. 함수의 기계어 명령이 포함됨
2.데이터 세그먼트
1. 초기값을 가진 전역 및 정적 변수를 저장
2. 프로그램 실행 시 메모리에 로드되며, 저장된 초기값을 유지
3.BSS 세그먼트
1. 초기화되지 않은 전역 및 정적 변수를 저장
2. 프로그램 실행 시 자동으로 0으로 초기화됨
4.읽기 전용 데이터 세그먼트
1. rodata 세그먼트라고도 하며, 변경할 수 없는 상수를 저장
2. const 변수나 매니페스트 상수 등이 포함됨
3. 실행 파일 내 변수의 위치 결정
•전역 변수는 데이터 세그먼트 또는 BSS 세그먼트에 위치
•const 키워드를 사용한 변수는 읽기 전용 데이터 세그먼트에 저장
•static 키워드를 사용하면 내부 연결성을 가지며, 특정 번역 단위에서만 접근 가능
20.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 20
프로그램 스택
1. 프로그램 스택 개요
•실행 파일이 메모리에 로드될 때 운영체제는 프로그램 스택이라는 메모리 공간을 할당
•함수가 호출될 때마다 스택 프레임이 생성되며, 함수가 종료되면 해당 프레임이 제거됨
2. 스택에 저장되는 데이터
1.리턴 주소
1. 함수 호출 후 되돌아갈 위치를 저장
2.CPU 레지스터
1. 함수 호출 전에 사용하던 레지스터 값을 스택에 저장하여 복구 가능하도록 함
2. 함수가 종료될 때 레지스터 값을 원래대로 복구
3.지역 변수
1. 함수 내에서 선언된 변수들이 스택 프레임에 저장
2. 함수가 종료되면 스택에서 제거됨
3. 스택 메모리 관리와 주의점
•스택 프레임은 스택 포인터를 이용해 관리되며, 함수 호출 시 증가하고 종료 시 감소
•함수가 종료되면 해당 스택 프레임이 제거되므로, 지역 변수의 주소를 리턴하면 예상치 못한 동작 발생 가능
•잘못된 포인터 참조로 인해 프로그램이 비정상 종료될 수도 있음
21.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 21
동적 할당 힙
1. 동적 할당 개요
•프로그램 실행 중 메모리 사용량이 변할 수 있기 때문에 추가적인 메모리가 필요할 수 있음
•실행 파일 이미지나 스택에 미리 할당되지 않은 메모리는 동적으로 할당됨
2. 힙 메모리 할당과 관리
•운영체제는 프로세스마다 힙이라는 메모리 공간을 제공
•malloc, free와 같은 함수를 사용하여 동적으로 메모리를 할당하고 해제
•C++에서는 new, delete 연산자로 힙 메모리를 관리
3. 동적 메모리 사용의 주의점
•new와 delete 연산자는 오버로딩이 가능하여, 항상 힙에서 할당된다고 가정하면 안 됨
•메모리 누수를 방지하기 위해 동적 할당된 메모리는 반드시 해제해야 함
•힙 할당은 스택보다 성능이 느리므로 과도한 사용을 피해야 함
22.
멤버 변수
초중급 게임개발자 스터디 <데브루키> 알콜코더(박민근/크래프톤) 22
1. 개요
•C의 구조체와 C++의 클래스는 여러 변수를 묶어 논리적인 단위로 관리할 때 사용
•구조체나 클래스의 선언만으로 저장 공간이 할당되는 것은 아님
•인스턴스를 생성해야 실제 메모리가 할당됨
2. 클래스 정적 멤버
•static 키워드를 사용하면 클래스에 속하지만 인스턴스마다 존재하지 않는 변수 정의 가능
•정적 변수는 클래스 내에서 선언되지만, 실제 메모리는 cpp 파일에서 정의해야 함
•클래스 외부에서 접근할 때는 클래스 이름을 함께 사용해야 함
3. static 키워드의 의미
•파일 범위에서 사용하면 해당 cpp 파일에서만 보이도록 제한
•함수 내에서 사용하면 전역 변수처럼 동작하지만 해당 함수 안에서만 유지
•클래스나 구조체에서 사용하면 인스턴스에 종속되지 않고 공통적인 값으로 유지
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 24
메모리 정렬과 패딩
1. 메모리 정렬의 중요성
•현대 CPU는 정렬된 메모리에서 데이터를 읽고 쓰는 것이 빠름
•32비트 정수는 4바이트 정렬 주소에서, 16비트 정수는 2바이트 정렬 주소에서
읽는 것이 효율적
•정렬되지 않은 주소에서 데이터를 읽으면 추가적인 연산이 필요하거나
프로그램이 강제 종료될 수도 있음
2. 데이터 정렬 조건
•32비트 값은 4바이트 정렬을 따라야 함
•16비트 값은 2바이트 정렬을 따라야 함
•8비트 값은 어디에나 위치할 수 있음
•SIMD 명령어를 사용하는 경우 16바이트 정렬이 필요할 수도 있음
3. 패딩과 메모리 효율성
•클래스나 구조체에서 서로 다른 크기의 변수가 연속될 경우, 컴파일러는 정렬을
맞추기 위해 패딩을 추가
•잘못된 변수 배치는 불필요한 패딩을 증가시켜 메모리 낭비를 초래
•작은 변수를 한데 모아 배치하면 패딩을 줄이고 메모리 사용을 최적화할 수 있음
4. 패딩을 고려한 데이터 구조 설계
•불필요한 패딩을 줄이기 위해 변수를 정렬된 순서로 배치
•구조체 마지막에 명시적으로 패딩을 추가하여 정렬을 명확히 표시
25.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 25
3.3.7.2 C++ 클래스의 메모리 구조
1. 클래스와 구조체의 메모리 차이
•C++ 클래스는 상속과 가상 함수로 인해 C 구조체보다 복잡한 메모리 구조를 가짐
•클래스가 다른 클래스를 상속받으면, 메모리에서는 부모 클래스의 멤버가 먼저 배치되고 자식 클래스의 멤버가 그 뒤를 이어서 배치됨
•클래스 간 메모리 정렬 조건에 따라 패딩이 추가될 수 있음
2. 가상 함수와 vtable
•클래스에 가상 함수가 있으면 vtable이라는 테이블이 추가됨
•vtable은 해당 클래스의 가상 함수 목록을 포함하며, 객체는 vtable을 가리키는 포인터(vpointer)를 가짐
•가상 함수를 호출할 때 vtable을 통해 실제 실행할 함수를 동적으로 결정
3. 다형성과 vtable 구조
•다형성은 코드가 객체의 실제 타입을 몰라도 적절한 함수를 호출할 수 있도록 함
•예를 들어, Shape 클래스를 상속받은 Circle, Rectangle, Triangle 클래스가 각각 Draw() 함수를 구현하면, vtable을 통해 적절한 Draw() 함수가 호출됨
CPU
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 27
1. 주요 연산 장치
•수리/논리 장치(ALU): 정수 연산 및 비트 연산 수행
•부동소수점 장치(FPU): 부동소수점 연산을 담당하며, IEEE 754 표준을 따름
•벡터 처리 장치(VPU): 한 번에 여러 정수 또는 부동소수점 연산을 병렬로 처리
2. 메모리 관리 및 제어
•메모리 컨트롤러(MC): CPU 내부와 외부 메모리 장치 간 데이터 전송을 관리
•메모리 관리 장치(MMU): 가상 메모리 주소 변환 및 접근 권한을 처리
3. 데이터 저장 및 흐름 제어
•레지스터: 연산을 위한 임시 저장소로, CPU 내부에서 가장 빠르게 접근 가능
•제어 장치(CU): 명령어를 해석하고 CPU 내부 구성 요소 간 데이터 흐름을 조정
28.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 28
3.4.3.1 ALU (Arithmetic and Logic Unit)
•기본적인 정수 연산과 논리 연산을 수행하는 장치
•주요 연산: 덧셈, 뺄셈, 곱셈, 나눗셈, 부정 연산, AND, OR, XOR 등
•일부 CPU는 ALU를 수리 장치와 논리 장치로 나누어 설계하기도 함
•부동소수점 연산은 별도의 FPU에서 처리하는 경우가 많음
3.4.3.2 VPU (Vector Processing Unit)
•벡터 연산을 수행하는 장치로, 여러 개의 데이터를 동시에 처리할 수 있음
•SIMD(Single Instruction Multiple Data) 방식을 사용하여 한 개의 명령어로 여러 데이터를 병렬 연산
•현대 CPU는 FPU와 통합된 형태의 VPU를 가지며, 일부 부동소수점 연산을 VPU에서 수행
•벡터 연산은 그래픽, 과학 연산, AI 연산 등에 활용됨
29.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 29
3.4.3.3 레지스터
1. 레지스터 개요
•CPU 내부의 초고속 메모리로, 연산 속도를 극대화하기 위해 사용됨
•주메모리보다 물리적으로 가까운 위치에 있으며, 보통 정적 RAM(SRAM)으로 구현
•CPU 내부 레지스터 집합을 레지스터 파일이라고 함
2. 레지스터의 역할
•명령어 포인터(IP): 현재 실행 중인 명령어의 주소를 저장
•스택 포인터(SP): 스택의 최상단 주소를 가리키며, 함수 호출 및 반환 시 사용
•베이스 포인터(BP): 함수의 스택 프레임 내에서 기준이 되는 주소 저장
•상태 레지스터: 연산 결과에 따라 플래그를 설정하여 프로그램 흐름을 제어
3. 레지스터와 연산 속도
•CPU 연산에서 데이터를 가장 빠르게 접근할 수 있는 저장소
•FPU와 VPU의 레지스터는 일반 정수 레지스터(GPR)보다 크며, 부동소수점 연산에 최적화
•현대 CPU에서는 부동소수점 연산이 벡터 처리 장치(VPU)에서 수행됨
4. 정수와 부동소수점 변환 이슈
•과거에는 FPU가 별도로 존재하여 정수(int)와 부동소수점(float) 변환이 느렸음
•현재는 VPU에서 정수와 부동소수점 연산을 모두 처리 가능하지만, 변환 비용이 발생하므로 피하는 것이 좋음
30.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 30
3.4.3.4 제어 장치
1. 제어 장치(CU)의 역할
•CPU 내부의 데이터 흐름을 조정하고, 다른 구성 요소 간의 동작을 지휘
•명령어 스트림을 읽고, 각 명령어를 해석하여 실행할 연산 장치에 전달
2. 주요 기능
•명령어를 해석하여 ALU, FPU, VPU, 레지스터, 메모리 컨트롤러 등과 연결
•명령어를 명령 코드(opcode)와 피연산자(operand)로 분해하여 처리
3. 고급 CPU에서의 역할 확장
•파이프라인 구조와 슈퍼스칼라(Superscalar) CPU에서는 역할이 더욱 중요
•분기 예측 및 비순차 실행을 위한 스케줄링을 수행하여 성능 최적화
31.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 31
1. 클럭의 개념
•디지털 회로는 상태를 변경할 때 주기적인 클럭 신호를 사용
•CPU의 상태 변화는 시스템 클럭에 의해 동기화되며, 이 신호의 주기가 클럭 사이클
2. 클럭 속도와 CPU 연산
•한 클럭 사이클에 하나의 명령어가 처리되는 것은 아니며, 일부 명령어는 여러 마이크로 연산으로 분해되어 여러 사이클이 필요
3. 파이프라인과 성능
•현대 CPU는 파이프라인을 통해 여러 명령어 단계를 동시에 실행
•CPU의 성능은 클럭 속도뿐만 아니라 파이프라인, 슈퍼스칼라 설계, 멀티코어 등의 요소에 의해 결정
3.4.4.1 클럭 속도 vs 처리 성능
1. 처리 성능의 측정 기준
•처리량은 초당 수행할 수 있는 연산의 수로 측정됨
•단위: 초당 백만 명령어(MIPS) 또는 초당 부동소수점 연산(FLOPS)
2. 클럭 속도와 실제 성능 차이
•명령어마다 실행 사이클이 다르므로, 클럭 속도가 곧 처리 성능을 의미하지 않음
•예를 들어, 3GHz CPU가 부동소수점 곱셈을 수행할 때 6사이클이 필요하면 이론적으로 0.5 GFLOPS 성능을 낼 수 있음
3. 벤치마크의 필요성
•CPU 성능은 단순한 클럭 속도로 비교하기 어려움
•파이프라인, 슈퍼스칼라 설계, 벡터 처리, 멀티코어 등의 영향을 받음
•실제 성능을 비교하려면 표준화된 벤치마크를 활용하는 것이 일반적
클럭
32.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 32
메모리
1. 메모리 개요
•컴퓨터의 메모리는 여러 개의 셀로 구성되며, 각 셀은 1바이트의 데이터를 저장
•주소를 통해 특정 셀에 접근하며, 주소 범위에 따라 메모리 크기가 결정됨
2. 메모리 종류
•읽기 전용 메모리(ROM): 전원이 꺼져도 데이터가 유지되며, 일부 ROM은 한 번만 기록 가능
•읽기/쓰기 메모리(RAM): 데이터를 자유롭게 읽고 쓸 수 있으며, 전원이 꺼지면 데이터가 손실
3. RAM의 종류
•정적 RAM(SRAM): 빠르고 전력 소비가 낮지만, 비용이 높아 주로 캐시 메모리로 사용
•동적 RAM(DRAM): 일정 주기로 데이터를 새롭게 저장해야 하며, 속도는 느리지만 비용이 저렴해 주 메모리로 사용
4. 추가적인 구분 기준
•여러 CPU가 동시에 접근할 수 있는지 여부에 따라 멀티포트 RAM으로 구분
•클럭과 동기화 여부에 따라 동기식(SDRAM)과 비동기식으로 구분
•데이터 전송 방식에 따라 싱글 데이터 레이트(SDR)와 더블 데이터 레이트(DDR)로 나뉨
33.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 33
버스
1. 버스 개요
•CPU와 메모리 사이의 데이터 전달을 담당하는 연결 장치
•각 라인은 1비트를 전송하며, 여러 라인이 병렬로 데이터를 전송
2. 버스의 종류
•주소 버스: CPU가 메모리나 레지스터의 특정 주소를 지정할 때 사용
•데이터 버스: 주소 버스에서 지정한 위치의 데이터를 주고받음
3.4.6.1 버스의 크기
1. 주소 버스
•주소 버스의 크기에 따라 CPU가 접근할 수 있는 메모리의 최대 크기가 결정
•16비트 주소 버스는 64KiB, 32비트 주소 버스는 4GiB, 64비트 주소 버스는 16EiB의 메모리를 지원
2. 데이터 버스
•CPU가 한 번에 주고받을 수 있는 데이터의 크기를 결정
•일반적으로 CPU의 레지스터 크기와 유사하지만, 일부 경우에는 다를 수 있음
•64비트 CPU에서도 16비트 데이터를 읽는 경우 추가적인 연산이 필요할 수 있음
34.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 34
3.4.6.2 워드
1. 워드의 개념
•워드는 여러 바이트로 구성된 데이터 단위를 의미하며, 하드웨어에 따라 크기가 다름
•일반적으로 16비트, 32비트, 64비트 단위를 사용
2. 자연스러운 워드 크기
•CPU의 레지스터 크기와 데이터 버스 크기가 같은 경우를 자연스러운 워드 크기라고 함
•예를 들어, 32비트 CPU는 32비트 데이터를 처리하는 것이 가장 효율적
3.4.6.3 n비트 컴퓨터
1. n비트 컴퓨터의 의미
•n비트 데이터 버스와 레지스터를 가진 컴퓨터를 의미
•하지만 n비트가 항상 모든 구성 요소를 설명하는 것은 아님
2. 데이터 버스와 레지스터의 불일치
•일부 CPU는 레지스터 크기와 데이터 버스 크기가 다를 수 있음
•예를 들어, 8088은 16비트 레지스터와 16비트 주소 버스를 가졌지만, 8비트 데이터 버스를 사용하여 메모리에 접근
35.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 35
기계어와 어셈블리어
1. 기계어 개요
•CPU는 단순한 명령어의 흐름으로 프로그램을 실행
•각 명령어는 메모리 컨트롤러, ALU, FPU, VPU 등의 구성 요소에 특정 동작을 수행하도록 지시
•일반적으로 명령어는 순차적으로 실행되지만, 특정 명령어는 실행 흐름을 변경 가능
3.4.7.1 명령어 집합 아키텍처
1. ISA 개념
•CPU가 지원하는 명령어 집합과 주소 모드, 메모리 내 명령어 형식 등을 포함하는 개념
•프로그램이 CPU의 명령어를 사용할 수 있도록 정의된 구조
2. 주요 명령어 유형
•이동 명령어: 레지스터 간 또는 레지스터와 메모리 간 데이터 이동
•수리 연산: 덧셈, 뺄셈, 곱셈, 나눗셈 등의 연산
•비트 연산: AND, OR, XOR 등 비트 단위 연산
•시프트 및 회전: 데이터 비트를 좌우로 이동하거나 회전
•비교: 두 값을 비교하여 결과를 상태 레지스터에 저장
•점프와 분기: 특정 조건에 따라 프로그램 흐름을 변경
•푸시와 팝: 스택을 이용한 데이터 저장과 복원
•함수 호출과 리턴: 서브루틴 호출 및 실행 완료 후 복귀
•인터럽트: CPU가 특정 이벤트 발생 시 처리할 수 있도록 지원
36.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 36
3.4.7.2 기계어
1. 기계어의 개념
•CPU가 직접 이해하는 숫자로 구성된 명령어
•프로그램이 기계어로 인코딩될 때 실제 실행 가능
2. 기계어 구성 요소
•명령어 코드: CPU가 수행할 동작을 지정
•피연산자: 명령어가 사용할 입력값 또는 출력값
•옵션 필드: 명령어의 주소 지정 모드나 기타 설정 정보
3. 기계어의 인코딩 방식
•일부 CPU는 고정 길이 명령어를 사용, 일부는 가변 길이 명령어를 사용
•명령어 워드는 CPU에 따라 크기가 다름
3.4.7.3 어셈블리 언어
1. 개요
•기계어를 사람이 읽고 쓰기 쉽게 만든 프로그래밍 언어
•명령어 코드를 사람이 이해할 수 있는 형태로 표현
2. 어셈블리 언어의 특징
•명령어를 문자로 표현하며, 피연산자를 쉽게 지정 가능
•레지스터와 메모리 주소를 명확히 구분하여 사용
•특정 주소 대신 라벨을 사용하여 가독성을 높임
37.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 37
3.4.7.4 주소 지정 방식
1. 주소 지정 방식의 개념
•명령어가 데이터를 참조하는 방법을 정의
2. 주요 주소 지정 방식
•레지스터 주소 지정: 레지스터 간 데이터 이동
•즉시값 주소 지정: 상수를 직접 명령어에 포함
•직접 주소 지정: 특정 메모리 주소를 명령어에서 직접 참조
•레지스터 간접 주소 지정: 레지스터에 저장된 주소를 참조
•상대 주소 지정: 현재 명령어 위치를 기준으로 오프셋 적용
•기타 주소 지정 방식: 하드웨어에 따라 다양한 변형이 존재
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 39
메모리 매핑
1. 개요
•CPU는 주소 버스를 통해 메모리 공간을 할당하고 접근
•물리적인 메모리 장치가 특정 주소 공간에 매핑됨
2. 주소 공간 활용
•일부 구간은 ROM, 나머지는 RAM 용도로 사용
•예를 들어, 애플 II의 경우 16비트 주소 공간에서 특정 범위는 ROM, 나머지는 RAM에 할당
3. 실제 사용 가능한 메모리
•이론적으로 가능한 주소 공간이 모든 메모리 용량을 의미하는 것은 아님
•64비트 주소 버스가 지원하는 전체 공간을 실제로 활용하는 경우는 드뭄
3.5.1.1 메모리 맵 I/O
1. 개요
•특정 주소를 주변 장치와 연결하여 CPU가 직접 메모리 접근 방식으로 장치를 제어
2. 메모리 맵 I/O 방식
•특정 주소를 읽거나 쓰면 주변 장치가 이를 감지하고 해당 동작을 수행
•예를 들어, 애플 II는 특정 주소를 읽으면 RAM의 뱅크 전환 기능을 수행
3. 포트 맵 I/O와의 차이
•메모리 맵 I/O는 주소 공간을 장치에 할당
•포트 맵 I/O는 특정 레지스터를 사용하여 장치를 제어
40.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 40
3.5.1.2 비디오 램
1. 개요
•디스플레이 장치는 보통 특정 메모리 주소를 읽어 화면에 표시
•비디오 램(VRAM)은 그래픽 데이터를 저장하는 특수한 메모리
2. 초기 비디오 램 구성
•예전 시스템에서는 비디오 램이 메인보드의 메모리 칩 일부를 차지
•IBM PC의 경우 VRAM은 메모리 공간을 공유
3. 현대 시스템의 VRAM
•GPU가 별도의 비디오 램을 가지고 있으며, 고속 데이터 처리를 위해 PCIe와 같은 버스를 사용
•CPU와 GPU가 동일한 메모리를 공유하는 경우도 존재
41.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 41
1. 개요
•프로그램이 사용하는 메모리 주소는 실제 하드웨어 메모리
주소와 다를 수 있음
•CPU는 룩업 테이블을 통해 가상 주소를 물리 주소로 매핑
2. 가상 메모리의 이점
•실제 물리 메모리보다 더 많은 메모리를 사용할 수 있음
•디스크 공간을 활용하여 부족한 RAM을 보완
•각 프로그램이 독립적인 메모리 공간을 가질 수 있어 충돌 방지
가상 메모리
42.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 42
3.5.2.1 가상 메모리 페이지
1. 페이지 개념
•가상 주소 공간을 일정한 크기의 페이지 단위로 나누어 관리
•일반적으로 4KiB 또는 8KiB 크기를 사용
2. 페이지 테이블
•가상 주소의 페이지 번호를 물리 메모리의 페이지 번호로 변환
•운영체제는 페이지 테이블을 통해 가상 주소를 물리 주소로 매핑
3.5.2.2 가상 주소에서 물리 주소로 변환하기
1. 주소 변환 과정
•가상 주소는 페이지 번호와 오프셋으로 나뉨
•페이지 번호는 페이지 테이블을 통해 물리 페이지 번호로 변환
•변환된 물리 주소에 오프셋을 더하여 최종 물리 주소 결정
2. 메모리 관리 장치(MMU) 역할
•CPU의 MMU가 페이지 테이블을 검색하여 변환 수행
•변환된 주소는 캐싱되어 반복 접근 시 성능 향상
43.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 43
3.5.2.3 페이지 폴트 처리
1. 페이지 폴트 개념
•프로그램이 매핑되지 않은 가상 주소에 접근하면 발생
•운영체제가 해당 페이지를 디스크에서 로드한 후 프로그램 실행을 계속
2. 스왑 메커니즘
•필요하지 않은 페이지를 디스크에 저장하고 새로운 페이지를 로드
•메모리 부족 시 자주 사용되는 페이지를 유지하고 덜 사용되는 페이지를 스왑
3.5.2.4 변환 색인 버퍼
1. 변환 속도 향상
•페이지 테이블은 크기가 커서 변환 속도가 느릴 수 있음
•변환 색인 버퍼(TLB)는 최근 변환된 페이지를 캐싱하여 속도 향상
2. 캐시 계층과 비교
•일반적인 캐시와 유사하지만, 메모리 주소 변환 정보를 저장
•TLB에 없는 페이지는 일반 페이지 테이블을 조회해야 하므로 속도가 느려짐
44.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 44
지연 감소를 위한 메모리 구조
1. 메모리 지연 개념
•CPU가 메모리에 요청을 보내고 실제 데이터를 받을 때까지의 시간
•메모리 지연은 시스템 성능에 큰 영향을 미침
2. 메모리 지연을 결정하는 요인
•메모리 셀 구현 기술
•메모리에서 지원하는 읽기/쓰기 포트 수
•메모리와 CPU 코어 간의 물리적 거리
3. 정적 RAM과 동적 RAM의 차이
•SRAM은 빠르지만 크기가 크고 비용이 높음
•DRAM은 트랜지스터를 적게 사용하여 저렴하지만 속도가 느림
4. 메모리 포트와 성능
•단일 포트 RAM은 한 번에 하나의 읽기 또는 쓰기만 가능
•다중 포트 RAM은 여러 코어가 동시에 접근할 수 있어 성능 향상
5. CPU와 메모리 거리
•물리적 거리가 증가하면 지연 시간이 증가
•메모리 접근을 최적화하기 위해 신호의 전송 경로를 최소화해야 함
45.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 45
3.5.3.1 메모리 갭
1. CPU와 메모리 속도 차이
•초기 컴퓨터에서는 CPU와 메모리 속도가 거의 같았음
•현대 시스템에서는 메모리 접근 시간이 CPU 실행 속도보다 훨씬 느림
2. 메모리 갭 해결 기법
•캐시 메모리를 사용하여 자주 접근하는 데이터를 빠르게 제공
•CPU가 다른 작업을 수행하면서 메모리 요청이 완료되도록 스케줄링
•프로그램 데이터를 효율적으로 배열하여 메모리 접근을 최적화
3.5.3.2 레지스터 파일
1. 개요
•CPU 내부의 레지스터는 메모리 접근 지연을 최소화하는 가장 빠른 저장 장치
•보통 다중 포트 정적 RAM으로 구현
2. 레지스터의 장점
•ALU와 가까운 위치에 있어 거의 즉시 접근 가능
•주메모리 접근보다 훨씬 빠르므로 프로그램 실행 속도 향상
3. 레지스터와 메모리 비용 차이
•레지스터는 크기가 작고 자주 사용되지만, 단위 비용이 높음
•주메모리보다 속도는 빠르지만 용량이 제한적
46.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 46
메모리 캐시 계층
1. 개요
•메모리 접근 지연을 줄이기 위해 여러 단계의 캐시를 사용
•L1 캐시는 가장 빠르지만 작고, L2와 L3 캐시는 크지만
상대적으로 느림
2. 캐시 히트와 미스
•캐시에 있는 데이터를 사용하면 히트, 없는 경우 미스 발생
•캐시 미스 시 주메모리에서 데이터를 가져와야 하므로 성능 저하
47.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 47
3.5.4.1 캐시 라인
1. 개요
•메모리 캐시는 연속된 데이터를 한 번에 가져오는 방식 사용
•캐시의 데이터 전송 단위를 캐시 라인이라고 함
2. 공간적 지역성과 시간적 지역성
•프로그램은 메모리를 순차적으로 접근하는 경우가 많아 캐시 라인을 활용
•자주 사용하는 데이터는 캐시에 남겨둠으로써 성능 향상
3.5.4.2 캐시 라인과 주메모리 주소 매핑
1. 매핑 방식
•캐시 크기에 따라 주메모리 주소가 반복적으로 매핑됨
•캐시의 한 라인은 여러 개의 주메모리 주소와 매핑될 수 있음
2. 주소 매핑 방법
•캐시 크기를 기준으로 모듈로 연산을 수행해 주소를 결정
•특정 캐시 라인이 주메모리의 어느 블록을 담당하는지 태그를 사용해 구분
3.5.4.3 캐시 주소 부여
1. 주소 변환 과정
•CPU가 주메모리 주소를 요청하면 먼저 캐시에서 확인
•캐시 라인 번호와 태그를 확인하여 데이터가 존재하는지 판단
2. 태그와 캐시 라인의 관계
•각 캐시 라인은 태그를 통해 특정 주메모리 블록과 연결
•캐시 미스 발생 시 주메모리에서 데이터를 가져와 태그를 갱신
48.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 48
3.5.4.4 집합 연관 및 교체 정책
1. 직접 매핑과 집합 연관
•직접 매핑 방식에서는 특정 주메모리 블록이 하나의 캐시 라인에만 할당
•집합 연관 캐시는 여러 캐시 라인에 매핑될 수 있어 충돌을 줄임
2. 캐시 교체 정책
•NMRU 방식: 가장 덜 사용된 데이터를 교체
•FIFO 방식: 가장 먼저 들어온 데이터를 교체
•LRU 방식: 가장 오래 사용되지 않은 데이터를 교체
3.5.4.5 멀티레벨 캐시
1. 개요
•L1, L2, L3 캐시를 단계적으로 사용하여 성능 향상
•L1 캐시는 작고 빠르며, L3는 크지만 상대적으로 느림
2. 멀티코어 환경에서의 캐시
•L1은 각 코어마다 따로 존재하지만, L2나 L3는 공유될 수도 있음
•캐시가 많을수록 적중률은 증가하지만 접근 속도는 낮아질 수 있음
3.5.4.6 명령어 캐시와 데이터 캐시
1. 캐시의 역할
•명령어 캐시는 실행할 코드의 일부를 미리 로드
•데이터 캐시는 연산에 필요한 데이터를 빠르게 제공
2. 캐시 충돌 방지
•명령어 캐시와 데이터 캐시는 분리되어야 성능 저하를 막을 수 있
49.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 49
3.5.4.7 쓰기 정책
1. 쓰기 스루와 쓰기 백
•쓰기 스루: 데이터를 캐시와 주메모리에 동시에 저장
•쓰기 백: 데이터를 캐시에 먼저 저장한 후 필요할 때 주메모리에 반영
2. 성능과 일관성 고려
•쓰기 스루는 일관성이 유지되지만 성능이 낮음
•쓰기 백은 성능이 높지만 충돌이 발생할 수 있음
3.5.4.8 캐시 일관성
1. 캐시와 주메모리의 동기화
•다중 코어 환경에서는 각 코어가 캐시를 공유할 수도 있음
•모든 캐시와 주메모리가 동일한 값을 유지해야 함
2. 일관성 유지 프로토콜
•MESI, MOESI, MESIF 같은 프로토콜을 사용하여 일관성 유지
3.5.4.9 캐시 미스 피하기
1. 캐시 미스를 줄이는 방법
•연속된 데이터를 한 번에 가져오는 방식 사용
•메모리 구조를 최적화하여 캐시 효율 극대화
2. 코드 최적화
•루프 내에서 캐시 적중률을 높이도록 코드 설계
•인라인 함수 사용을 최소화하여 캐시 낭비 방지
50.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 50
불균일 메모리 접근
1. 개요
•시스템 설계에서 메모리 접근 방식을 결정하는 두 가지 모델이 있음
•균일 메모리 접근(UMA)과 불균일 메모리 접근(NUMA)
2. UMA와 NUMA 비교
•UMA에서는 모든 CPU 코어가 동일한 주소 공간의 주메모리에 접근
•NUMA에서는 각 코어가 자신의 로컬 메모리를 가지며, 다른 코어의 메모리에 접근할 때 성능 저하 발생
3. UMA의 문제점
•여러 코어가 동일한 메모리를 공유하면 캐시 경쟁이 발생
•특정 코어가 자주 사용하는 데이터가 다른 코어에서도 필요할 경우 성능 저하
4. NUMA의 장점
•각 코어에 빠른 로컬 스토어를 제공하여 접근 속도 향상
•DMA 컨트롤러를 활용해 로컬 스토어와 주메모리 간 데이터 이동 가능
51.
초중급 게임 개발자스터디 <데브루키> 알콜코더(박민근/크래프톤) 51
3.5.5.1 PS3의 SPU 로컬 스토어
1. PS3의 메모리 구조
•메인 CPU인 PPU와 8개의 SPU로 구성
•PPU는 256MiB 주메모리에, GPU는 256MiB 비디오 램에 접근 가능
2. SPU의 독립적인 로컬 스토어
•각 SPU는 256KiB 크기의 로컬 스토어를 독립적으로 가짐
•SPU는 직접 주메모리나 VRAM에 접근할 수 없으며, DMA를 통해 데이터 이동
3. 데이터 전송 방식
•DMA 컨트롤러를 사용하여 SPU의 로컬 스토어와 주메모리 간 데이터를 전송
•PS3의 메모리 구조는 병렬 처리를 극대화하기 위한 설계
3.5.5.2 PS2 스크래치패드
1. PS2의 메모리 구조
•PS2의 메인 CPU인 이모션 엔진에는 16KiB 스크래치패드 메모리 존재
•16KiB L1 명령어 캐시, 8KiB L1 데이터 캐시와 함께 동작
2. 스크래치패드의 역할
•L1 캐시와 달리 명확한 주소 공간을 가짐
•프로그램이 직접 제어하며 데이터를 저장 및 관리
3. 장점과 활용
•시스템 버스를 거치지 않고 데이터 접근 가능
•CPU가 다른 작업을 수행하는 동안 독립적으로 메모리 이동 가능
•DMA 요청을 통해 주메모리와 벡터 처리 장치 간 데이터를 전송