일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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)
- 프로그래밍 기초
- ColorGradingLutPass
- Cartoon Rendering
- Three(Two) Tone Shading
- Rim Light
- Windows Build
- Private Bytes
- working set
- 3d
- 메모리 누수
- OculusMotionVectorPass
- Cell Shader
- Toon Shader
- Cell Look
- Virtual Byte
- Specular
- C언어
- 개인 바이트
- AppSW
- URP로 변경
- 벡터
- 작업 집합
- 가상 바이트
- URP
- VR
- Today
- Total
WinCNT
프로세스와 스레드 본문
실제 작업하는 것은 스레드
그래서 worker thread라는 용어가 존재한다
스레드는 왜 필요한가?
모든 프로세스는 적어도 하나 이상의 스레드를 사용한다
스레드는 프로세스의 주소 공간 내에 있는 코드를 수행한다
스레드는 프로세스와 유사하게 두 개의 요소로 구성되어 있다
- 운영체제가 스레드를 다루기 위해 사용하는 스레드 커널 오브젝트
- 스레드가 코드를 수행할 때 함수의 매개변수와 지역변수를 저장하기 위한 스레드 스택
실행 코드와 데이터는 한 세트
함수 스택, 콜 스택 - 스레드 스택
함수 내부가 실행되는 건 스레드가 기반
비동기를 구현하기 위해 만들어진 것은 스레드 이외에도 존재한다
Co-routine 등
본격적으로 스레드가 사용되기 시작한 것은 하드웨어(CPU)의 개수가 2개 이상이 될 때부터
하지만 CPU가 1개였을 때에도 스레드는 존재했다
동기와 비동기에 대한 문제 등등
스레드를 사용하기 위해서는 설계부터 잘 고민해야 한다
- 무엇을 동시에 할 것인가
- 어떻게 동시에 할 것인가
예를 들어 단팥빵을 만든다고 할 때,
반죽하는 작업 / 팥 앙금을 만드는 작업으로 나눌 수 있을 것이다
그렇다면 반죽 - 팥 앙금 작업을 동시에 여러 명이 하는 방법이 있을테고
반죽과 팥 앙금 작업을 나눠서 하는 방법이 있을 것이다
이렇듯 동시에 한다고 해서 여러 방법이 존재한다
프로세스와 스레드
프로세스
프로세스는 일반적으로 수행 중인 프로그램의 인스턴스라고 정의
프로세스를 관리하기 위한 목적으로 운영 체제가 사용하는 프로세스 커널 오브젝트
실행 모듈이나 DLL의 코드와 데이터를 수용하는 주소 공간(스레드 스택, 힙 할당)
※ 힙 영영은 공용 공간 - 포인터만 있으면 어떤 스레드에서도 접근 가능하다
스레드
스레드는 프로세스의 주소 공간 내의 코드를 수행
운영체제가 스레드를 다루기 위한 스레드 커널 오브젝트
스레드가 코드를 수행할 때 함수의 매개변수와 지역변수를 저장하기 위한 스레드 스택
스레드의 필요성
프로세스는 자신만의 주소 공간을 가지기 때문에 많은 시스템 리소스를 사용한다
반면, 스레드는 프로세스에 비해 상당히 적은 시스템 리소스가 필요하다
(커널 오브젝트와 스레드 스택 정도만 필요함)
하지만 스레드가 프로세스에 비해 부하가 적다고 해도
경우에 따라서는 여러 개의 프로세스를 이용하는 방법이 더 좋기도 하다
따라서 추가적으로 스레드를 생성하는 설계를하기 전에
다음과 같은 판단 기준으로 잘 생각해 보는 것이 좋다
판단의 기준 1. 성능 이슈
스레드를 사용하면 필연적으로 복잡도 증가하며 구현의 어려워진다
즉, 안전성 확보가 중요하다
판단의 기준 2. 구조 설계와 전략
설계가 구체적이어야 하며, 설계에 대해 논리적인 설명이 가능해야 한다
또한 예외 상황에 대한 고려가 필요하다
스레드가 사용된 예
스레드가 사용된 구체적인 예로는 백그라운드 서비스, Visual Studio의 컴파일 에러 체크,
엑셀의 재계산 작업, 디스크 조각 모음의 백그라운드 수행 등이 있다
(대체적으로 백그라운드 작업 처리를 할 때 사용된 경우가 많음)
반대로 스레드를 이용한 UI(유저 인터페이스) 구현은 가능한 피하는 것이 좋다
게임에서 스레드가 사용되는 예
렌더 스레드 - 물리 스레드
렌더 스레드 - 물리 스레드 등에 사용될 수 있다
(물론 모든 렌더 스레드, 물리 스레드에 사용하지 않음)
물리 연산이 비쌀 때, 렌더 스레드에 영향을 방지하기 위해 사용할 수 있다
(새 떼를 구현할 때 등)
리소스 로딩, 맵 이동
스레드를 이용하여 백그라운드로 일부 리소스를 미리 메모리에 로딩해두는 방법이 있다
전부 로딩하면 스타팅이 오래 걸리고, 전부 필요할 때만 로딩하면 이동에 오래 걸리는데
그걸 방지할 수 있음
게임 서버 구조
분산 구조 - 프로세스 분산
내부 구조 - 멀티 스레드 분산
프로세스 분산 - 기능 분산, 확장성을 위해 주로 사용
프로세스 분산은 물리적으로 분산이 가능하다는 말이기도 하다
(스레드로 분산하면 물리적으로 분산이 불가능함)
예) 로그인 서버 - 게임 서버의 분산
복잡도(예외 처리 등)는 올라가지만 확장성의 증가가 더 크기 때문에 구현한다(...)
스레드 분산
기능 분산과 병렬 분산
방(대기실)을 만드는 스레드를 만들었을 경우,
CPU가 많을 때 여러 스레드를 사용할 수 있게 된다
스레드 함수
작업 스레드가 수행하는 것은 함수 단위이므로 함수가 필요하다
또한 함수는 리턴 타입, 함수 이름, 파라메터가 필요하며 함수의 호출은 커널이 수행할 것이다
스레드가 수행하는 것은 함수 단위
스레드는 수행할 함수를 커널에게 맡긴다
그러면 커널이 수행할 수 있을 때 수행할 것이다
작업 흐름을 제어하는 방법에는 2가지가 있다
스레드 간의 통신을 통해 스레드의 작업 시작을 컨트롤하는 방법
API를 이용하여 커널에게 맡길 때 플래그로 스레드의 작업 시작을 컨트롤하는 방법
스레드의 생성
스레드를 생성하는 함수는 3가지가 있다
CreateThread 함수, _beginthread 함수, _beginthreadex 함수
하지만 결론부터 말하자면 _beginthreadex 함수을 사용하는 것이 좋다
일단 CreateThread 함수는 다음과 같은 매개변수를 갖는다
HANDLE CreateThread(
[in, optional] LPSECURITY_ATTRIBUTES lpThreadAttributes,
[in] SIZE_T dwStackSize,
[in] LPTHREAD_START_ROUTINE lpStartAddress,
[in, optional] __drv_aliasesMem LPVOID lpParameter,
[in] DWORD dwCreationFlags,
[out, optional] LPDWORD lpThreadId
);
여기서 중요한 것은 lpStartAddress와 lpParameter이다
lpStartAddress는 스레드가 수행할 함수 포인터를 지정한다
lpParameter에는 사라질 가능성이 없는 변수(주소)를 넘겨야 한다
(그래서 보통 Heap 영역의 주소를 넘기며, Stack 영역의 주소를 넘기진 않음)
코드 생성 - 런타임 라이브러리
서버 - 다중 스레드(/MT) = 설치가 힘들 때
클라이언트 - 다중 스레드 DLL(/MD) = 설치가 가능할 때
스레드의 내부
스레드의 함수 포인터는 커널 입장에서는 main 함수와 같은 진입점과 같다
스레드는 내부에서 스레드의 흐름을 컨트롤할 수 있지만
외부에서도 핸들을 가지고 컨트롤할 수 있다
C/C++ 런타임 라이브러리에 대한 고찰
참고 사이트)
https://docs.microsoft.com/ko-kr/cpp/build/reference/md-mt-ld-use-run-time-library?view=msvc-170
https://docs.microsoft.com/ko-kr/cpp/windows/deployment-concepts?view=msvc-170
번외) Resource acquisition is initialization(RAII)
RAII는 디자인 패턴 중 하나
리소스의 획득과 해방은 클래스형 변수의 초기화와 파괴 처리에 연결한다라는 디자인 패턴이다
참고 사이트)
https://docs.microsoft.com/ko-kr/cpp/cpp/welcome-back-to-cpp-modern-cpp?view=msvc-170
https://dydtjr1128.github.io/cpp/2020/04/05/Cpp-lock.html
https://lipcoder.tistory.com/entry/DirectX-12-COMComponent-Object-Model
SSS
'게임 프로그래밍(학습 내용 정리) > 시스템 프로그래밍' 카테고리의 다른 글
Exception Filter (0) | 2022.03.22 |
---|---|
실제 핸들과 허위 핸들(Pseudo Handle) (0) | 2022.03.22 |
커널 오브젝트와 프로세스 (0) | 2022.03.14 |
커널 오브젝트 (0) | 2022.03.08 |
시스템 프로그래밍이란 무엇인가? (0) | 2022.03.07 |