CS โ context switching
๐ 05/12 โ Context Switching์ ๋ํด์ ์ค๋ช ํด ์ฃผ์ธ์
๋ชจ์๋ฉด์ ์ฃผ์ : โContext Switching์ ๋ํด์ ์ค๋ช ํด ์ฃผ์ธ์โ ์ ์ยท๋ฐ์ ์์ โ PCB/TCB ์ ์ฅยท๋ณต์ โ ๋ชจ๋ ์ค์์น โ ์ปจํ ์คํธ ์ค์์น โ ๋น์ฉ ์์(์บ์ flushยทTLB flushยทํ์ดํ๋ผ์ธ ์ ์ง) โ ํ๋ก์ธ์ค vs ์ค๋ ๋ ๋น์ฉ ์ฐจ โ ์ค์ผ์ค๋ง ์๊ณ ๋ฆฌ์ฆ๊ณผ์ ์ฐ๊ด โ Windows ๊น์ด(Win32 ์ค๋ ๋ APIยท๋๊ธฐํ ๊ฐ์ฒดยทConcRT/PPLยทFiberยทUMSยทC++ ํ์ค ๋งคํยทTLSยทCRT ์ต์ ) โ ์ธ๋ฆฌ์ผ(
FRunnableThreadยทTaskGraphยทGameThread/RenderThread/RHIThread)๊น์ง
ํ์ต ์์ญ โ 19ยท20๋ฒ์์ ํ์๋ OSยท๋์์ฑ ํ๊ท
19๋ฒ์์ ํ๋ก์ธ์ค/์ค๋ ๋์ ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ ๋ฆฌํ๋ฉด์ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ ํต์ฌ ์ฐจ์ด ์ ์ค ํ๋๋ก ๋ค๋ค๊ณ , 20๋ฒ์์ ์คํ ์ค๋ฒํ๋ก์ ์ค๋ ๋๋ณ ๋ ๋ฆฝ ์คํ์ ๋ค๋ค์ต๋๋ค. 21๋ฒ์ ๊ทธ ์ฌ์ด ๋ค๋ฆฌ์ ํด๋นํ๋ โ์ค๋ ๋ ์ ํ ์์ฒด๊ฐ ์ด๋ป๊ฒ ์ผ์ด๋๊ณ ์ ๋น์ผ๊ฐโ๋ฅผ ๋ณธ ์ฃผ์ ๋ก ๋์ด์ฌ๋ฆฝ๋๋ค.
1
2
3
4
5
6
7
8
01๋ฒ ๋ฉ๋ชจ๋ฆฌ 4์์ญ (Code/Data/Heap/Stack) โ ํ์ด์ง ํ
์ด๋ธยท๊ฐ์ ๋ฉ๋ชจ๋ฆฌ ํ ๋
03๋ฒ new vs malloc (ํ vs ์คํ) โ ์บ์ ๋์ ์ดํด ํ ๋
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
19๋ฒ ํ๋ก์ธ์ค vs ์ค๋ ๋ โ PCB/TCBยท์ปจํ
์คํธ ๋น์ฉ 5~10๋ฐฐ ์ฐจ์ด ์ฒซ ๋ฑ์ฅ
20๋ฒ Stack Overflow (์ค๋ ๋๋ณ ๋
๋ฆฝ ์คํ) โ SPยท๊ฐ๋ ํ์ด์งยท์คํ ํ๊ณ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
21๋ฒ Context Switching (โ
) โ ๋ณธ ์ฃผ์ ํ์ฅ
์ดํ ๊ฐ์ ๋ฉ๋ชจ๋ฆฌยทํ์ด์ง / ์ค์ผ์ค๋ฌ ์๊ณ ๋ฆฌ์ฆ / ์บ์ ์ผ๊ด์ฑ (MESI)
์ปจํ
์คํธ ์ค์์นญ์ OS ์ค์ผ์ค๋ฌ + CPU ๋ง์ดํฌ๋ก์ํคํ
์ฒ + ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ + ์บ์ ๊ณ์ธต์ด ๋ชจ๋ ๋ง๋๋ ์ง์ ์
๋๋ค. ๊ทธ๋์ ํ ์ฃผ์ ์์ OSยทํ๋์จ์ดยท์ปดํ์ผ๋ฌยท์ธ์ด ํ์คยทํ๋ซํผ API๊ฐ ๋์์ ๋ฑ์ฅํฉ๋๋ค. Windows๋ ํนํ CreateThreadยทCritical SectionยทSRWLockยทFiberยทUMS ๊ฐ์ ํ๋ถํ API ๊ณ์ธต์ ๊ฐ์ง๊ณ ์์ด์, MSVC ๋ฌธ์๋ฅผ ๋ฐ๋ผ ๋ด๋ ค๊ฐ๋ฉด โ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ โ ์ปค๋ ๋ชจ๋ ๊ฐ์ โ ๊น์ง์ ๋น์ฉ ์คํํธ๋ผ์ ๋จ๊ณ๋ณ๋ก ๋ณผ ์ ์์ต๋๋ค.
๋ชจ์๋ฉด์ ๋ต๋ณ
์ปจํ ์คํธ ์ค์์นญ์ CPU ์ฝ์ด ์์์ ์คํ๋๋ ํ ์คํ ๋จ์(์ค๋ ๋ ๋๋ ํ๋ก์ธ์ค)๋ฅผ ์ ์ ๋ด๋ ค๋๊ณ , ๋ค๋ฅธ ์คํ ๋จ์๋ก ๊ฐ์๋ผ์ฐ๋ ๊ณผ์ ์ ๋๋ค. ํต์ฌ์ ํ์ฌ ์คํ ์ค์ด๋ ๋จ์์ ์ํ(๋ ์ง์คํฐยทSPยทPC ๋ฑ)๋ฅผ ์์ง ์๋๋ก ๋ฉ๋ชจ๋ฆฌ์ ์ ์ฅํ๊ณ , ์๋ก ๋ค์ด์ฌ ๋จ์์ ์คํ ์ํ๊ฐ ๋ฉ์ท๋ ์์ ๊ทธ๋๋ก ๋ณต์๋๋๋ก ์ ์ฅ๋ ์ปจํ ์คํธ๋ฅผ ๋ฉ๋ชจ๋ฆฌ์์ CPU ๋ ์ง์คํฐ๋ก ์ ์ฌํ๋ ๊ฒ์ ๋๋ค. ์ด ์ํ๋ฅผ โ์ปจํ ์คํธ(context)โ๋ผ ๋ถ๋ฅด๊ณ , ๊ทธ๋์ ์ด ์์ ์ ์ด๋ฆ์ด ์ปจํ ์คํธ ์ค์์นญ(context switching)์ ๋๋ค. OS๋ ์ด ์ ๋ณด๋ฅผ PCB(Process Control Block, ํ๋ก์ธ์ค ์ ์ด ๋ธ๋ก)์ TCB(Thread Control Block, ์ค๋ ๋ ์ ์ด ๋ธ๋ก)๋ผ๋ ์ปค๋ ์๋ฃ๊ตฌ์กฐ์ ์ ์ฅํฉ๋๋ค.
์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋๋ ๊ฒฝ์ฐ๋ ํฌ๊ฒ ๋ค ๊ฐ์ง๋ก ๋๋ฉ๋๋ค. ํ ๋จ๋ฝ์ ์ฃฝ ๋์ด๋๊ธฐ๋ณด๋ค ๊ธ๋จธ๋ฆฌํ๋ก ๋ถ๋ฆฌํ๋ ๊ฒ ์ ํํฉ๋๋ค.
- ํ์ด๋จธ ์ธํฐ๋ฝํธ(timer interrupt) ๋ง๋ฃ โ OS ์ค์ผ์ค๋ฌ๊ฐ ๋งค ์ค๋ ๋์ ํ ๋นํด ๋ ์๊ฐ ์กฐ๊ฐ(time slice, ๋ณดํต ์ ms)์ด ๋๋๋ฉด ๊ฐ์ ๋ก ์ค์์นญํฉ๋๋ค. ์ ์ ํ ์ค์ผ์ค๋ง์ ๋ณธ์ฒด์ ๋๋ค.
- ๋ธ๋กํน I/O ๋๋ ์์คํ
์ฝ โ
read()ยทrecv()ยทWaitForSingleObject()์ฒ๋ผ ๋๊ธฐ๋ฅผ ๋๋ฐํ๋ ํธ์ถ์ ๋ง๋๋ฉด ๊ทธ ์ค๋ ๋๋ ์ฆ์ Wait ์ํ๋ก ์ ํ๋๊ณ , ์ค์ผ์ค๋ฌ๊ฐ ๋ค๋ฅธ Ready ์ค๋ ๋๋ฅผ ๊ณจ๋ผ ์คํํฉ๋๋ค. - ๋๊ธฐํ ๊ฐ์ฒด ๋๊ธฐ โ mutexยทsemaphoreยทevent๋ฅผ ๊ธฐ๋ค๋ฆฌ๊ฑฐ๋ condition variable์์ ์ ๋ค๋ฉด ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ผ์ด๋ฉ๋๋ค. ๊นฌ ๋ค ๋ค์ Ready ํ์ ๋ค์ด๊ฐ๋ค๊ฐ ์ปจํ ์คํธ ์ค์์นญ์ผ๋ก ๋ณต๊ทํฉ๋๋ค.
- ์๋ฐ์ ์๋ณด(voluntary yield) โ
Sleep(0)ยทSwitchToThreadยทstd::this_thread::yield์ฒ๋ผ ์ค๋ ๋๊ฐ ์ง์ CPU๋ฅผ ๋ด๋ ค๋๋ ๊ฒฝ์ฐ์ ๋๋ค. ์ด๋๋ ์ค์ผ์ค๋ฌ๊ฐ ๋ค์ ํ๋ณด๋ฅผ ๊ฒฐ์ ํ๊ณ ์ค์์นญํฉ๋๋ค.
์ฌ๊ธฐ์ ์์ฃผ ํท๊ฐ๋ฆฌ๋ ๊ฒ ๋ชจ๋ ์ค์์น(mode switch)์ ์ปจํ ์คํธ ์ค์์น(context switch)์ ์ฐจ์ด์ ๋๋ค. ๋ชจ๋ ์ค์์น๋ ๊ฐ์ ์ค๋ ๋ ์์์ ์ฌ์ฉ์ ๋ชจ๋(user mode)์ ์ปค๋ ๋ชจ๋(kernel mode)๋ฅผ ์ค๊ฐ๋ ๊ฒ์ผ๋ก, ์์คํ ์ฝ ํธ์ถ์ด๋ ํ๋์จ์ด ์ธํฐ๋ฝํธ ์ฒ๋ฆฌ ์ ๋ฐ์ํฉ๋๋ค. ๋ ์ง์คํฐ๋ฅผ ์ผ๋ถ ์ ์ฅยท๋ณต์ํ๊ธด ํ์ง๋ง ์คํ ์ฃผ์ฒด(์ค๋ ๋)๊ฐ ๋ฐ๋์ง ์์ผ๋ฏ๋ก PCBยทTCB ๊ต์ฒด๊ฐ ์๊ณ , ๋น์ฉ๋ ํจ์ฌ ์์ต๋๋ค. ์ปจํ ์คํธ ์ค์์น๋ ๋ณดํต ๋ชจ๋ ์ค์์น ์์์ ์ผ์ด๋์ง๋ง, ๋ชจ๋ ์ค์์น๊ฐ ์๋ค๊ณ ํญ์ ์ปจํ ์คํธ ์ค์์น๊ฐ ์ผ์ด๋๋ ๊ฑด ์๋๋๋ค โ ์์คํ ์ฝ์ด ์ฆ์ ๋๋๋ฉด ๊ฐ์ ์ค๋ ๋๊ฐ ์ฌ์ฉ์ ๋ชจ๋๋ก ๋์์ฌ ๋ฟ ๋ค๋ฅธ ์ค๋ ๋๋ก ๊ฐ์๋ผ์ฐ์ง ์์ต๋๋ค.
๋น์ฉ์ ์ฌ๋ฌ ์ธต์์ ๋์ ๋ฉ๋๋ค. ์ด๊ฒ๋ ๊ธ๋จธ๋ฆฌํ๋ก ์ ๋ฆฌํฉ๋๋ค.
- ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ โ ๋ฒ์ฉ ๋ ์ง์คํฐ(general purpose register), SP(Stack Pointer, ์คํ ํฌ์ธํฐ), PC(Program Counter, ํ๋ก๊ทธ๋จ ์นด์ดํฐ), ํ๋๊ทธ ๋ ์ง์คํฐ, FPUยทSIMD ๋ ์ง์คํฐ(x86_64์์ XMMยทYMMยทZMM)๋ฅผ PCB/TCB๋ก ์ฎ๊ธฐ๋ ์ง์ ๋น์ฉ. ๋ณดํต ์๋ฐฑ nanosecond.
- ์บ์ ์ฝ๋(cache cold) โ ์ ์ค๋ ๋์ ๋ฐ์ดํฐยท๋ช ๋ น์ด๊ฐ L1ยทL2 ์บ์์ ์์ด ์ง์ ์งํ ์ค์ค์ด ์บ์ ๋ฏธ์ค(cache miss)๊ฐ ๋ฐ์ํฉ๋๋ค. ์ด๊ฒ ์ง์ ๋น์ฉ๋ณด๋ค ํจ์ฌ ํฐ ๊ฐ์ ๋น์ฉ์ ๋๋ค.
- TLB(Translation Lookaside Buffer, ์ฃผ์ ๋ณํ ์บ์) flush โ ํ๋ก์ธ์ค ์ ํ์์๋ง ์ผ์ด๋ฉ๋๋ค. ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ด ๋ฐ๋๋ฏ๋ก MMU(Memory Management Unit, ๋ฉ๋ชจ๋ฆฌ ๊ด๋ฆฌ ์ ๋)๊ฐ ์บ์ฑํด๋๋ ๊ฐ์โ๋ฌผ๋ฆฌ ๋งคํ์ ๋น์์ผ ํ๊ณ , ์ดํ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ๋ง๋ค ํ์ด์ง ํ ์ด๋ธ ์ํฌ(page table walk)๊ฐ ๋ค์ ์ผ์ด๋ฉ๋๋ค. ๊ฐ์ ํ๋ก์ธ์ค ๋ด ์ค๋ ๋ ์ ํ์์ ๋ฐ์ํ์ง ์์ต๋๋ค.
- ํ์ดํ๋ผ์ธ ์ ์ง(pipeline stall)์ ๋ถ๊ธฐ ์์ธก๊ธฐ(branch predictor) ๋ฌดํจํ โ CPU์ instruction pipeline์ ๋ค์ด ์๋ ๋ช ๋ น๋ค์ด ๋ชจ๋ ํ๊ธฐ๋๊ณ , ๋ถ๊ธฐ ์์ธก๊ธฐ๊ฐ ํ์ตํด ๋ ํจํด๋ ์ ์ค๋ ๋ ์ฝ๋์ ์ด๊ธ๋ ์ ์ ์ ํ๋๊ฐ ๋จ์ด์ง๋๋ค.
- ์ปค๋ ์ง์ ๋น์ฉ โ ์์คํ ์ฝ๋ก ์ง์ ํด ์ค์ผ์ค๋ฌ๋ฅผ ์คํํ๊ณ ๋ค์ ์ฌ์ฉ์ ๋ชจ๋๋ก ๋์์ค๋ ๋ฐ ๋๋ ๋ชจ๋ ์ค์์น ์์ฒด ๋น์ฉ.
ํ๋ก์ธ์ค ์ปจํ ์คํธ ์ค์์น์ ์ค๋ ๋ ์ปจํ ์คํธ ์ค์์น์ ๋น์ฉ ์ฐจ์ด๋ ์ด ๋น์ฉ ํญ๋ชฉ ์ค ์ด๋ ๊ฒ์ด ๋ฐ์ํ๋๋๋ก ๊ฒฐ์ ๋ฉ๋๋ค. ์ค๋ ๋ ์ ํ์ ๊ฐ์ PCB(๊ฐ์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ) ์์์ TCB๋ง ๋ฐ๊พธ๋ฏ๋ก ํ์ด์ง ํ ์ด๋ธ ๋ฒ ์ด์ค ๋ ์ง์คํฐ(x86 CR3)๋ฅผ ๊ทธ๋๋ก ๋๊ณ TLBยทํธ๋ค ํ ์ด๋ธ๋ ๋ณด์กด๋ฉ๋๋ค. ํ๋ก์ธ์ค ์ ํ์ CR3๋ฅผ ๊ต์ฒดํ๊ณ TLB๋ฅผ ๋น์์ผ ํ๋, ์งํ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ๋ชจ๋ TLB miss๋ก ์์ํฉ๋๋ค. ๊ทธ๋์ ์ผ๋ฐ์ ์ผ๋ก ์ค๋ ๋ ์ ํ์ด ํ๋ก์ธ์ค ์ ํ๋ณด๋ค 5~10๋ฐฐ ๋น ๋ฅด๋ค๋ ๋ง์ด ๋์ต๋๋ค โ 19๋ฒ์์ ์ ๋ฆฌํ ๊ทธ๋๋ก์ ๋๋ค. ๋ค๋ง ์ต๊ทผ CPU๋ ASID(Address Space ID) ๋๋ PCID(Process Context ID, x86)๋ก TLB ์ํธ๋ฆฌ๋ฅผ ํ๋ก์ธ์ค๋ณ๋ก ํ๊น ํด์ ์ ํ ์ ์ ์ฒด flush๋ฅผ ํํผํ๊ธฐ๋ ํฉ๋๋ค. ๊ทธ๋๋ ์บ์ ์ฝ๋๋ ํผํ ์ ์์ต๋๋ค.
์ค์ผ์ค๋ง ์๊ณ ๋ฆฌ์ฆ์ด ์ปจํ ์คํธ ์ค์์นญ์ ๋น๋์ ์ ์ฑ ์ ๊ฒฐ์ ํฉ๋๋ค. ์ ์ ํ(preemptive) ์ค์ผ์ค๋ง์ ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก ๊ฐ์ ์ค์์นญ์ ์ผ์ผํค๋ ๋ชจ๋ธ๋ก WindowsยทLinux์ ํ์ค์ด๊ณ , ๋น์ ์ ํ(non-preemptive)ยทํ๋ ฅ์ (cooperative) ์ค์ผ์ค๋ง์ ์ค๋ ๋๊ฐ ์๋ฐ์ ์ผ๋ก ์๋ณดํ ๋๋ง ์ค์์นญํ๋ ๋ชจ๋ธ์ ๋๋ค. ๋ผ์ด๋ ๋ก๋น(Round-Robin)์ ๋ชจ๋ Ready ์ค๋ ๋์ ๊ฐ์ time slice๋ฅผ ๋๋ฆฌ๋ ๋ฐฉ์, ์ฐ์ ์์ ์ค์ผ์ค๋ง(priority scheduling)์ ์ฐ์ ์์ ์์๋๋ก ๋์คํจ์นํ๋ ๋ฐฉ์, MLFQ(Multi-Level Feedback Queue)๋ ๊ทธ ๋์ ๊ฒฐํฉํด ์ธํฐ๋ํฐ๋ธ ์์ ๊ณผ ๋ฐฐ์น ์์ ์ ์๋ ๋ถ๋ฅํ๋ ๋ฐฉ์์ ๋๋ค. time slice๋ฅผ ์งง๊ฒ ์ก์ผ๋ฉด ์๋ต์ฑ์ด ์ข์์ง์ง๋ง ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ด ๋์ ๋๊ณ , ๊ธธ๊ฒ ์ก์ผ๋ฉด throughput์ด ์ข์์ง์ง๋ง ์๋ต์ฑ์ด ๋จ์ด์ง๋ ํธ๋ ์ด๋์คํ๊ฐ ์์ต๋๋ค. Windows๋ ๋ณดํต ์ฝ 15.6ms๋ฅผ ๊ธฐ๋ณธ quantum์ผ๋ก ์ฐ๊ณ , ๋ฉํฐ๋ฏธ๋์ด ํ์ด๋จธ API๋ก 1ms๊น์ง ์ค์ผ ์ ์์ต๋๋ค.
Windows ๊ด์ ์์ ๋ณด๋ฉด ๋น์ฉ์ ์ค์ด๋ ๋จ๊ณ๊ฐ ์ฌ๋ฌ ์ธต์
๋๋ค. Win32 ์ค๋ ๋ API(CreateThread, WaitForSingleObject)๋ ํญ์ ์ปค๋ ๋ชจ๋๋ฅผ ๊ฑฐ์น๊ณ , Critical Section์ ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ ยท๊ฒฝํฉ ์์๋ง ์ปค๋ ์ง์
(SRWLock๋ ๋น์ท), Concurrency Runtime/PPL์ ๊ทธ ์์ ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ Task Scheduler๋ฅผ ๋์ด ์ปจํ
์คํธ ์ค์์นญ์ ๋ ํํผ, Fiber API(CreateFiber/SwitchToFiber)๋ ์์ ์ปค๋ ๊ฐ์
์๋ ํ๋ ฅ์ ์ค์์นญ, UMS(User-Mode Scheduling)๋ ๊ทธ ๋์ ์ ์ถฉ ๋ชจ๋ธ์
๋๋ค. C++ ํ์ค์ std::threadยทstd::mutex๋ Windows์์ ๊ฒฐ๊ตญ ์ด ์์ ๋งคํ๋๊ณ , MSVC ๋ฐํ์์ด SRWLock ๊ฐ์ ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์ ํํด ๋น์ฉ์ ๋ฎ์ถฅ๋๋ค. ๊ทธ๋์ โ์ปจํ
์คํธ ์ค์์นญ์ด ๋น์ธ๋คโ๋ ์ผ๋ฐ๋ก ์ ๋ง์ง๋ง, ์ด๋ค ๋๊ธฐํ ๋๊ตฌ๋ฅผ ๊ณ ๋ฅด๋๋์ ๋ฐ๋ผ ๊ฐ์ ์์
์ด 100๋ฐฐ๊น์ง ๋นจ๋ผ์ง ์ ์์ต๋๋ค. ์ธ๋ฆฌ์ผ ์์ง๋ ์ด ์๋ฆฌ๋ฅผ ๋ฐ๋ผ GameThreadยทRenderThreadยทRHIThread๋ฅผ ๋ถ๋ฆฌํ๊ณ ๊ทธ ์ฌ์ด๋ฅผ ๋ช
๋ น ํ(command queue)๋ก ์ฐ๊ฒฐํด ๋๊ธฐํ ๋น๋๋ฅผ ์ต์ํํฉ๋๋ค. ๊ฒฐ๊ตญ ์ปจํ
์คํธ ์ค์์นญ์ ํผํ ์ ์๋ OS ๋ฉ์ปค๋์ฆ์ด๊ณ , ์์ง๋์ด๋ง์ ๊ทธ ๋น๋์ ๋น์ฉ์ ์ค์ด๋ ๋ฐฉํฅ์ผ๋ก ๊ฐ๋ ๊ฒ ํต์ฌ์
๋๋ค.
ํต์ฌ ๊ฐ๋
| ๋ถ๋ฅ | ํค์๋ | ํ ์ค ์ ์ |
|---|---|---|
| ์ ์ | ์ปจํ ์คํธ ์ค์์นญ (Context Switching) | CPU ์ฝ์ด์์ ์คํ๋๋ ์ค๋ ๋/ํ๋ก์ธ์ค๋ฅผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๊ฐ์๋ผ์ฐ๋ OS ์์ |
| ย | ์ปจํ ์คํธ (Context) | ์ค๋ ๋ ์คํ์ ์ฌ๊ฐํ๋ ๋ฐ ํ์ํ ๋ชจ๋ ์ํ (๋ ์ง์คํฐยทSPยทPCยทํ๋๊ทธยทFPU ๋ฑ) |
| ย | ๋ชจ๋ ์ค์์น (Mode Switch) | ๊ฐ์ ์ค๋ ๋ ์์์ user mode โ kernel mode ์ ํ. PCB ๊ต์ฒด ์์ |
| ย | ์ธํฐ๋ฝํธ (Interrupt) | ์ธ๋ถ ์ฅ์นยทCPU ์์ธยทsyscall ๋ช
๋ น์ด ํ์ฌ ์คํ ํ๋ฆ์ ์ค๋จ์ํค๊ณ IDT์ ๋ฑ๋ก๋ ํธ๋ค๋ฌ๋ก ๊ฐ์ ์ ํ์ํค๋ ๋ฉ์ปค๋์ฆ. ๋ชจ๋ ์ค์์น์ ์ฃผ๋ ํธ๋ฆฌ๊ฑฐ |
| ์๋ฃ๊ตฌ์กฐ | PCB (Process Control Block, ํ๋ก์ธ์ค ์ ์ด ๋ธ๋ก) | OS๊ฐ ํ๋ก์ธ์ค ์ ๋ณด ๊ด๋ฆฌํ๋ ๊ตฌ์กฐ์ฒด (PIDยทํ์ด์ง ํ ์ด๋ธยทํธ๋คยท๋ฉ๋ชจ๋ฆฌ๋งต) |
| ย | PCB์ ์ญํ | โ ํ๋ก์ธ์ค ์๋ณ(PID) โก ์ฃผ์ ๊ณต๊ฐ ๊ฒฉ๋ฆฌ(ํ์ด์ง ํ
์ด๋ธ ๋ฒ ์ด์ค ๋ณด๊ด) โข ์์ ๊ด๋ฆฌ(์ด๋ฆฐ ํ์ผยทํธ๋คยท์๊ทธ๋) โฃ ์ค์ผ์ค๋ง ์ํ ์ถ์ (Ready/Running/Wait) โค ์ปจํ
์คํธ ์ค์์น ์ ์ ์ฅ ๋งค์ฒด. Windows์์ EPROCESS, Linux์์ task_struct |
| ย | TCB (Thread Control Block, ์ค๋ ๋ ์ ์ด ๋ธ๋ก) | ์ค๋ ๋ ์ ๋ณด (TIDยท๋ ์ง์คํฐ ์ปจํ ์คํธยทSPยทPCยท์ฐ์ ์์ยท์ํ) |
| ๋ฐ์ ์์ | ํ์ด๋จธ ์ธํฐ๋ฝํธ | quantum(time slice) ๋ง๋ฃ ์ OS๊ฐ ๊ฐ์ ์ค์์นญ |
| ย | ๋ธ๋กํน ์์คํ ์ฝ | readยทrecvยทWaitForSingleObject โ ๋๊ธฐ ๋๋ฐ ํธ์ถ |
| ย | ๋๊ธฐํ ๋๊ธฐ | mutexยทsemaphoreยทeventยทcondition variable์์ ๋ธ๋ก |
| ย | ์๋ฐ์ ์๋ณด (yield) | Sleep(0)ยทSwitchToThreadยทstd::this_thread::yield |
| ๋ ์ง์คํฐ | ๋ ์ง์คํฐ (Register) | CPU ์ฝ์ด ๋ด๋ถ์ ์ด๊ณ ์ ์ ์ฅ ๊ณต๊ฐ(64bit ร ์์ญ ๊ฐ). ๋ชจ๋ ์ฐ์ฐ์ด ๊ทธ ์์์ ์ผ์ด๋๊ณ , ์ค๋ ๋ ์คํ ์ํ(PCยทSPยท์ค๊ฐ๊ฐ)๊ฐ ์ฌ๊ธฐ ๋ด๊ฒจ ์ปจํ ์คํธ ์ค์์นญ์ ๋ฐฑ์ ๋์์ด ๋๋ค |
| ย | ๋ ์ง์คํฐ vs ๋ฉ๋ชจ๋ฆฌ | ๋ ๋ค โ๋ฐ์ดํฐ ์ ์ฅ ๊ณต๊ฐโ์ด์ง๋ง ์์นยท์๋๊ฐ ๋ค๋ฆ. ๋ ์ง์คํฐ๋ CPU ์ฝ์ด ๋ด๋ถ (0.3ns), RAM์ CPU ๋ฐ ๋ฉ๋ชจ๋ฆฌ ์ฌ๋กฏ (~100ns). ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต์ ์ต์์ ๋จ์ผ๋ก ๋ณดํต โ๋ฉ๋ชจ๋ฆฌโ๋ผ ๋ถ๋ฅด์ง ์์ โ ์ด์์ฒด์ ๊ต๊ณผ์์์๋ โ๋ ์ง์คํฐ โ ๋ฉ๋ชจ๋ฆฌโ๋ก ๊ตฌ๋ถ |
| ย | PC (Program Counter) | ๋ค์ ์คํํ ๋ช ๋ น์ด ์ฃผ์. ๋ณต์์ ํต์ฌ |
| ย | SP (Stack Pointer) | ์ค๋ ๋ ์๊ธฐ ์คํ์ ์ต์๋จ. TCB์ ์ ์ฅ |
| ย | ๋ฒ์ฉ ๋ ์ง์คํฐ (GPR) | x86_64: raxยทrbxยทrcxยทrdxยทrsiยทrdiยทr8~r15 |
| ย | FPU/SIMD ๋ ์ง์คํฐ | XMM/YMM/ZMM. ์ฌ์ฉ ์ lazy save๋ก ๋น์ฉ ์ ๊ฐ |
| ย | CR3 (ํ์ด์ง ํ ์ด๋ธ ๋ฒ ์ด์ค) | ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์๋ณ. ํ๋ก์ธ์ค ์ ํ ์ ๊ต์ฒด |
| ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต | ๋ฉ๋ชจ๋ฆฌ ๊ณ์ธต (Memory Hierarchy) | CPU โ ๋ ์ง์คํฐ(0.3ns) โ L1(~1nsยท32~64KB) โ L2(~3nsยท์๋ฐฑKB) โ L3(~10nsยท์MB) โ RAM(~100nsยทGB) โ SSD(~100ฮผs). ์๋ก ๊ฐ์๋ก ๋น ๋ฅด๊ณ ์์ |
| ย | L1/L2/L3 ์บ์ | RAM๊ณผ ๋ ์ง์คํฐ ์ฌ์ด์ SRAM ์บ์. L1ยทL2๋ ์ฝ์ด ์ ์ฉ, L3๋ ์ฝ์ด ๊ณต์ . ์ปจํ ์คํธ ์ค์์น ์งํ ์ ์ค๋ ๋ ๋ฐ์ดํฐ๊ฐ ์บ์์ ์์ผ๋ฉด โ์บ์ ์ฝ๋โ ๋ฐ์ |
| ย | SRAM vs DRAM | ๋ ์ง์คํฐยท์บ์๋ SRAM(ํธ๋์ง์คํฐ 6๊ฐ๋ก 1bit, ๋น ๋ฅด์ง๋ง ๋น์ธ๊ณ ํผ). RAM์ DRAM(ํธ๋์ง์คํฐ+์ปคํจ์ํฐ 1์, ๋๋ฆฌ์ง๋ง ์ธ๊ณ ์์ โ ๋์ฉ๋ ๊ฐ๋ฅ) |
| ๋น์ฉ ์์ | ์บ์ ์ฝ๋ (Cache Cold) | ์ ์ค๋ ๋ ๋ฐ์ดํฐ๊ฐ L1/L2์ ์์ด ๋ฏธ์ค ๋์ |
| ย | TLB flush | ๊ฐ์โ๋ฌผ๋ฆฌ ๋งคํ ์บ์ ๋ฌดํจํ. ํ๋ก์ธ์ค ์ ํ๋ง |
| ย | ํ์ดํ๋ผ์ธ ์ ์ง | instruction pipelineยท๋ถ๊ธฐ ์์ธก๊ธฐ ๋ฌดํจํ |
| ย | PCID/ASID | TLB ์ํธ๋ฆฌ๋ฅผ ํ๋ก์ธ์ค๋ณ ํ๊น ํด flush ํํผ (ํ๋ CPU) |
| ๋น๊ต | ํ๋ก์ธ์ค vs ์ค๋ ๋ ๋น์ฉ | ์ค๋ ๋ ์ ํ์ด 5~10๋ฐฐ ๋น ๋ฆ (TLBยทํ์ด์ง ํ ์ด๋ธ ๋ณด์กด) |
| ย | ์บ์ ํํธ์จ๋ก ๋ณธ ์ค๋ ๋ ์ฐ์ | ์ค๋ ๋ ์ ํ์ ๊ฐ์ ํ๋ก์ธ์ค์ ์ฝ๋ยทํยท์ ์ญ ๋ฐ์ดํฐ๊ฐ L1/L2/L3์ ๊ทธ๋๋ก ๋จ์์์ด ์บ์ ํํธ์จ ์ ์ง โ ์ฆ์ ๋น ๋ฅธ ์คํ. ํ๋ก์ธ์ค ์ ํ์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ๋ณ๊ฒฝ์ผ๋ก ์บ์ ์ฝ๋ + TLB flush โ ์บ์ ๋ฏธ์ค๊ฐ ๋์ ๋๋ฉฐ ์ค๋ ๋ ์ ํ๋ณด๋ค ๋๋ฆฐ ํต์ฌ ์ด์ |
| ์ค์ผ์ค๋ง | ์ ์ ํ (Preemptive) | ํ์ด๋จธ๋ก ๊ฐ์ ์ค์์นญ. WindowsยทLinux ํ์ค |
| ย | ๋น์ ์ ํ/ํ๋ ฅ์ (Cooperative) | ์๋ฐ์ ์๋ณด ์์๋ง ์ค์์นญ. Fiberยท์์ Windows 3.1 |
| ย | Round-Robin | ๋ชจ๋ ์ค๋ ๋ ๊ท ๋ฑ time slice |
| ย | ์ฐ์ ์์ ์ค์ผ์ค๋ง | ์ฐ์ ์์ ํฐ ์. ๊ธฐ์(starvation) ์ํ |
| ย | MLFQ (Multi-Level Feedback Queue) | ์ธํฐ๋ํฐ๋ธ/๋ฐฐ์น ์๋ ๋ถ๋ฅ. WindowsยทLinux CFS์ ์ ์กฐ |
| ย | time slice (quantum) | ํ ์ค๋ ๋์ ์ฐ์ ์คํ ํ์ฉ ์๊ฐ. Windows ๊ธฐ๋ณธ ์ฝ 15.6ms |
| Win32 ์ค๋ ๋ | CreateThread | ์ปค๋ ์ค๋ ๋ ์์ฑ. ํญ์ ์ปค๋ ์ง์ |
| ย | SwitchToThread | ๊ฐ์ ์ฝ์ด์ ๋ค๋ฅธ Ready ์ค๋ ๋๋ก ์ฆ์ ์๋ณด |
| ย | Sleep(0) | ๊ฐ์ ์ฐ์ ์์ ์ค๋ ๋์ ์๋ณด (์์ผ๋ฉด ์ฆ์ ๋ณต๊ท) |
| ย | WaitForSingleObject | ์ปค๋ ๊ฐ์ฒด(์ด๋ฒคํธยท๋ฎคํ ์คยท์ธ๋งํฌ์ด) ๋๊ธฐ |
| ย | SuspendThread/ResumeThread | ์ค๋ ๋ ๊ฐ์ ์ผ์์ ์ง/์ฌ๊ฐ (๋๋ฒ๊ฑฐยท์ธ๋ถ ์ ์ด์ฉ) |
| Win32 ๋๊ธฐํ | Critical Section | ์ฌ์ฉ์ ๋ชจ๋ spin โ ๊ฒฝํฉ ์ ์ปค๋ ์ง์ . ๊ฐ์ ํ๋ก์ธ์ค ๋ด๋ง |
| ย | Mutex | ์ปค๋ ๊ฐ์ฒด. ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ๊ฐ๋ฅ. ํญ์ ์ปค๋ ์ง์ |
| ย | Event / Semaphore | ์ปค๋ ๊ฐ์ฒด. WaitForSingleObject๋ก ๋๊ธฐ |
| ย | SRWLock (Slim Reader/Writer) | ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ R/W lock. Vista+ |
| ย | Condition Variable | SleepConditionVariableSRW. ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ |
| ConcRT/PPL | Concurrency Runtime | MSVC ์ฌ์ฉ์ ๋ชจ๋ Task Scheduler (/cpp/parallel/concrt/) |
| ย | Context::Block/Yield/Unblock | ํ๋ ฅ์ ์ปจํ ์คํธ ์๋ณด โ ์ฌ์ฉ์ ๋ชจ๋ |
| ย | work stealing | ํ๊ฐํ ์์ปค๊ฐ ๋ค๋ฅธ ํ์์ ์์ ํ์นจ |
| ย | oversubscription | ์ฝ์ด ์๋ณด๋ค ๋ง์ ์ค๋ ๋ ์๋์ ์ด์ฉ |
| Fiber/UMS | Fiber (CreateFiber) | ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ ์ค์์นญ. ์ปค๋ ๋ชจ๋ฆ |
| ย | SwitchToFiber | Fiber ๊ฐ ์ง์ ์ ํ. ์์ญ nanosecond |
| ย | UMS (User-Mode Scheduling) | ์ปค๋ ์ธ์ง + ์ฌ์ฉ์ ๋ชจ๋ ์ค์ผ์ค๋ง. Windows 7+/x64 |
| C++ ํ์ค | std::thread | Windows์์ _beginthreadex โ CreateThread ๋งคํ |
| ย | std::mutex | MSVC: SRWLock ๋๋ Critical Section ์ ๊ตฌํ |
| ย | std::atomic | CPU ๋ช ๋ น(LOCK XADDยทLOCK CMPXCHG). ์ปจํ ์คํธ ์ค์์นญ ์์ |
| ย | std::condition_variable | MSVC: Windows Condition Variable ์ |
| TLS | __declspec(thread) | MSVC TLS ๋ณ์. ์ค๋ ๋๋ณ ๋ ๋ฆฝ ์ฌ๋กฏ |
| ย | TlsAlloc/TlsGetValue | ๋์ TLS ์ฌ๋กฏ ๊ด๋ฆฌ |
| ย | TLS์ ์ปจํ ์คํธ ์ค์์นญ | TLS๋ ์ค๋ ๋ ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผ โ ์ค์์นญ ์ ์๋ ๋ณด์กด |
| CRT | /MT (์ ์ CRT) | CRT๋ฅผ exe์ ์ ์ ๋งํฌ. ๋ฉํฐ์ค๋ ๋ ์์ ํ ์ฌ์ฉ |
| ย | /MD (DLL CRT) | CRT๋ฅผ DLL๋ก ๋์ ๋งํฌ. ๊ถ์ฅ (UCRT) |
| ย | CRT ๋ฝ (_lock_file ๋ฑ) | stdioยทheap์ด ๋ด๋ถ์ ์ผ๋ก ๋ฝ โ ์ปจํ ์คํธ ์ค์์นญ ์ ๋ฐ ๊ฐ๋ฅ |
| ์ธ๋ฆฌ์ผ | GameThread | TickยทUObjectยทAActor ์ฒ๋ฆฌ. ๋ฉ์ธ ์ค๋ ๋ |
| ย | RenderThread | GameThread ๋ช ๋ น ๋ฐ์ RHI ๋ช ๋ น ์์ฑ |
| ย | RHIThread | GPU ๋๋ผ์ด๋ฒ ํธ์ถ ์ ๋ด (D3D12/Vulkan/Metal) |
| ย | TaskGraph | ์์กด์ฑ ๊ธฐ๋ฐ ์์ ๋ถํ . ์ปจํ ์คํธ ์ค์์นญ ์ต์ํ |
| ย | FRunnableThread | OS ์ค๋ ๋ ์ถ์ํ โ ๋ด๋ถ์ ์ผ๋ก CreateThread |
| ย | ENamedThreads | ์์ ์ ์ด๋ ์ค๋ ๋์ ๋์คํจ์นํ ์ง ๋ช ์ |
๋ชฉ์ฐจ
- ํต์ฌ ์์ฝ ์นด๋
- ํ ์ค ์ ์ โ ์ปจํ ์คํธ ์ค์์นญ์ด๋ ๋ฌด์์ธ๊ฐ
- ๋ฐ์ ์์ 4๊ฐ์ง โ ํ์ด๋จธยท์์คํ ์ฝยท๋๊ธฐํ ๋๊ธฐยท์๋ฐ์ ์๋ณด
- PCB/TCB ์ ์ฅยท๋ณต์ ๋จ๊ณ โ ๋ฌด์์ ์ด๋์ ์ ์ฅํ๋
- ๋ชจ๋ ์ค์์น โ ์ปจํ ์คํธ ์ค์์น โ ์์ฃผ ํท๊ฐ๋ฆฌ๋ ๊ตฌ๋ถ
- ๋น์ฉ ์์ โ ์บ์ flush ยท TLB flush ยท ํ์ดํ๋ผ์ธ ์ ์ง
- ํ๋ก์ธ์ค vs ์ค๋ ๋ ์ปจํ ์คํธ ์ค์์น ๋น์ฉ ๋น๊ต
- ์ค์ผ์ค๋ง ์๊ณ ๋ฆฌ์ฆ๊ณผ์ ์ฐ๊ด โ ์ ์ ํ/๋น์ ์ ํ/RR/์ฐ์ ์์
- Windows ๊ด์ โ Win32 ์ค๋ ๋ API์ ์ปจํ ์คํธ ์ค์์นญ
- Windows ๋๊ธฐํ ๊ฐ์ฒด๋ณ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ
- Concurrency Runtime / PPL โ ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ ์ค์ผ์ค๋ฌ
- Fiber API์ UMS โ ์ปค๋ ๊ฐ์ ์๋ ํ๋ ฅ์ ์ค์์นญ
- C++ ํ์ค ๋์์ฑ์ Windows ๋งคํ
- Thread Local Storage์ ์ปจํ ์คํธ ์ค์์นญ
- CRT ๋ฉํฐ์ค๋ ๋ ์ต์
โ
/MTvs/MD - ์ธ๋ฆฌ์ผ์์์ ์ปจํ ์คํธ ์ค์์นญ โ GameThread/RenderThread/RHIThread
- ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
- ํต์ฌ ์์ฝ ์นด๋ (์ฌ๊ฒ์ฌ)
- ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
1. ํต์ฌ ์์ฝ ์นด๋
30์ด ๋ต๋ณ
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
์ปจํ
์คํธ ์ค์์นญ = CPU ์ฝ์ด์์ ์คํ๋๋ ์ค๋ ๋/ํ๋ก์ธ์ค๋ฅผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๊ฐ์๋ผ์ฐ๋ OS ์์
.
ํ์ฌ ์ปจํ
์คํธ(๋ ์ง์คํฐยทSPยทPC)๋ฅผ PCB/TCB์ ์ ์ฅ โ ๋ค์ ์ปจํ
์คํธ ๋ณต์.
๋ฐ์ ์์ 4๊ฐ์ง:
โ ํ์ด๋จธ ์ธํฐ๋ฝํธ โ quantum ๋ง๋ฃ (์ ์ ํ ์ค์ผ์ค๋ง)
โก ๋ธ๋กํน ์์คํ
์ฝ โ read/recv/WaitForSingleObject
โข ๋๊ธฐํ ๊ฐ์ฒด ๋๊ธฐ โ mutex/semaphore/event/condition variable
โฃ ์๋ฐ์ ์๋ณด โ Sleep(0)/SwitchToThread/std::this_thread::yield
๋น์ฉ ์์:
โ ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ (์ง์ ๋น์ฉ, ์๋ฐฑ ns)
โก ์บ์ ์ฝ๋ (๊ฐ์ ๋น์ฉ, ๊ฐ์ฅ ํผ)
โข TLB flush (ํ๋ก์ธ์ค ์ ํ์์๋ง, PCID๋ก ํํผ ๊ฐ๋ฅ)
โฃ ํ์ดํ๋ผ์ธ ์ ์ง + ๋ถ๊ธฐ ์์ธก๊ธฐ ๋ฌดํจํ
โค ์ปค๋ ์ง์
(๋ชจ๋ ์ค์์น) ์์ฒด ๋น์ฉ
ํ๋ก์ธ์ค vs ์ค๋ ๋:
์ค๋ ๋ ์ ํ = TCB๋ง ๊ต์ฒด, ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ๋ณด์กด โ 5~10๋ฐฐ ๋น ๋ฆ
ํ๋ก์ธ์ค ์ ํ = CR3 ๊ต์ฒด + TLB flush + ์บ์ ์ฝ๋
๋ชจ๋ ์ค์์น โ ์ปจํ
์คํธ ์ค์์น:
๋ชจ๋ ์ค์์น = ๊ฐ์ ์ค๋ ๋ user โ kernel (PCB ๊ต์ฒด ์์)
์ปจํ
์คํธ ์ค์์น = ๋ค๋ฅธ ์ค๋ ๋/ํ๋ก์ธ์ค๋ก ๊ฐ์๋ผ์ (๋ณดํต ๋ชจ๋ ์ค์์น ์์์)
Windows ๋น์ฉ ์คํํธ๋ผ (๋ฎ์ โ ๋์):
Fiber/SwitchToFiber ์ฌ์ฉ์ ๋ชจ๋, ์์ญ ns
ConcRT Context::Yield ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์
SRWLock / Critical Section ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ , ๊ฒฝํฉ ์ ์ปค๋
Mutex / Event / Semaphore ํญ์ ์ปค๋ ๊ฐ์ฒด
CreateThread quantum ๋ง๋ฃ ํ์ด๋จธ ์ธํฐ๋ฝํธ โ ์ปค๋ ์ค์ผ์ค๋ฌ
๊ผฌ๋ฆฌ์ง๋ฌธ ์ฐ๊ฒฐ ๋งต
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Context Switching
โโโ ๋ฐ์ ์์ (์ ์ผ์ด๋๋?)
โ โโโ ํ์ด๋จธ ์ธํฐ๋ฝํธ (์ ์ )
โ โโโ ๋ธ๋กํน I/O / ์์คํ
์ฝ
โ โโโ ๋๊ธฐํ ๊ฐ์ฒด ๋๊ธฐ (mutex/event)
โ โโโ ์๋ฐ์ ์๋ณด (yield/Sleep(0))
โโโ PCB/TCB (๋ฌด์์ ์ ์ฅํ๋?)
โ โโโ PC, SP, ๋ฒ์ฉ ๋ ์ง์คํฐ, ํ๋๊ทธ
โ โโโ FPU/SIMD ๋ ์ง์คํฐ (lazy save)
โ โโโ ํ์ด์ง ํ
์ด๋ธ ๋ฒ ์ด์ค (CR3 โ ํ๋ก์ธ์ค ์ ํ๋ง)
โ โโโ ํธ๋ค ํ
์ด๋ธ (ํ๋ก์ธ์ค ์ ํ๋ง)
โโโ ๋ชจ๋ ์ค์์น vs ์ปจํ
์คํธ ์ค์์น
โ โโโ ๋ชจ๋ ์ค์์น: user โ kernel (์ค๋ ๋ ๋์ผ)
โ โโโ ์ปจํ
์คํธ ์ค์์น: ์ค๋ ๋ ๊ต์ฒด (๋ณดํต ๋ชจ๋ ์ค์์น ์)
โโโ ๋น์ฉ
โ โโโ ์บ์ ์ฝ๋ โ ๊ฐ์ฅ ํผ (๊ฐ์ )
โ โโโ TLB flush โ ํ๋ก์ธ์ค๋ง (PCID๋ก ํํผ)
โ โโโ ํ์ดํ๋ผ์ธ ์ ์งยท๋ถ๊ธฐ ์์ธก ๋ฌดํจํ
โ โโโ ์ปค๋ ์ง์
์์ฒด
โโโ ํ๋ก์ธ์ค vs ์ค๋ ๋ (5~10๋ฐฐ ์ฐจ์ด)
โ โโโ 19๋ฒ ํ๊ท
โโโ ์ค์ผ์ค๋ง ์๊ณ ๋ฆฌ์ฆ
โ โโโ ์ ์ ํ vs ๋น์ ์ ํ
โ โโโ Round-Robin / ์ฐ์ ์์ / MLFQ
โ โโโ time slice (Windows ๊ธฐ๋ณธ ~15.6ms)
โ โโโ ์งง์ผ๋ฉด ์๋ต์ฑโยท์ค๋ฒํค๋โ / ๊ธธ๋ฉด throughputโยท์๋ต์ฑโ
โโโ Windows ๊น์ด (MSVC ๋ฌธ์ ํธ๋ฆฌ)
โ โโโ Win32 ์ค๋ ๋ API
โ โ โโโ CreateThread (์ปค๋ ์ค๋ ๋ ์์ฑ)
โ โ โโโ SwitchToThread / Sleep(0) (์๋ฐ ์๋ณด)
โ โ โโโ WaitForSingleObject (๋ธ๋กํน)
โ โ โโโ SuspendThread / ResumeThread
โ โโโ ๋๊ธฐํ ๊ฐ์ฒด ๋น์ฉ ์คํํธ๋ผ
โ โ โโโ Critical Section (์ฌ์ฉ์ ์ฐ์ , ๊ฐ์ ํ๋ก์ธ์ค๋ง)
โ โ โโโ SRWLock (์ฌ์ฉ์ ์ฐ์ , R/W ๋ถ๋ฆฌ)
โ โ โโโ Condition Variable (์ฌ์ฉ์ ์ฐ์ )
โ โ โโโ Mutex/Event/Semaphore (ํญ์ ์ปค๋)
โ โโโ ConcRT/PPL โ ์ฌ์ฉ์ ๋ชจ๋ Task Scheduler
โ โ โโโ Context::Block/Yield/Unblock
โ โ โโโ work stealing
โ โ โโโ oversubscription
โ โโโ Fiber API
โ โ โโโ CreateFiber / SwitchToFiber
โ โ โโโ ์ปค๋ ๋ชจ๋ฆ โ ํ๋ ฅ์ ์ค์์นญ
โ โโโ UMS (User-Mode Scheduling)
โ โโโ C++ ํ์ค์ Windows ๋งคํ
โ โ โโโ std::thread โ _beginthreadex โ CreateThread
โ โ โโโ std::mutex โ SRWLock or Critical Section
โ โ โโโ std::condition_variable โ Condition Variable
โ โโโ TLS โ ์ค๋ ๋๋ณ ๋ฉ๋ชจ๋ฆฌ, ์ค์์นญ ์ ์๋ ๋ณด์กด
โ โ โโโ __declspec(thread)
โ โ โโโ TlsAlloc / TlsGetValue
โ โโโ CRT ์ต์
โ โโโ /MT (์ ์ CRT)
โ โโโ /MD (DLL CRT, UCRT)
โ โโโ stdio/heap ๋ฝ โ ์๋์น ์์ ์ค์์นญ ์ ๋ฐ
โโโ ์ธ๋ฆฌ์ผ
โโโ GameThread (Tick, UObject)
โโโ RenderThread (RHI ๋ช
๋ น)
โโโ RHIThread (GPU ๋๋ผ์ด๋ฒ)
โโโ TaskGraph (์์กด์ฑ ๊ธฐ๋ฐ)
โโโ FRunnableThread (OS ์ค๋ ๋ ์ถ์ํ)
โโโ ENamedThreads โ ๋์คํจ์น ์์น ๋ช
์
2. ํ ์ค ์ ์ โ ์ปจํ ์คํธ ์ค์์นญ์ด๋ ๋ฌด์์ธ๊ฐ
ํต์ฌ ํ ๋ฌธ์ฅ
์ปจํ ์คํธ ์ค์์นญ์ CPU ์ฝ์ด ์์์ ์คํ๋๋ ์ค๋ ๋(๋๋ ํ๋ก์ธ์ค)๋ฅผ ์ ์ ๋ด๋ ค๋๊ณ , ๋ค๋ฅธ ์คํ ๋จ์๋ก ๊ฐ์๋ผ์ฐ๋ OS์ ํต์ฌ ์์ ์ ๋๋ค.
โ์ปจํ ์คํธโ๋ ์ ํํ ๋ฌด์์ธ๊ฐ
์ค๋ ๋๊ฐ ์คํ์ ์ ์ ๋ฉ์ท๋ค๊ฐ ์ ํํ ๊ทธ ์๋ฆฌ์์ ์ฌ๊ฐํ๋ ค๋ฉด, CPU์ ๋ชจ๋ ํ๋ฐ์ฑ ์ํ๋ฅผ ๋น ์ง์์ด ์ ์ฅํด์ผ ํฉ๋๋ค. ์ด๊ฒ ์ปจํ ์คํธ์ ๋๋ค.
1
2
3
4
5
6
7
8
์ปจํ
์คํธ์ ๊ตฌ์ฑ (x86_64 ๊ธฐ์ค):
โโ ๋ฒ์ฉ ๋ ์ง์คํฐ (GPR): rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp, r8~r15 (16๊ฐ ร 8B)
โโ ๋ช
๋ น ํฌ์ธํฐ: rip (= PC)
โโ ํ๋๊ทธ ๋ ์ง์คํฐ: rflags
โโ ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ: cs, ds, ss, es, fs, gs
โโ FPU/MMX ๋ ์ง์คํฐ: st0~st7 (๊ฐ 80bit)
โโ SIMD ๋ ์ง์คํฐ: xmm0~xmm15 (128bit), ymm0~15 (256bit), zmm0~31 (512bit AVX-512)
โโ (ํ๋ก์ธ์ค ์ ํ ์) ํ์ด์ง ํ
์ด๋ธ ๋ฒ ์ด์ค: cr3
์ค๋ ๋ ์ปจํ ์คํธ๋ง ๋ฐ์ ธ๋ ํ ํ๋น ์๋ฐฑ ๋ฐ์ดํธ~์ KB๊ฐ ๋ฉ๋ชจ๋ฆฌ๋ก ์ค๊ฐ๋๋ค. AVX-512๊ฐ ํ์ฑํ๋ ์ฝ๋๋ ZMM ๋ ์ง์คํฐ๋ง 32ร64B = 2KB๋ผ ์ปจํ ์คํธ๊ฐ ๋ ๋ฌด๊ฑฐ์์ง๋ฏ๋ก, OS๋ ๋ณดํต lazy save(ํ์ํ ๋๋ง ์ ์ฅ) ์ ์ฑ ์ ์๋๋ค.
ํ๋ฆ ํ๋์
1
2
3
4
5
6
7
8
9
10
11
์ค๋ ๋ A ์คํ ์ค
โ (ํ์ด๋จธ ์ธํฐ๋ฝํธ / ๋ธ๋กํน / yield)
์ฌ์ฉ์ ๋ชจ๋ โ ์ปค๋ ๋ชจ๋ (๋ชจ๋ ์ค์์น)
โ
์ค์ผ์ค๋ฌ: A์ ์ปจํ
์คํธ โ A์ TCB์ ์ ์ฅ
์ค์ผ์ค๋ฌ: ๋ค์ ํ๋ณด B ์ ํ (์ฐ์ ์์ยทtime sliceยทaffinity ๊ณ ๋ ค)
์ค์ผ์ค๋ฌ: B์ TCB์์ ์ปจํ
์คํธ ๋ณต์
โ (ํ๋ก์ธ์ค ์ ํ์ด๋ฉด cr3 ๊ต์ฒด โ TLB flush)
์ปค๋ ๋ชจ๋ โ ์ฌ์ฉ์ ๋ชจ๋ (๋ชจ๋ ์ค์์น)
โ
์ค๋ ๋ B ์คํ ์ฌ๊ฐ (B๊ฐ ๋ฉ์ท๋ ์๋ฆฌ๋ถํฐ)
์ด ์ ์ฒด ๊ณผ์ ์ด ์ผ๋ฐ์ ์ผ๋ก 1~10ฮผs ์ฌ์ด์ ๋๋ค. ์ง์ ๋น์ฉ์ ๋ณดํต 0.5~1ฮผs, ๋๋จธ์ง๋ ์บ์ยทTLB ์ฝ๋ ๋น์ฉ์ ๋๋ค.
์ ํ์ํ๊ฐ
CPU ์ฝ์ด๋ ํ ์๊ฐ์ ํ๋์ ๋ช ๋ น ํ๋ฆ๋ง ์คํํ ์ ์์ต๋๋ค(SMT/ํ์ดํผ์ค๋ ๋ฉ์ด ์์ด๋ ๋ณธ์ง์ ๊ฐ์). ๊ทธ๋ฐ๋ฐ OS๋ ์๋ฐฑ~์์ฒ ๊ฐ์ ์ค๋ ๋๋ฅผ ๋์์ ์ด์ ์๋ ๊ฒ์ฒ๋ผ ๋ณด์ฌ์ผ ํฉ๋๋ค. ๊ทธ๋์ ๋น ๋ฅด๊ฒ ๋์๊ฐ๋ฉฐ ์๊ฐ์ ์ชผ๊ฐ ์ฐ๋ ๋ชจ๋ธ, ์ฆ ์๋ถํ (time-sharing) ์ด ํ์ํ๊ณ , ๊ทธ ์๋ถํ ์ ๋ณธ์ฒด๊ฐ ์ปจํ ์คํธ ์ค์์นญ์ ๋๋ค.
19๋ฒ์์ โ์ค๋ ๋ ์ ํ์ด 5~10๋ฐฐ ๋น ๋ฅด๋คโ๊ณ ํ๋๋ฐ, ๊ทธ ์ฐจ์ด์ ์์ธ์ด 21๋ฒ์์ ์ค๋ช ํ ๋น์ฉ ์์๋ค์ ๋๋ค.
3. ๋ฐ์ ์์ 4๊ฐ์ง โ ํ์ด๋จธยท์์คํ ์ฝยท๋๊ธฐํ ๋๊ธฐยท์๋ฐ์ ์๋ณด
๋ฐ์ ์์ 1 โ ํ์ด๋จธ ์ธํฐ๋ฝํธ (Timer Interrupt)
OS๊ฐ ์ค๋ ๋์ ํ ๋นํ time slice (quantum, ์๊ฐ ์กฐ๊ฐ) ๊ฐ ๋ง๋ฃ๋๋ฉด ํ๋์จ์ด ํ์ด๋จธ๊ฐ ์ธํฐ๋ฝํธ๋ฅผ ๋ฐ์์ํค๊ณ , OS ์ค์ผ์ค๋ฌ๊ฐ ๊ฐ์ ๋ก ์ปจํ ์คํธ ์ค์์นญ์ ์ผ์ผํต๋๋ค. ์ ์ ํ(preemptive) ์ค์ผ์ค๋ง์ ๋ณธ์ฒด์ ๋๋ค.
1
2
3
4
5
์๊ฐ์ถ โ
์ค๋ ๋ A: โโโโโโโโโโโโ (time slice 15.6ms ์์ง)
โ ํ์ด๋จธ ์ธํฐ๋ฝํธ
โ ์ปจํ
์คํธ ์ค์์น
์ค๋ ๋ B: โโโโโโโโโโโโ (๋ค์ quantum)
Windows์ ๊ธฐ๋ณธ quantum์ ์ฝ 15.6ms(Server๋ ๋ ๊น), ๋ฉํฐ๋ฏธ๋์ด ํ์ด๋จธ API(timeBeginPeriod(1))๋ก ์ต์ 1ms๊น์ง ์ค์ผ ์ ์์ต๋๋ค. ์งง์์๋ก ์๋ต์ฑ์ด ์ข์์ง์ง๋ง ์ปจํ
์คํธ ์ค์์นญ ๋น๋๊ฐ ๋์ด ์ค๋ฒํค๋๊ฐ ๋์ ๋ฉ๋๋ค.
๋ฐ์ ์์ 2 โ ๋ธ๋กํน ์์คํ ์ฝ (Blocking System Call)
๋๊ธฐ๋ฅผ ๋๋ฐํ๋ ์์คํ ์ฝ์ ๋ง๋๋ฉด ๊ทธ ์ค๋ ๋๋ ์ฆ์ Wait ์ํ๋ก ์ ํ๋๊ณ , ์ค์ผ์ค๋ฌ๊ฐ ๋ค๋ฅธ Ready ์ค๋ ๋๋ฅผ ๊ณจ๋ผ ๋์คํจ์นํฉ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Windows
DWORD result = WaitForSingleObject(hEvent, INFINITE);
// ํธ์ถ ์ฆ์ โ Wait ์ํ โ ์ปจํ
์คํธ ์ค์์น โ ๋ค๋ฅธ ์ค๋ ๋ ์คํ
// hEvent ์๊ทธ๋ โ Ready ํ โ ์ค์ผ์ค๋ง โ ์ปจํ
์คํธ ์ค์์น๋ก ๋ณต๊ท
// ํ์ผ I/O
HANDLE hFile = CreateFile(...);
DWORD bytesRead;
ReadFile(hFile, buffer, 1024, &bytesRead, NULL);
// ๋์คํฌ ์๋ต ๋๊ธฐ โ Wait โ ์ปจํ
์คํธ ์ค์์น
// ๋คํธ์ํฌ I/O (๋๊ธฐ ๋ชจ๋)
recv(socket, buffer, 1024, 0);
// ์์ ๋ฐ์ดํฐ ๋์ฐฉ๊น์ง โ Wait โ ์ปจํ
์คํธ ์ค์์น
์ด ๊ฒฝ์ฐ ์ปจํ ์คํธ ์ค์์นญ์ ์์์ ํจ์จ์ ์ผ๋ก ์ฌ์ฉํ๋ ํ์์ ๋๋ค. CPU๊ฐ ๋์คํฌ๋ ๋คํธ์ํฌ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉฐ ๋๊ฒ ๋๋ ๋์ ๋ค๋ฅธ ์ผ์ ํ๊ฒ ๋ง๋๋ ๊ฒ ๋ฉํฐ์ค๋ ๋ฉ์ ๋ณธ์ง์ด๋๊น์.
๋ฐ์ ์์ 3 โ ๋๊ธฐํ ๊ฐ์ฒด ๋๊ธฐ
mutexยทsemaphoreยทeventยทcondition variable์์ ๋๊ธฐ ์ํ๋ก ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ์ ๋๋ค. ๋ณธ์ง์ ์ผ๋ก ๋ธ๋กํน ์์คํ ์ฝ์ ํ ํํ์ง๋ง, ๋ฐ์ ๋น๋์ ํจํด์ด ๋ค๋ฆ ๋๋ค.
1
2
3
4
5
std::mutex m;
std::lock_guard<std::mutex> lock(m); // ๋ฝ์ด ์กํ์์ผ๋ฉด โ Wait โ ์ปจํ
์คํธ ์ค์์น
std::condition_variable cv;
cv.wait(lock, []{ return ready; }); // ์กฐ๊ฑด false๋ฉด โ Wait โ ์ปจํ
์คํธ ์ค์์น
Windows์ Critical Section๊ณผ SRWLock์ ์ฒ์์ ์ฌ์ฉ์ ๋ชจ๋์์ ์ ๊น spinํ๋ค๊ฐ ๊ทธ๋๋ ๋ชป ์ก์ผ๋ฉด ๊ทธ๋ ์ปค๋์ ์ง์ ํด Wait ์ํ๋ก ๋ค์ด๊ฐ๋๋ค. ์ด๊ฒ โ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ โ ๋๊ธฐํ ๊ฐ์ฒด์ ํต์ฌ์ผ๋ก, ๊ฒฝํฉ์ด ์๋ ์ผ๋ฐ์ ์ผ์ด์ค์์ ์ปจํ ์คํธ ์ค์์นญ ์์ด ๋ฝ ํ๋์ด ๋๋ฉ๋๋ค.
๋ฐ์ ์์ 4 โ ์๋ฐ์ ์๋ณด (Voluntary Yield)
์ค๋ ๋๊ฐ ์ง์ โ์ง๊ธ CPU๋ฅผ ๋ค๋ฅธ ์ค๋ ๋์ ๋๊ธฐ๊ฒ ๋คโ๊ณ OS์ ์๋ฆฌ๋ ํธ์ถ์ ๋๋ค. ํ๋ ฅ์ ์ค์ผ์ค๋ง์ ํจํด์ด์ง๋ง, ์ ์ ํ OS์์๋ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
1
2
3
4
5
6
7
8
// Windows
SwitchToThread(); // ๊ฐ์ ์ฝ์ด์ ๋ค๋ฅธ Ready ์ค๋ ๋์ ์๋ณด. ์์ผ๋ฉด ์ฆ์ ๋ณต๊ท
Sleep(0); // ๊ฐ์ ์ฐ์ ์์ ์ค๋ ๋์ ์๋ณด. ๋ ๋์ ์ฐ์ ์์๋ ํญ์ ์ ์
Sleep(1); // ์ต์ 1ms ๋๊ธฐ (์ค์ ๋ก quantum ๋จ์๋ก ๋ฐ์ฌ๋ฆผ)
// C++ ํ์ค
std::this_thread::yield(); // ๊ตฌํ์ฒด๊ฐ ์ ์ ํ OS ํธ์ถ๋ก ๋งคํ
std::this_thread::sleep_for(...);
Sleep(0)๊ณผ SwitchToThread์ ์ฐจ์ด๋ ์ด๋ค ์ค๋ ๋๊น์ง ํ๋ณด๋ก ๋ณด๋๋์
๋๋ค. Sleep(0)์ ๊ฐ์ ์ฐ์ ์์ ํ์ , SwitchToThread๋ ๊ฐ์ ์ฝ์ด์ ๋ชจ๋ Ready ์ค๋ ๋(์ฐ์ ์์ ๋ฌด๊ด). spin lock์์ ๊ฒฝํฉ ์ _mm_pause() ๋๋ SwitchToThread๋ก ๋ค๋ฅธ ์ค๋ ๋์ ์๋ณดํ๋ ํจํด์ด ํํฉ๋๋ค.
4์์ ๋น๊ต ํ
| ๋ฐ์ ์์ | ํธ๋ฆฌ๊ฑฐ | ๋ชจ๋ | ๋น๋ | ๋น์ฉ |
|---|---|---|---|---|
| ํ์ด๋จธ ์ธํฐ๋ฝํธ | ํ๋์จ์ด quantum ๋ง๋ฃ | ๊ฐ์ (์ ์ ) | ๋ณดํต (์์ญ Hz) | ๋ณดํต |
| ๋ธ๋กํน ์์คํ ์ฝ | I/Oยทํ์ผยท์์ผ | ์ค๋ ๋ ์๋ฐ โ ์ปค๋ ๊ฐ์ | ์ฆ์ | ๋ณดํต |
| ๋๊ธฐํ ๋๊ธฐ | mutexยทevent ๋ฑ | ์๋ฐ โ ์ปค๋ (๊ฒฝํฉ ์) | ์ฝ๋ ์์กด | ์ฌ์ฉ์ ๋ชจ๋๋ฉด ์์ |
| ์๋ฐ์ ์๋ณด | yieldยทSleep(0) | ์๋ฐ | ์ฝ๋ ์์กด | ๊ฐ์ฅ ์์ |
4. PCB/TCB ์ ์ฅยท๋ณต์ ๋จ๊ณ โ ๋ฌด์์ ์ด๋์ ์ ์ฅํ๋
PCB์ TCB์ ์ญํ ๊ตฌ๋ถ
19๋ฒ์์ ์ ๋ฆฌํ ๊ทธ๋๋ก์ง๋ง, ์ปจํ ์คํธ ์ค์์นญ์์ ๋์ด ์ด๋ป๊ฒ ์ฐ์ด๋์ง ๋ ์์ธํ ๋ด ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
PCB (Process Control Block) โ ํ๋ก์ธ์ค 1๊ฐ๋น 1๊ฐ
โโ PID
โโ ํ์ด์ง ํ
์ด๋ธ ๋ฒ ์ด์ค (cr3 ๊ฐ)
โโ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ์ ๋ณด (์ฝ๋/๋ฐ์ดํฐ/ํ ์์ญ ๋งคํ)
โโ ํธ๋ค ํ
์ด๋ธ (ํ์ผยท์์ผยท์ด๋ฒคํธ ๋ฑ)
โโ ํ๊ฒฝ ๋ณ์, ๋ถ๋ชจ/์์ PID
โโ ๋ณด์ ํ ํฐ (Windows: ์ฌ์ฉ์/๊ทธ๋ฃน/๊ถํ)
โโ ์์ TCB ๋ฆฌ์คํธ
TCB (Thread Control Block) โ ์ค๋ ๋ 1๊ฐ๋น 1๊ฐ
โโ TID
โโ ๋ ์ง์คํฐ ์ปจํ
์คํธ (PC, SP, GPR, ํ๋๊ทธ, FPU/SIMD)
โโ ์คํ ๋ฒ ์ด์ค ์ฃผ์ + ํฌ๊ธฐ (์๊ธฐ ์คํ์ ์์น)
โโ ์ฐ์ ์์, ์ํ (Running/Ready/Wait)
โโ TLS ์ฌ๋กฏ ํฌ์ธํฐ
โโ ์๊ทธ๋ ๋ง์คํฌ / SEH ์ฒด์ธ
โโ ์์ PCB ํฌ์ธํฐ
์ค๋ ๋ ์ปจํ ์คํธ ์ค์์น ๋จ๊ณ (๊ฐ์ ํ๋ก์ธ์ค ๋ด)
1
2
3
4
5
6
7
8
9
10
11
12
13
1. ํธ๋ฆฌ๊ฑฐ (ํ์ด๋จธ/์์คํ
์ฝ/๋๊ธฐํ ๋๊ธฐ/yield)
2. CPU๊ฐ ์๋์ผ๋ก ํธ๋ฉ โ ์ปค๋ ๋ชจ๋ ์ง์
3. ์ปค๋ ์ง์
์ ์ผ๋ถ ๋ ์ง์คํฐ ์๋ ์ ์ฅ (CPU์ trap frame ๋ฉ์ปค๋์ฆ)
4. ์ค์ผ์ค๋ฌ ์ง์
5. ํ์ฌ ์ค๋ ๋ A์ TCB์:
- ๋ ์ง์คํฐ ์ปจํ
์คํธ ์ ์ฅ (PC, SP, GPR, ํ๋๊ทธ)
- FPU/SIMD๋ lazy save (์ฌ์ฉํ์ผ๋ฉด)
6. ์ค์ผ์ค๋ฌ๊ฐ ๋ค์ ์ค๋ ๋ B ์ ํ
- ์ฐ์ ์์, time slice ์๋, CPU affinity, NUMA ๋
ธ๋ ๊ณ ๋ ค
7. ์ค๋ ๋ B์ TCB์์:
- ๋ ์ง์คํฐ ์ปจํ
์คํธ ๋ณต์
- SP๋ฅผ B์ ์คํ์ผ๋ก ๊ต์ฒด โ ์ด ์์ ๋ถํฐ B์ ์คํ์ด ํ์ฑ
8. ์ฌ์ฉ์ ๋ชจ๋๋ก ๋ณต๊ท (rip๊ฐ ๊ฐ๋ฆฌํค๋ ๋ช
๋ น๋ถํฐ ์ฌ๊ฐ)
ํต์ฌ์ ํ์ด์ง ํ ์ด๋ธยทํธ๋ค ํ ์ด๋ธยท๋ฉ๋ชจ๋ฆฌ๋งต์ ๊ฑด๋๋ฆฌ์ง ์๋๋ค๋ ์ ์ ๋๋ค. ๊ฐ์ ํ๋ก์ธ์ค์ ์ค๋ ๋๋ค์ ๊ฐ์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ ๊ณต์ ํ๋ฏ๋ก cr3๊ฐ ๊ทธ๋๋ก์ ๋๋ค.
ํ๋ก์ธ์ค ์ปจํ ์คํธ ์ค์์น ๋จ๊ณ (๋ค๋ฅธ ํ๋ก์ธ์ค๋ก)
1
2
3
4
5
6
7
8
1~6. (์์ ๋์ผ)
7. ์ ํ๋ก์ธ์ค P2์ PCB์์:
- ํ์ด์ง ํ
์ด๋ธ ๋ฒ ์ด์ค (cr3) ๊ต์ฒด โ ์ด๊ฒ ์ถ๊ฐ
- TLB flush (๋๋ PCID ํ๊น
์ผ๋ก ํํผ)
- ํธ๋ค ํ
์ด๋ธ ํฌ์ธํฐ ๊ต์ฒด
- ๋ณด์ ํ ํฐ ๊ต์ฒด
8. P2์ ์ฒซ ์ค๋ ๋ B์ TCB ๋ณต์ (์์ ๋์ผ)
9. ์ฌ์ฉ์ ๋ชจ๋๋ก ๋ณต๊ท
์ถ๊ฐ๋๋ ๋จ๊ณ๋ cr3 ๊ต์ฒด์ ๊ทธ์ ๋ฐ๋ฅธ TLB flush๊ฐ ํต์ฌ์ ๋๋ค. ์ด๊ฒ 5~10๋ฐฐ ๋น์ฉ ์ฐจ์ด์ ์ง์ ์์ธ์ ๋๋ค.
lazy FPU save โ ๋น์ฉ ์ ๊ฐ ํธ๋ฆญ
FPU/SIMD ๋ ์ง์คํฐ๋ ์๋ ๋ง๊ณ (AVX-512๋ฉด 2KB), ๋ชจ๋ ์ค๋ ๋๊ฐ ์ฐ์ง ์์ต๋๋ค. ๊ทธ๋์ OS๋ ์ปจํ ์คํธ ์ค์์นญ ์ FPU ์ฌ์ฉ ๋นํธ๋ง ๋๊ณ ์ค์ ์ ์ฅ์ ๋ฏธ๋ฃน๋๋ค. ๋ค์ ์ค๋ ๋๊ฐ FPU ๋ช ๋ น์ ์ฒ์ ์ฐ๋ ์๊ฐ ํธ๋ฉ์ด ๊ฑธ๋ฆฌ๊ณ , ๊ทธ๋ ์ด์ ์ค๋ ๋์ FPU ์ปจํ ์คํธ๋ฅผ ์ ์ฅํ๊ณ ์ ์ค๋ ๋์ ์ปจํ ์คํธ๋ฅผ ๋ณต์ํฉ๋๋ค.
1
2
3
์ค๋ ๋ A: FPU ์ฌ์ฉ โ ์ปจํ
์คํธ ์ค์์น ์ FPU ์ฌ์ฉ ๋นํธ๋ง ๋
์ค๋ ๋ B: FPU ์ ์ โ FPU ์ปจํ
์คํธ ์ ๋ง์ง (์ด๋)
์ค๋ ๋ B: FPU ๋ช
๋ น ๋ง๋จ โ ํธ๋ฉ โ ๊ทธ๋ A์ FPU ์ ์ฅ + B์ FPU ๋ณต์
๋๋ถ๋ถ์ ์ํฌ๋ก๋์์ FPU๋ฅผ ์ฐ๋ ์ค๋ ๋ ์๊ฐ ์ ์ด์ ์ด ์ต์ ํ๊ฐ ํฐ ํจ๊ณผ๋ฅผ ๋ ๋๋ค. ๋จ ๊ฒ์์ฒ๋ผ ๊ฑฐ์ ๋ชจ๋ ์ค๋ ๋๊ฐ SIMD๋ฅผ ์ฐ๋ฉด lazy save์ ์ด๋์ด ์ค์ด๋ญ๋๋ค.
5. ๋ชจ๋ ์ค์์น โ ์ปจํ ์คํธ ์ค์์น โ ์์ฃผ ํท๊ฐ๋ฆฌ๋ ๊ตฌ๋ถ
์ ์ ์ฐจ์ด
| ํญ๋ชฉ | ๋ชจ๋ ์ค์์น (Mode Switch) | ์ปจํ ์คํธ ์ค์์น (Context Switch) |
|---|---|---|
| ๋ฌด์์ด ๋ฐ๋๋ | CPU ๋ชจ๋ (user โ kernel) | ์คํ ์ฃผ์ฒด (์ค๋ ๋ A โ ์ค๋ ๋ B) |
| ์ค๋ ๋ ๋์ผ์ฑ | ๊ฐ์ | ๋ค๋ฆ (๋๋ ๋ค๋ฅธ ํ๋ก์ธ์ค) |
| PCB/TCB ๊ต์ฒด | ์์ | ์์ |
| TLB flush | ์์ | ์์ (ํ๋ก์ธ์ค ์ ํ๋ง) |
| ์บ์ ์ฝ๋ | ๊ฑฐ์ ์์ | ํผ (๊ฐ์ ๋น์ฉ์ ํต์ฌ) |
| ๋น์ฉ | ์์ญ~์๋ฐฑ ns | ์๋ฐฑ ns~์ ฮผs (+ ์บ์ ์ฝ๋) |
| ๊ด๊ณ | ์ปจํ ์คํธ ์ค์์น๋ ๋ณดํต ๋ชจ๋ ์ค์์น ์์์ ์ผ์ด๋จ | ๋ชจ๋ ์ค์์น๋ ์ปจํ ์คํธ ์ค์์น ์์ด๋ ์ผ์ด๋จ |
๋ชจ๋ ์ค์์น๊ฐ ์ผ์ด๋๋ ๊ฒฝ์ฐ
CPU๋ ๋ค์ ๋ค ๊ฐ์ง ์ฌ๊ฑด์์ ์ฌ์ฉ์ ๋ชจ๋ โ ์ปค๋ ๋ชจ๋๋ก ์๋ ์ง์ ํฉ๋๋ค. ์ฌ์ฉ์ ์ฝ๋๊ฐ ์ง์ โ์ง๊ธ๋ถํฐ ์ปค๋ ๋ชจ๋โ๋ผ๊ณ ์ ์ธํ ์๋ ์๊ณ , ํ๋์จ์ด๊ฐ ๊ฐ์ ๋ก ๋ชจ๋๋ฅผ ์ฌ๋ฆฐ๋ค๋ ๊ฒ ํต์ฌ์ ๋๋ค.
| ํธ๋ฆฌ๊ฑฐ | ์์ | ๋๊ฐ ๋ฐ์์ํค๋ |
|---|---|---|
| ์์คํ ์ฝ (System Call) | read()ยทwrite()ยทCreateFile()ยทWaitForSingleObject()ยทmmap() | ์ฌ์ฉ์ ์ฝ๋ (syscall/int 0x80 ๋ช
๋ น) |
| ํ๋์จ์ด ์ธํฐ๋ฝํธ (Hardware Interrupt) | ํ์ด๋จธยทํค๋ณด๋ยท๋ง์ฐ์คยท๋์คํฌ ์๋ฃยท๋คํธ์ํฌ ํจํท ์์ | ์ธ๋ถ ์ฅ์น (CPU์ INTR ํ) |
| ์์ธ (Exception/Trap) | Page FaultยทDivide by ZeroยทInvalid OpcodeยทGeneral Protection Fault | CPU ์์ฒด (๋ช ๋ น ์คํ ๋์ค ๊ฐ์ง) |
| ์ํํธ์จ์ด ์ธํฐ๋ฝํธ | ๋๋ฒ๊ฑฐ breakpoint(int 3), ๋ช
์์ ํธ๋ฉ ๋ช
๋ น | ์ฌ์ฉ์/๋๋ฒ๊ฑฐ ์ฝ๋ |
์ง์ ์งํ CPU๋ trap frame(ํ์ฌ RIPยทRSPยทRFLAGS ๋ฑ)์ ์ปค๋ ์คํ์ ์๋ ์ ์ฅํ๊ณ , IDT(Interrupt Descriptor Table)์ ๋ฑ๋ก๋ ํธ๋ค๋ฌ๋ก ์ ํํฉ๋๋ค. ๊ถํ ๋นํธ(CS ๋ ์ง์คํฐ์ RPL)๋ 0(์ปค๋)์ผ๋ก ๋ฐ๋๋๋ค.
์ปค๋ โ ์ฌ์ฉ์ ๋ชจ๋ ๋ณต๊ท๋ ๊ทธ ๋ฐ๋ ๊ฒฝ๋ก์
๋๋ค. iret(์ธํฐ๋ฝํธ ๋ฐํ) ๋๋ sysret(ํ๋ syscall ๋ฐํ) ๋ช
๋ น์ด trap frame์ ๊บผ๋ด RIPยทRSPยทRFLAGSยทCS๋ฅผ ์ฌ์ฉ์ ๊ฐ์ผ๋ก ๋ณต์ํ๋ฉด์ ๊ถํ๋ 3(์ฌ์ฉ์)์ผ๋ก ๋ด๋ฆฝ๋๋ค.
1
2
3
4
5
6
7
8
9
10
11
์ฌ์ฉ์ ๋ชจ๋ ์ฝ๋ ์คํ
โ โ syscall / int 0x80 (์์คํ
์ฝ)
โ โก ์ธ๋ถ ์ฅ์น ์ธํฐ๋ฝํธ
โ โข Page FaultยทDivide by Zero (์์ธ)
โ โฃ int 3 (๋๋ฒ๊ฑฐ)
CPU: trap frame ์ ์ฅ โ CS.RPL = 0 โ IDT ํธ๋ค๋ฌ๋ก ์ ํ
โ
์ปค๋ ๋ชจ๋ ์ฝ๋ ์คํ
โ iret / sysret
CPU: trap frame ๋ณต์ โ CS.RPL = 3
์ฌ์ฉ์ ๋ชจ๋ ์ฝ๋ ์ฌ๊ฐ
๋ชจ๋ ์ค์์น๋ง ์ผ์ด๋๋ ๊ฒฝ์ฐ
1
2
3
// ์์คํ
์ฝ์ด ์ฆ์ ๋๋จ โ ์ปจํ
์คํธ ์ค์์น ์์
DWORD pid = GetCurrentProcessId(); // user โ kernel โ user, ๊ฐ์ ์ค๋ ๋
QueryPerformanceCounter(&counter); // ๊ฐ์ ์ค๋ ๋, ๊ฐ์ quantum ์์์ ๋ณต๊ท
์ ํธ์ถ๋ค์ user mode โ kernel mode ์ ํ์ด ์ผ์ด๋์ง๋ง(๋ชจ๋ ์ค์์น), ์ ๋ณด๋ฅผ ์ฝ๊ณ ์ฆ์ ์ฌ์ฉ์ ๋ชจ๋๋ก ๋์์ค๋ฏ๋ก ๋ค๋ฅธ ์ค๋ ๋๋ก ๊ฐ์๋ผ์ฐ์ง ์์ต๋๋ค(์ปจํ ์คํธ ์ค์์น ์์).
์ปจํ ์คํธ ์ค์์น๋ ๋ณดํต ๋ชจ๋ ์ค์์น ์์์
ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก ์ปจํ ์คํธ ์ค์์น๊ฐ ์ผ์ด๋๋ ค๋ฉด ๋จผ์ ์ฌ์ฉ์ ๋ชจ๋ โ ์ปค๋ ๋ชจ๋ (๋ชจ๋ ์ค์์น)๊ฐ ์ผ์ด๋์ผ ํฉ๋๋ค. ์ธํฐ๋ฝํธ ํธ๋ค๋ฌ๋ ํญ์ ์ปค๋ ๋ชจ๋์์ ์คํ๋๋๊น์. ๊ทธ ํธ๋ค๋ฌ ์์์ ์ค์ผ์ค๋ฌ๊ฐ ํธ์ถ๋๊ณ , ๋ค๋ฅธ ์ค๋ ๋๋ฅผ ๊ณจ๋ผ ๊ทธ ์ค๋ ๋์ ์ปจํ ์คํธ๋ก ๋ณต์ํ ๋ค ๋ค์ ์ฌ์ฉ์ ๋ชจ๋ (๋ ํ ๋ฒ์ ๋ชจ๋ ์ค์์น)๋ก ๋ณต๊ทํฉ๋๋ค.
1
2
3
4
5
6
7
8
์ฌ์ฉ์ ์ฝ๋ ์คํ ์ค (user mode)
โ ํ์ด๋จธ ์ธํฐ๋ฝํธ
๋ชจ๋ ์ค์์น: user โ kernel
โ
์ค์ผ์ค๋ฌ ์ง์
โ ์ปจํ
์คํธ ์ค์์น (์ค๋ ๋ A โ ์ค๋ ๋ B)
โ
๋ชจ๋ ์ค์์น: kernel โ user
์ฌ์ฉ์ ์ฝ๋ ์คํ (์ค๋ ๋ B์ user mode)
Fiber๋ ๋ ๋ค ์์
Fiber API(SwitchToFiber)๋ ์ฌ์ฉ์ ๋ชจ๋์์ ์ง์ SPยทPC๋ฅผ ๋ฐ๊ฟ์น๊ธฐํ๋ฏ๋ก ๋ชจ๋ ์ค์์น๋ ์ปจํ
์คํธ ์ค์์น(OS ๊ด์ )๋ ์ผ์ด๋์ง ์์ต๋๋ค. OS ์ค๋ ๋๋ ๊ทธ๋๋ก์ด๊ณ , ๊ทธ ์ค๋ ๋ ์์์ ์ฌ์ฉ์ ์ฝ๋๊ฐ ์๊ธฐ ์คํ ์ปจํ
์คํธ๋ง ๊ฐ์์น์ฐ๋ ๊ฒ์
๋๋ค. ๊ทธ๋์ ์์ญ nanosecond์ ๋๋ฉ๋๋ค.
ํ ์ค ์์ฝ
๋ชจ๋ ์ค์์น๋ ๊ถํ์ด ๋ฐ๋๋ ๊ฒ, ์ปจํ ์คํธ ์ค์์น๋ ์คํ ์ฃผ์ฒด๊ฐ ๋ฐ๋๋ ๊ฒ. ๋์ ์์ฃผ ํจ๊ป ์ผ์ด๋์ง๋ง ๊ฐ์ง ์์ต๋๋ค.
6. ๋น์ฉ ์์ โ ์บ์ flush ยท TLB flush ยท ํ์ดํ๋ผ์ธ ์ ์ง
๋น์ฉ์ ๊ธ๋จธ๋ฆฌํ๋ก ๋ถ๋ฆฌํด ์ ๋ฆฌํฉ๋๋ค(20๋ฒ ํ์ผ์์ ํ์ธ๋ ์ฌ์ฉ์ ์ ํธ ๊ทธ๋๋ก).
๋น์ฉ ์์ 1 โ ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ (์ง์ ๋น์ฉ)
๋ ์ง์คํฐ๋ฅผ ๋ฉ๋ชจ๋ฆฌ(TCB)์ ์ฎ๊ธฐ๋ ์ง์ ์ ์์ ์ ๋๋ค. x86_64์ GPR 16๊ฐ + ํ๋๊ทธ + ์ธ๊ทธ๋จผํธ + (์ ํ์ ) FPU/SIMD๋ฅผ ํฉ์น๋ฉด ํ ๋ฒ์ ์๋ฐฑ ๋ฐ์ดํธ๋ฅผ ๋ฉ๋ชจ๋ฆฌ๋ก ๋ณด๋ด๊ณ , ๋ค์ ๊ฐ์ ธ์ต๋๋ค.
- ๋ณดํต ์๋ฐฑ nanosecond ์์ค
- ๊ทธ ์์ฒด๋ก๋ ์์ง๋ง ์ปจํ ์คํธ ์ค์์นญ์ด ๋งค quantum(์: 15.6ms)๋ง๋ค ์ผ์ด๋๋ฉด ๋์ ๋จ
- AVX-512 ํ์ฑํ ์ ZMM 32ร64B = 2KB๋ผ ์ง์ ๋น์ฉ์ด ๋์ด๋จ
๋น์ฉ ์์ 2 โ ์บ์ ์ฝ๋ (Cache Cold) โ ๊ฐ์ฅ ํฐ ๊ฐ์ ๋น์ฉ
์๋ก ๋ค์ด์จ ์ค๋ ๋ B์ ๋ฐ์ดํฐยท๋ช ๋ น์ด๊ฐ L1ยทL2 ์บ์์ ์์ผ๋ฏ๋ก, ์ง์ ์งํ ์ค์ค์ด ์บ์ ๋ฏธ์ค(cache miss) ๊ฐ ๋ฐ์ํฉ๋๋ค. ๋ฉ๋ชจ๋ฆฌ์์ ์บ์ ๋ผ์ธ(๋ณดํต 64B)์ ๋ค์ ๊ฐ์ ธ์ค๋ ๋ฐ ํ ๋ฒ์ ์์ญ~์๋ฐฑ nanosecond๊ฐ ๋ค๊ณ , ์ด๊ฒ ์๋ฐฑ~์์ฒ ๋ฒ ๋ฐ๋ณต๋ฉ๋๋ค.
1
2
3
4
5
6
์ค๋ ๋ A ์คํ ์ค โ A์ working set์ด L1/L2์ ์บ์ฑ๋จ
โ ์ปจํ
์คํธ ์ค์์น
์ค๋ ๋ B ์คํ ์์ โ A์ ์บ์ ๋ผ์ธ์ด ๊ฐ๋, B์ ๋ฐ์ดํฐ๋ ๋ฉ๋ชจ๋ฆฌ์
โ
B์ ๋ช
๋ น ์คํ โ L1 miss โ L2 miss โ L3 miss โ DRAM ์ ๊ทผ (~100ns)
โ ์บ์ ๋ผ์ธ ๊ฐ์ ธ์ค๊ธฐ โ ๋ค์ ๋ช
๋ น ์คํ โ ๋ ๋ค๋ฅธ ๋ฏธ์ค โ ...
- ์ง์ ๋น์ฉ๋ณด๋ค ์~์์ญ ๋ฐฐ ํฐ ๊ฒฝ์ฐ๊ฐ ์ผ๋ฐ์
- ์๊ณ ๊ตฌ์ญ์ด ์งง์ผ๋ฉด spin lock์ด mutex๋ณด๋ค ๋น ๋ฅธ ํต์ฌ ์ด์
- L1 ์บ์ ํฌ๊ธฐ(๋ณดํต 32~64KB), L2(512KB~1MB)๊ฐ ์์ ๋นจ๋ฆฌ ์ฑ์์ง
๋น์ฉ ์์ 3 โ TLB Flush (ํ๋ก์ธ์ค ์ ํ์์๋ง)
TLB(Translation Lookaside Buffer, ์ฃผ์ ๋ณํ ์บ์)๋ ๊ฐ์ ์ฃผ์ โ ๋ฌผ๋ฆฌ ์ฃผ์ ๋งคํ์ ์บ์ฑํ๋ MMU(Memory Management Unit) ๋ด๋ถ ์บ์์ ๋๋ค. ๋ณดํต 64~512 ์ํธ๋ฆฌ๋ก ์์ต๋๋ค. ํ๋ก์ธ์ค๊ฐ ๋ฐ๋๋ฉด ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ด ๋ค๋ฅด๋ฏ๋ก ์ด ์บ์๋ฅผ ๋ฌดํจํํด์ผ ํฉ๋๋ค.
1
2
3
4
๊ฐ์ ์ฃผ์ 0x12345678 (ํ๋ก์ธ์ค P1) โ ๋ฌผ๋ฆฌ ์ฃผ์ 0xAAAA โ TLB ์บ์ฑ
โ ํ๋ก์ธ์ค ์ ํ (P1 โ P2)
๊ฐ์ ์ฃผ์ 0x12345678 (ํ๋ก์ธ์ค P2) โ ๋ฌผ๋ฆฌ ์ฃผ์ 0xBBBB โ ๋ค๋ฅธ ๋งคํ!
โ ๊ธฐ์กด TLB ์ํธ๋ฆฌ๋ ๋ฌดํจํ ํ์
- TLB flush ํ์ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ํ์ด์ง ํ ์ด๋ธ ์ํฌ(page table walk) ๋ถํฐ ์์
- 4๋จ๊ณ ํ์ด์ง ํ ์ด๋ธ์ด๋ฉด ํ ๋ฒ ์ํฌ์ 4๋ฒ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ
- ํ๋ x86์ PCID(Process Context ID) ๋ก TLB ์ํธ๋ฆฌ์ ํ๋ก์ธ์ค ID๋ฅผ ํ๊น ํด ์ ์ฒด flush๋ฅผ ํํผ
- ARM์ ASID(Address Space ID) ๋ก ๊ฐ์ ์ญํ
- ์ค๋ ๋ ์ ํ์์ ๊ฐ์ ํ๋ก์ธ์ค๋ผ TLB flush ์์ โ ์ด๊ฒ 5~10๋ฐฐ ์ฐจ์ด์ ํต์ฌ
๋น์ฉ ์์ 4 โ ํ์ดํ๋ผ์ธ ์ ์ง์ ๋ถ๊ธฐ ์์ธก๊ธฐ ๋ฌดํจํ
CPU์ instruction pipeline์ ๋ค์ด ์๋ ๋ช ๋ น๋ค์ด ์ปจํ ์คํธ ์ค์์น ์์ ์ ๋ชจ๋ ํ๊ธฐ๋ฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ถ๊ธฐ ์์ธก๊ธฐ(branch predictor)๊ฐ ํ์ตํด ๋ ํจํด์ด ์ด์ ์ค๋ ๋ ์ฝ๋ ๊ธฐ์ค์ด๋ผ, ์ ์ค๋ ๋์ ๋ถ๊ธฐ ํจํด๊ณผ ์ด๊ธ๋ ์ ์ ์ ํ๋๊ฐ ๋จ์ด์ง๋๋ค.
- Pipeline drain: ๋ณดํต ์ญ์ cycles
- BTB(Branch Target Buffer) ์ฝ๋: ๋ถ๊ธฐ๋ง๋ค misprediction โ flush ๋ฐ๋ณต
๋น์ฉ ์์ 5 โ ์ปค๋ ์ง์ (๋ชจ๋ ์ค์์น) ์์ฒด ๋น์ฉ
์ปจํ ์คํธ ์ค์์นญ์ ๊ฑฐ์ ํญ์ ๋ชจ๋ ์ค์์น ์์์ ์ผ์ด๋๋ฏ๋ก ๊ทธ ๋น์ฉ์ด ํจ๊ป ๋ญ๋๋ค. ์์คํ ์ฝ ํ ๋ฒ์ ๋ณดํต 100~500 nanosecond, Spectre/Meltdown ์ํ ํจ์น ์ดํ์๋ KPTI(Kernel Page Table Isolation) ๋๋ฌธ์ ๋ ๋น์ธ์ก์ต๋๋ค(์ microsecond๊น์ง).
๋น์ฉ ์์ ์ข ํฉ
| ์์ | ์ง์ /๊ฐ์ | ํ๋ก์ธ์ค ์ ํ | ์ค๋ ๋ ์ ํ | ์ ๋ ๋น์ฉ |
|---|---|---|---|---|
| ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ | ์ง์ | O | O | ์๋ฐฑ ns |
| ๋ชจ๋ ์ค์์น (์ปค๋ ์ง์ ) | ์ง์ | O | O | 100~500 ns (KPTI ์ ๋ ๋น์) |
| ์บ์ ์ฝ๋ | ๊ฐ์ | O (ํผ) | O (์์) | ์~์์ญ ฮผs |
| TLB flush / ํ์ด์ง ํ ์ด๋ธ ์ํฌ | ๊ฐ์ | O | X | ์ ฮผs |
| ํ์ดํ๋ผ์ธยท๋ถ๊ธฐ ์์ธก | ๊ฐ์ | O | O | ์์ญ ns~์๋ฐฑ ns |
์ดํฉ: ์ค๋ ๋ ์ ํ ์ฝ 1~5ฮผs, ํ๋ก์ธ์ค ์ ํ ์ฝ 5~20ฮผs (์ํฌ๋ก๋ยทCPU์ ๋ฐ๋ผ ๋ณ๋).
7. ํ๋ก์ธ์ค vs ์ค๋ ๋ ์ปจํ ์คํธ ์ค์์น ๋น์ฉ ๋น๊ต
19๋ฒ์์ ๋ค๋ฃฌ ๋น๊ต๋ฅผ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ ๊ด์ ์์ ์ ๋ฐํ๊ฒ ๋ค์ ๋ด ๋๋ค.
๋น๊ต ํ
| ๋น์ฉ ํญ๋ชฉ | ํ๋ก์ธ์ค ์ ํ | ์ค๋ ๋ ์ ํ (๊ฐ์ ํ๋ก์ธ์ค) |
|---|---|---|
| ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ | O | O |
| ํ์ด์ง ํ ์ด๋ธ ๋ฒ ์ด์ค (cr3) ๊ต์ฒด | O | X |
| TLB flush (PCID ์์ ์) | O | X |
| L1/L2 ์บ์ ์ฝ๋ | ํผ (working set ์์ ๊ต์ฒด) | ๋ณดํต (์ค๋ ๋๋ณ working set ์ ๋) |
| L1 i-cache ์ฝ๋ | ํผ | ๋ณดํต (์ฝ๋ ์ผ๋ถ ๊ณต์ ) |
| ํธ๋ค ํ ์ด๋ธ ๊ต์ฒด | O | X |
| ๋ณด์ ํ ํฐ ๊ต์ฒด | O | X |
| ๋ชจ๋ ์ค์์น ์์ฒด | O | O |
| ์ด ๋น์ฉ (๋๋ต) | 5~20 ฮผs | 1~5 ฮผs |
| ์๋ ๋น์ฉ | 5~10๋ฐฐ | ๊ธฐ์ค |
์บ์ ์ฝ๋์ ์ฐจ์ด๊ฐ ๋ฏธ๋ฌํ ์ด์
๊ฐ์ ํ๋ก์ธ์ค์ ์ค๋ ๋๋ค๋ working set์ด ๋ค๋ฅด๋ฉด ์บ์ ์ฝ๋ ๋น์ฉ์ด ํฝ๋๋ค โ ์๋ฅผ ๋ค์ด ์ค๋ ๋ A๊ฐ ๋ถ๋ถ ํธ๋ฆฌ X๋ฅผ ์์ ํ๊ณ , ์ค๋ ๋ B๊ฐ ๋ถ๋ถ ํธ๋ฆฌ Y๋ฅผ ์์ ํ๋ฉด ๋ ๋ค ์๊ธฐ ๋ฐ์ดํฐ๋ก ์บ์๋ฅผ ์ฑ์๋ก๋๋ค. ๊ทธ๋๋ ์ฝ๋ ์์ญ(.text ์น์ )์ ๊ณต์ ๋๋ฏ๋ก i-cache ์ฝ๋๋ ํ๋ก์ธ์ค ์ ํ๋ณด๋ค ์์ต๋๋ค. ๋ ๊ฐ์ ํ๋ก์ธ์ค๋ผ ๊ฐ์ ์ฃผ์๊ฐ ๊ฐ์ TLB ์ํธ๋ฆฌ๋ ์ผ๋ถ ์ฌ์ฌ์ฉ๋ฉ๋๋ค.
PCID/ASID๋ก ์ขํ์ง ๊ฒฉ์ฐจ
ํ๋ x86(Haswell+)๊ณผ ARMv8์ TLB ์ํธ๋ฆฌ์ ํ๋ก์ธ์ค ID๋ฅผ ํ๊น ํด ํ๋ก์ธ์ค ์ ํ ์ ์ ์ฒด flush๋ฅผ ํํผํฉ๋๋ค. ๊ทธ๋์ PCID๊ฐ ํ์ฑํ๋ ์์คํ ์์ ํ๋ก์ธ์ค ์ ํ ๋น์ฉ์ด ์์ ๋ณด๋ค ์ค์์ต๋๋ค. ํ์ง๋ง ์บ์ ์ฝ๋๋ PCID๋ก๋ ํํผ ๋ชป ํจ โ TLB๋ ๋งคํ ์ ๋ณด ์บ์๊ณ , ์บ์๋ ๋ฐ์ดํฐ ์บ์๋ผ ๋ณ๊ฐ์ ๋๋ค.
๊ทธ๋์ ์ค๋ฌด ๊ฒฐ์
1
2
3
4
5
6
7
8
60fps ๊ฒ์ ์์ง (ํ๋ ์๋น 16.6ms):
โ ํ ๋ฒ์ ์๋ง ๊ฐ์ฒด ๋๊ธฐํ
โ ํ๋ก์ธ์ค ์ ํ ๋น์ฉ์ ๊ฒฌ๋ ์ ์์
โ ๋ฉํฐ์ค๋ ๋ + ๊ฐ์ ํ๋ก์ธ์ค ์์์ ๊ฒ์/๋ ๋ ์ค๋ ๋ ๋ถ๋ฆฌ
Chrome ํญ (๋ณด์ ๊ฒฉ๋ฆฌ ์ฐ์ ):
โ ์ปจํ
์คํธ ์ค์์นญ ๋น์ฉ๋ณด๋ค ๊ฒฉ๋ฆฌ๊ฐ ์ค์
โ ๋ฉํฐํ๋ก์ธ์ค ์ฑํ, IPC ๋น์ฉ ๊ฐ์
19๋ฒ์ ๊ฒฐ๋ก ์ ๊ทธ๋๋ก ์ด์ด๋ฐ์ต๋๋ค โ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ ๋ฉํฐํ๋ก์ธ์ค vs ๋ฉํฐ์ค๋ ๋ ์ ํ์ ํต์ฌ ๋ณ์ ์ค ํ๋์ ๋๋ค.
8. ์ค์ผ์ค๋ง ์๊ณ ๋ฆฌ์ฆ๊ณผ์ ์ฐ๊ด โ ์ ์ ํ/๋น์ ์ ํ/RR/์ฐ์ ์์
์ ์ ํ vs ๋น์ ์ ํ
| ํญ๋ชฉ | ์ ์ ํ (Preemptive) | ๋น์ ์ ํ / ํ๋ ฅ์ (Cooperative) |
|---|---|---|
| ์ค์์นญ ํธ๋ฆฌ๊ฑฐ | ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก ๊ฐ์ | ์ค๋ ๋์ ์๋ฐ์ ์๋ณด |
| ์๋ต์ฑ | ์ข์ (๋ณด์ฅ ๊ฐ๋ฅ) | ๋์จ (ํ ์ค๋ ๋๊ฐ ์๋ณด ์ ํ๋ฉด ๋ฉ์ถค) |
| ์ปจํ ์คํธ ์ค์์นญ ๋น๋ | ๋์ (quantum๋ง๋ค) | ๋ฎ์ (์๋ณดํ ๋๋ง) |
| ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ | ๋์ (๋์ ) | ๋ฎ์ |
| ์ฌ๋ก | WindowsยทLinuxยทmacOS | Windows 3.1ยท์์ macOSยทFiberยท์ฝ๋ฃจํด |
Round-Robin (RR)
๊ฐ์ฅ ๋จ์ํ ์ ์ ํ ์ค์ผ์ค๋ง์ ๋๋ค. ๋ชจ๋ Ready ์ค๋ ๋์ ๊ฐ์ time slice(quantum)๋ฅผ ๋๋ฆฌ๋ฉฐ ์ํํฉ๋๋ค.
1
2
3
4
Ready ํ: [A, B, C, D]
quantum ๋ง๋ฃ โ A๋ ํ ๋์ผ๋ก โ ๋ค์์ B
quantum ๋ง๋ฃ โ B๋ ํ ๋์ผ๋ก โ ๋ค์์ C
...
์ฅ์ ์ ๊ณต์ ์ฑ๊ณผ ๋จ์ํจ, ๋จ์ ์ ์ฐ์ ์์ ๋ฌด์ยท์งง์ ์์ ๊ณผ ๊ธด ์์ ์ ๋๋ฑ ์ฒ๋ฆฌ์ ๋๋ค.
์ฐ์ ์์ ์ค์ผ์ค๋ง
Ready ํ๋ฅผ ์ฐ์ ์์๋ณ๋ก ๋๋๊ณ , ํญ์ ๊ฐ์ฅ ๋์ ์ฐ์ ์์ ํ์ ์ค๋ ๋๋ฅผ ๋จผ์ ๋์คํจ์นํฉ๋๋ค.
- ์ฅ์ : ์ค์ํ ์์ (์ธํฐ๋ํฐ๋ธยท์ค์๊ฐ) ๋ณด์ฅ
- ๋จ์ : ๊ธฐ์(starvation) โ ๋ฎ์ ์ฐ์ ์์ ์ค๋ ๋๊ฐ ์์ํ ๋ชป ๋ ์ ์์
- ํด๊ฒฐ์ฑ : ์ฐ์ ์์ ๋ถ์คํ (priority boost) โ Windows๋ ์ค๋ ๊ธฐ๋ค๋ฆฐ ์ค๋ ๋์ ์ฐ์ ์์๋ฅผ ์ผ์์ ์ผ๋ก ์ฌ๋ฆผ
Windows๋ ์ฐ์ ์์ 0~31์ ์ฐ๊ณ (0~15: dynamic, 16~31: real-time), I/O ์๋ฃยทUI ์ด๋ฒคํธ ์ ๋ถ์คํ ์ผ๋ก ์๋ต์ฑ์ ๋์ ๋๋ค.
MLFQ (Multi-Level Feedback Queue)
์ฌ๋ฌ ์ฐ์ ์์ ํ๋ฅผ ๋๊ณ , ์ค๋ ๋์ ํ๋ ํจํด์ ๋ฐ๋ผ ์๋์ผ๋ก ํ ์ฌ์ด๋ฅผ ์ด๋์ํต๋๋ค.
1
2
3
4
5
6
7
8
ํ 1 (๋์ ์ฐ์ ์์, ์งง์ quantum)
ํ 2 (์ค๊ฐ ์ฐ์ ์์, ์ค๊ฐ quantum)
ํ 3 (๋ฎ์ ์ฐ์ ์์, ๊ธด quantum)
์ ์ค๋ ๋ โ ํ 1 (์งง์ quantum, ์๋ต์ฑ ์ฐ์ )
quantum ๋ค ์ฐ๊ณ ๋ ์ ๋๋จ โ ํ 2๋ก ๊ฐ๋ฑ (CPU-bound ์์ฌ)
quantum ๋ค ์ฐ๊ณ ๋ ์ ๋๋จ โ ํ 3๋ก ๊ฐ๋ฑ
I/O ๋๊ธฐ๋ก ์๋ณด โ ๋ค์ ํ 1๋ก ์น๊ฒฉ (์ธํฐ๋ํฐ๋ธ๋ก ์ฌ๋ถ๋ฅ)
์ด๊ฒ ์ธํฐ๋ํฐ๋ธ ์์ ๊ณผ ๋ฐฐ์น ์์ ์ ์๋์ผ๋ก ๋ถ๋ฅํฉ๋๋ค. Windows์ dynamic ์ฐ์ ์์, Linux์ CFS(Completely Fair Scheduler) ๊ฐ์ ํ๋ ์ค์ผ์ค๋ฌ๋ค์ ์ ์กฐ์ ๋๋ค.
time slice (quantum) ๊ธธ์ด์ ํธ๋ ์ด๋์คํ
| quantum ๊ธธ์ด | ์ปจํ ์คํธ ์ค์์นญ ๋น๋ | ์๋ต์ฑ | throughput |
|---|---|---|---|
| ์งง์ (1ms) | ๋์ | ์ข์ | ๋์จ (์ค๋ฒํค๋ ๋์ ) |
| ๋ณดํต (10~20ms) | ๋ณดํต | ๋ณดํต | ๋ณดํต |
| ๊ธบ (100ms+) | ๋ฎ์ | ๋์จ (๋๊ธฐ ์๊ฐ ์ฆ๊ฐ) | ์ข์ |
Windows ๊ธฐ๋ณธ quantum์ ์ฝ 15.6ms(10ms๋ ๊ฐ๋ฅ, ๋ฉํฐ๋ฏธ๋์ด ํ์ด๋จธ๋ก 1ms๊น์ง ๋จ์ถ ๊ฐ๋ฅ), Linux CFS๋ ๋์ ์ผ๋ก ๊ฒฐ์ ํฉ๋๋ค(๋ณดํต 4ms ์ดํ). ๊ฒ์์ด๋ ๋ฉํฐ๋ฏธ๋์ด ์ฑ์ timeBeginPeriod(1)๋ก quantum์ ์ค์ฌ ์๋ต์ฑ์ ํ๋ณดํ์ง๋ง, ์ด๋ ์์คํ
์ ์ฒด์ ์ํฅ์ ์ฃผ๋ฏ๋ก ์ ์คํ ์จ์ผ ํฉ๋๋ค(๋
ธํธ๋ถ ๋ฐฐํฐ๋ฆฌ ์๋ช
๋จ์ถ ๋ฑ).
CPU Affinity์ NUMA
์ค์ผ์ค๋ฌ๊ฐ ๋ค์ ์ค๋ ๋๋ฅผ ๊ณ ๋ฅผ ๋, ๊ทธ ์ค๋ ๋๊ฐ ๋ง์ง๋ง์ ์คํ๋๋ ์ฝ์ด์ ๊ฐ์ ์ฝ์ด์ ๋ฐฐ์นํ๋ฉด L1/L2 ์บ์๊ฐ ์ผ๋ถ ์ด์ ์์ด ์บ์ ์ฝ๋ ๋น์ฉ์ ์ค์ผ ์ ์์ต๋๋ค. ์ด๊ฒ CPU affinity ์ต์ ํ์
๋๋ค. ๋ฉํฐ ์์ผ NUMA(Non-Uniform Memory Access) ์์คํ
์์ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ ์๊ฐ์ด ๋
ธ๋๋ณ๋ก ๋ฌ๋ผ์, ์ค๋ ๋๋ฅผ ์๊ธฐ ๋ฉ๋ชจ๋ฆฌ๊ฐ ์๋ NUMA ๋
ธ๋์ ๋ฌถ์ด๋๋ ๊ฒ ์ค์ํฉ๋๋ค. Windows๋ SetThreadAffinityMask/SetThreadIdealProcessor, Linux๋ sched_setaffinity๋ก ์ ์ดํฉ๋๋ค.
9. Windows ๊ด์ โ Win32 ์ค๋ ๋ API์ ์ปจํ ์คํธ ์ค์์นญ
์ฌ๊ธฐ๋ถํฐ๋ MSVC ๋ฌธ์ ํธ๋ฆฌ(learn.microsoft.com/ko-kr/cpp/)๋ฅผ ๋ฐ๋ผ๊ฐ๋ฉฐ Windows์ ์ปจํ
์คํธ ์ค์์นญ ๋ฉ์ปค๋์ฆ์ ๋จ๊ณ๋ณ๋ก ๋ด
๋๋ค.
9.1 CreateThread โ ๊ฐ์ฅ ๊ธฐ๋ณธ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <windows.h>
DWORD WINAPI WorkerProc(LPVOID lpParam) {
DWORD id = GetCurrentThreadId();
// ... ์์
...
return 0;
}
int main() {
HANDLE hThread = CreateThread(
NULL, // ๊ธฐ๋ณธ ๋ณด์
0, // ๊ธฐ๋ณธ ์คํ ํฌ๊ธฐ (1MB)
WorkerProc, // ์์ ํจ์
NULL, // ์ธ์
0, // ์ฆ์ ์คํ (CREATE_SUSPENDED ์ ์ค)
NULL // ThreadId ์ถ๋ ฅ (NULL์ด๋ฉด ๋ฌด์)
);
WaitForSingleObject(hThread, INFINITE); // ์ค๋ ๋ ์ข
๋ฃ ๋๊ธฐ โ ์ปจํ
์คํธ ์ค์์น
CloseHandle(hThread);
return 0;
}
CreateThread๋ OS ์ปค๋์ ์ TCB๋ฅผ ๋ง๋ค๊ณ Ready ํ์ ๋ฃ์ต๋๋ค. ์ฆ์ ์คํํ ์ง(0) ์ผ์์ ์ง ์ํ๋ก ๋ง๋ค์ง(CREATE_SUSPENDED)๋ฅผ ์ ํํ ์ ์์ต๋๋ค. _beginthreadex ๋ CRT ์ด๊ธฐํ๋ฅผ ํจ๊ป ํด์ฃผ๋ ๋ํผ๋ผ C ๋ฐํ์์ ์ฐ๋ ์ฝ๋๋ ์ด์ชฝ์ ๊ถ์ฅํฉ๋๋ค(stdioยทerrnoยทstrtok ๊ฐ์ ํจ์๊ฐ TLS๋ฅผ ์ฐ๊ธฐ ๋๋ฌธ).
9.2 SwitchToThread / Sleep(0) โ ์๋ฐ์ ์๋ณด
1
2
3
4
5
6
7
8
9
10
// ๊ฐ์ ์ฝ์ด์ ๋ค๋ฅธ Ready ์ค๋ ๋์ ์๋ณด
BOOL switched = SwitchToThread();
// switched == TRUE: ์ค์ ๋ก ๋ค๋ฅธ ์ค๋ ๋๊ฐ ์คํ๋์
// switched == FALSE: ์๋ณดํ ์ค๋ ๋๊ฐ ์์ด ์ฆ์ ๋ณต๊ท
// ๊ฐ์ ์ฐ์ ์์ ์ค๋ ๋์ ์๋ณด (์์ผ๋ฉด ๊ทธ๋ฅ 0ms ๋๊ธฐ ํ ๋ณต๊ท)
Sleep(0);
// 1ms ๋๊ธฐ (์ค์ ๋ก quantum ๋จ์๋ก ๋ฐ์ฌ๋ฆผ โ ๋ณดํต 15.6ms)
Sleep(1);
์ฐจ์ด๋ฅผ ๋ช ํํ ์ ๋ฆฌํ๋ฉด:
| ํธ์ถ | ์๋ณด ๋์ | ์ปจํ ์คํธ ์ค์์น | ๊ถ์ฅ ์ฌ์ฉ์ฒ |
|---|---|---|---|
Sleep(0) | ๊ฐ์ ์ฐ์ ์์ ์ค๋ ๋ | ํ๋ณด ์์ ๋๋ง | ์ฐ์ ์์ ๊ท ๋ฑ spin loop |
SwitchToThread | ๊ฐ์ ์ฝ์ด์ ๋ชจ๋ Ready ์ค๋ ๋ | ํ๋ณด ์์ ๋๋ง | spin lock์ ์๋ณด ๋จ๊ณ |
Sleep(1+) | ๋ชจ๋ ํ๋ณด (์ง์ ์๊ฐ ํ ๊นธ) | ํญ์ | ์ง์ง ๋๊ธฐ |
_mm_pause | ์๋ณด ์ ํจ | ์์ | ์งง์ spin (CPU ํํธ๋ง) |
spin lock ๊ตฌํ์์ ํํ ํจํด์:
1
2
3
4
while (!try_lock()) {
for (int i = 0; i < 16; ++i) _mm_pause(); // CPU์ spin ํํธ (์ปจํ
์คํธ ์ค์์น ์์)
if (!try_lock()) SwitchToThread(); // ๊ทธ๋๋ ๋ชป ์ก์ผ๋ฉด ์๋ณด
}
9.3 WaitForSingleObject / WaitForMultipleObjects โ ๋ธ๋กํน
1
2
3
4
5
6
7
8
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL); // auto-reset event
// ๋ค๋ฅธ ์ค๋ ๋์์ SetEvent(hEvent) ํ ๋๊น์ง ๋๊ธฐ โ ์ปจํ
์คํธ ์ค์์น
DWORD result = WaitForSingleObject(hEvent, INFINITE);
// ์ฌ๋ฌ ๊ฐ์ฒด ์ค ํ๋๋ผ๋ ์๊ทธ๋๋ ๋๊น์ง
HANDLE handles[] = { hEvent1, hEvent2, hMutex };
DWORD which = WaitForMultipleObjects(3, handles, FALSE, INFINITE);
WaitForSingleObject๋ ํญ์ ์ปค๋ ์ง์
ํฉ๋๋ค. ๊ฐ์ฒด๊ฐ ์ด๋ฏธ ์๊ทธ๋ ์ํ๋ฉด ์ฆ์ ๋ณต๊ท(์ปจํ
์คํธ ์ค์์น ์์), ์๋๋ฉด ์ค๋ ๋๋ฅผ Wait ์ํ๋ก ์ ํํ๊ณ ์ปจํ
์คํธ ์ค์์นํฉ๋๋ค. ๋ ๋ฒ์งธ ์ธ์ INFINITE๋ ์๊ฐ ์ ํ ์์, 0์ ์ฆ์ ํด๋ง(ํฌ๊ธฐ), 0 < n ์ n ๋ฐ๋ฆฌ์ด ๋๊ธฐ.
9.4 SuspendThread / ResumeThread โ ๊ฐ์ ์ผ์์ ์ง
1
2
DWORD prev = SuspendThread(hThread); // ์นด์ดํฐ ์ฆ๊ฐ, 0๋ณด๋ค ํฌ๋ฉด ์ผ์์ ์ง ์ํ
ResumeThread(hThread); // ์นด์ดํฐ ๊ฐ์, 0๋๋ฉด ์ฌ๊ฐ
์ค๋ ๋๋ฅผ ์ธ๋ถ์์ ๊ฐ์ ๋ก ์ผ์์ ์ง/์ฌ๊ฐํ๋ ํธ์ถ์
๋๋ค. ๋๋ฒ๊ฑฐ(SuspendThread๋ก ๋ฉ์ถฐ์ ์ฝ์คํ ๊ฒ์ฌ), ํ๋กํ์ผ๋ฌ(์ํ๋ง ์ ์ ๊น ๋ฉ์ถค), ์ผ๋ถ ์ ์ด ์๋๋ฆฌ์ค์์๋ง ์๋๋ค. ์ฌ์ฉ์ ์ฝ๋์์ ๋๊ธฐํ ๋ชฉ์ ์ผ๋ก ์ฐ๋ฉด ์ ๋จ โ ๋ฝ์ ๋ค๊ณ ์๋ ์ค๋ ๋๋ฅผ ๋ฉ์ถ๋ฉด ๋ฐ๋๋ฝ์ด ๋ฉ๋๋ค.
9.5 ์ปจํ ์คํธ ์ค์์นญ๊ณผ์ ๊ด๊ณ ์ ๋ฆฌ
1
2
3
4
5
6
CreateThread โ ์ TCB ์์ฑ โ Ready ํ ์ง์
โ ์ค์ผ์ค๋ฌ ๋์คํจ์น ์ ์ปจํ
์คํธ ์ค์์น
SwitchToThread โ ์ฆ์ ์๋ณด โ ํ๋ณด ์์ผ๋ฉด ์ปจํ
์คํธ ์ค์์น
Sleep(0) โ ๊ฐ์ ์ฐ์ ์์ ์๋ณด
Sleep(n>0) โ ํญ์ Wait ์ํ โ ์ปจํ
์คํธ ์ค์์น
WaitForSingleObject โ ๊ฐ์ฒด ๋ฏธ์๊ทธ๋ ์ โ ์ปจํ
์คํธ ์ค์์น
SuspendThread โ ๋์ ์ค๋ ๋ Wait ์ํ (์๊ธฐ ์ปจํ
์คํธ ์ค์์น X)
10. Windows ๋๊ธฐํ ๊ฐ์ฒด๋ณ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ
MSVC ๋ฌธ์ ํธ๋ฆฌ์์ ๊ฐ์ฅ ์ค์ํ ๋น์ฉ ์ฐจ์ด๋ฅผ ๋ง๋๋ ์์ญ์ ๋๋ค. ๊ฐ์ โ๋ฝโ์ด๋ผ๋ ์ด๋ค ๊ฐ์ฒด๋ฅผ ์ฐ๋๋์ ๋ฐ๋ผ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ด 100๋ฐฐ๊น์ง ๋ฌ๋ผ์ง๋๋ค.
๋น์ฉ ์คํํธ๋ผ (๋ฎ์ โ ๋์)
| ๊ฐ์ฒด | ์์ญ | ๊ฒฝํฉ ์ ๋์ | ํ ํ ๋น์ฉ | ํ๋ก์ธ์ค ๊ฐ |
|---|---|---|---|---|
std::atomic (lock-free) | ์ฌ์ฉ์ ๋ชจ๋ | CPU ๋ช ๋ น์ผ๋ก ์ฌ์๋ | ์ ns | X |
| Critical Section | ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ | ์งง๊ฒ spin โ ๊ทธ๋๋ ์ ๋๋ฉด ์ปค๋ ์ง์ | 50~100 ns (๋ฌด๊ฒฝํฉ) | X (๊ฐ์ ํ๋ก์ธ์ค๋ง) |
| SRWLock | ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ | ๋น์ท | 50~100 ns | X |
| Condition Variable | ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ | SleepConditionVariableSRW๋ก ๋๊ธฐ | ๋น์ท | X |
| Mutex (์ปค๋ ๊ฐ์ฒด) | ์ปค๋ ๋ชจ๋ | ํญ์ ์ปค๋ ์ง์ | 1~3 ฮผs | O |
| Event | ์ปค๋ ๋ชจ๋ | ํญ์ ์ปค๋ ์ง์ | ๋น์ท | O |
| Semaphore | ์ปค๋ ๋ชจ๋ | ํญ์ ์ปค๋ ์ง์ | ๋น์ท | O |
Critical Section โ ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์
1
2
3
4
5
6
7
8
9
10
11
12
#include <windows.h>
CRITICAL_SECTION cs;
InitializeCriticalSection(&cs);
// ๋๋ spin count ์ง์ (๊ฒฝํฉ ์ spinํ ํ์)
InitializeCriticalSectionAndSpinCount(&cs, 4000);
EnterCriticalSection(&cs);
// ์๊ณ ๊ตฌ์ญ
LeaveCriticalSection(&cs);
DeleteCriticalSection(&cs);
๋ด๋ถ ๋์:
EnterCriticalSection์ง์ โ ์ฌ์ฉ์ ๋ชจ๋์์ ๋ฝ ์นด์ดํฐ atomic ์ฆ๊ฐ ์๋- ๋ฝ์ด ๋น์ด์์ผ๋ฉด ์ฆ์ ํ๋ (์ปค๋ ์ง์ ์์, ์ปจํ ์คํธ ์ค์์น ์์)
- ๋ฝ์ด ์กํ์์ผ๋ฉด
SpinCount๋งํผ spin (_mm_pause๋ฐ๋ณต) - ๊ทธ๋๋ ๋ชป ์ก์ผ๋ฉด ๊ทธ๋ ์ปค๋ ์ง์ โ ์ด๋ฒคํธ ๊ฐ์ฒด์์ ๋๊ธฐ โ ์ปจํ ์คํธ ์ค์์น
ํต์ฌ ํน์ฑ:
- ๊ฐ์ ํ๋ก์ธ์ค ๋ด์์๋ง ์ฌ์ฉ ๊ฐ๋ฅ (์ปค๋ ๊ฐ์ฒด๊ฐ ์๋๋ผ ์ฌ์ฉ์ ๋ฉ๋ชจ๋ฆฌ์ ์นด์ดํฐ ๋ณด๊ด)
- ์ฌ์ง์ ๊ฐ๋ฅ (recursive) โ ๊ฐ์ ์ค๋ ๋๊ฐ ์ฌ๋ฌ ๋ฒ Enter ๊ฐ๋ฅ
- ๋ฌด๊ฒฝํฉ ์ผ์ด์ค์์ 50~100 nanosecond โ Mutex์ 20~50๋ฐฐ ๋น ๋ฆ
SRWLock (Slim Reader/Writer Lock) โ Vista+
1
2
3
4
5
6
7
8
9
SRWLOCK lock = SRWLOCK_INIT;
// ์ฝ๊ธฐ ๋ฝ (์ฌ๋ฌ reader ๋์ ๊ฐ๋ฅ)
AcquireSRWLockShared(&lock);
ReleaseSRWLockShared(&lock);
// ์ฐ๊ธฐ ๋ฝ (๋ฐฐํ์ )
AcquireSRWLockExclusive(&lock);
ReleaseSRWLockExclusive(&lock);
ํน์ฑ:
- R/W ๋ถ๋ฆฌ โ reader๋ ๋์์ ์ฌ๋ฌ ๊ฐ, writer๋ ํ๋๋ง
- Critical Section๋ณด๋ค ๊ฐ๋ณ๊ณ , ๊ฒฝํฉ ์ spin ํ ์ปค๋ ๋๊ธฐ
- ์ฌ์ง์ ๋ถ๊ฐ โ ๊ฐ์ ์ค๋ ๋๊ฐ Acquire ๋ ๋ฒ ํ๋ฉด ๋ฐ๋๋ฝ
- read ๋น์ค์ด ํฐ ์๋ฃ๊ตฌ์กฐ(์์ฃผ ์ฝํ๋ ์บ์ ๋ฑ)์์ Critical Section๋ณด๋ค ์ ๋ฆฌ
- C++ ํ์ค
std::shared_mutex๊ฐ MSVC์์ SRWLock ์์ ๊ตฌํ๋จ
Mutex / Event / Semaphore โ ํญ์ ์ปค๋
1
2
3
4
5
HANDLE hMutex = CreateMutex(NULL, FALSE, TEXT("MyMutex"));
WaitForSingleObject(hMutex, INFINITE); // ํญ์ ์ปค๋ ์ง์
// ์๊ณ ๊ตฌ์ญ
ReleaseMutex(hMutex);
CloseHandle(hMutex);
ํน์ฑ:
- ์ปค๋ ๊ฐ์ฒด โ
WaitForSingleObject๋ก ๋๊ธฐ โ ํญ์ ์ปค๋ ์ง์ โ ํญ์ ์ปจํ ์คํธ ์ค์์น ๊ฐ๋ฅ - ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ๊ฐ๋ฅ โ ์ด๋ฆ์ ์ฃผ๋ฉด ๋ค๋ฅธ ํ๋ก์ธ์ค๊ฐ
OpenMutex๋ก ์ด ์ ์์ - ๋ฌด๊ฒฝํฉ์ด๋ผ๋ 1~3 ฮผs โ Critical Section์ 20~50๋ฐฐ ๋น์ธ๋ค
- Event๋ ์๊ทธ๋ ์ํ๋ฅผ ๊ฐ์ง๋ ๊ฐ์ฒด(SetEvent/ResetEvent), Semaphore๋ ์นด์ดํฐ๋ฅผ ๊ฐ์ง๋ ๋ฝ
Condition Variable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
SRWLOCK lock = SRWLOCK_INIT;
CONDITION_VARIABLE cv = CONDITION_VARIABLE_INIT;
// ๋๊ธฐ ์ธก
AcquireSRWLockExclusive(&lock);
while (!ready) {
SleepConditionVariableSRW(&cv, &lock, INFINITE, 0);
// ์๋์ผ๋ก ๋ฝ ํด์ โ ๋๊ธฐ โ ๊นจ์ด๋๋ฉด ๋ฝ ์ฌํ๋
}
AcquireSRWLockExclusive ํด์ ๋ ์ฌ์ฉ์๊ฐ ์ง์
// ๊นจ์ฐ๊ธฐ ์ธก
AcquireSRWLockExclusive(&lock);
ready = TRUE;
ReleaseSRWLockExclusive(&lock);
WakeConditionVariable(&cv); // ๋๋ WakeAllConditionVariable
ํน์ฑ:
- ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ โ SRWLock ์์์ ๋์
- C++
std::condition_variable์ด MSVC์์ ์ด๊ฑธ ๋ํ
์ ํ ๊ฐ์ด๋
1
2
3
4
5
๊ฐ์ ํ๋ก์ธ์ค, ์งง์ ์๊ณ ๊ตฌ์ญ, ์ฌ์ง์
ํ์ โ Critical Section
๊ฐ์ ํ๋ก์ธ์ค, read ๋น์ค ํผ โ SRWLock
๊ฐ์ ํ๋ก์ธ์ค, ๋จ์ผ ์นด์ดํฐ read-modify-write โ std::atomic (lock-free)
๊ฐ์ ํ๋ก์ธ์ค, ์กฐ๊ฑด ๋๊ธฐ ํจํด โ Condition Variable + SRWLock
ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ํ์ โ Mutex / Event / Semaphore
MSVC ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด SRWLock๊ณผ Critical Section์ ๊ฐ์ ํ๋ก์ธ์ค ๋ด์์ ๊ฐ์ฅ ๊ฐ๋ฒผ์ด ๋๊ธฐํ ์ต์ ์ด๊ณ , ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ๊ฐ ํ์ํ ๋๋ง ๋ฌด๊ฑฐ์ด ์ปค๋ ๊ฐ์ฒด๋ฅผ ์ ํํด์ผ ํฉ๋๋ค.
11. Concurrency Runtime / PPL โ ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ ์ค์ผ์ค๋ฌ
MSVC๊ฐ ์ ๊ณตํ๋ Concurrency Runtime(/cpp/parallel/concrt/)์ OS ์์ ์ฌ์ฉ์ ๋ชจ๋ Task Scheduler๋ฅผ ๋์ด ์ปจํ
์คํธ ์ค์์นญ ๋น์ฉ์ ๋ ์ค์
๋๋ค. PPL(Parallel Patterns Library) ์ด ๊ทธ ์์ ์นํ ๊ณ ์์ค API์
๋๋ค.
ํต์ฌ ๊ตฌ์ฑ์์
1
2
3
4
5
6
7
8
โโ PPL (Parallel Patterns Library) โ ๊ณ ์์ค ์๊ณ ๋ฆฌ์ฆ
โ parallel_for, parallel_for_each, parallel_invoke, task<T>
โ
โโ Agents Library โ ๋ฉ์์ง ํจ์ฑ ๋ชจ๋ธ
โ agent, message_block
โ
โโ Concurrency Runtime โ ๊ทธ ์๋ Task Scheduler
Scheduler, ScheduleGroup, Context, Task
Task Scheduler์ ํต์ฌ ๋ฉ์ปค๋์ฆ
1. Work Stealing โ ๋ถํ ๋ถ์ฐ
๊ฐ ์์ปค ์ค๋ ๋๊ฐ ์๊ธฐ ์์ ํ๋ฅผ ๊ฐ์ง๊ณ , ํ๊ฐํ ์์ปค๊ฐ ๋ค๋ฅธ ์์ปค์ ํ ๋์์ ์์ ์ ํ์นฉ๋๋ค(steal). ํ์ ์ ๋์ ๋ค๋ฅด๊ฒ ์ฐ๋ deque ์๊ณ ๋ฆฌ์ฆ์ด๋ผ ๋ฝ ๊ฒฝํฉ์ด ๊ฑฐ์ ์๊ณ , ์ปจํ ์คํธ ์ค์์นญ ์์ด ๋ถํ ๋ถ์ฐ์ด ์ผ์ด๋ฉ๋๋ค.
1
2
3
4
5
Worker 1 ํ: [T1, T2, T3, T4] โ ์๊ธฐ๋ ์์์ pop
Worker 2 ํ: [] โ ๋น์์
โ steal!
Worker 2 ํ: [] โ Worker 1 ํ ๋ค์์ T4 ๊ฐ์ ธ๊ฐ
Worker 1 ํ: [T1, T2, T3]
2. Context::Block / Yield / Unblock โ ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ ์๋ณด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <concrt.h>
void MyTask() {
// ... ์์
...
// ์๋ฐ์ ์๋ณด โ ์ฌ์ฉ์ ๋ชจ๋, ์ปค๋ ์ง์
์์
Concurrency::Context::Yield();
// ๋ช
์์ ๋ธ๋ก (๋ค๋ฅธ ์ปจํ
์คํธ๊ฐ Unblock ํธ์ถ ์ ๊น์ง ๋๊ธฐ)
Concurrency::Context::Block();
// ๋ค๋ฅธ ์ปจํ
์คํธ๋ฅผ ๊นจ์
otherContext->Unblock();
}
Context::Yield๋ ๊ฐ์ ์ค์ผ์ค๋ฌ ์์ ๋ค๋ฅธ ready Task๋ก ์๋ณดํฉ๋๋ค โ OS ์ปจํ
์คํธ ์ค์์น ์์ด ์ฌ์ฉ์ ๋ชจ๋ ์คํ ์ ํ๋ง ์ผ์ผํต๋๋ค. Fiber์ ๋น์ทํ ๋ฉ์ปค๋์ฆ์ ConcRT๊ฐ ์ถ์ํํ ๊ฒ์
๋๋ค.
3. Oversubscription โ ์๋์ ๊ณผ๋ค ๊ตฌ๋
1
2
3
4
Concurrency::Context::Oversubscribe(true);
// ๋ธ๋กํน ํธ์ถ (์: I/O)
DoLongIO();
Concurrency::Context::Oversubscribe(false);
๋ธ๋กํน ํธ์ถ ์ง์ ์ Oversubscribe(true)๋ฅผ ํธ์ถํ๋ฉด ConcRT๊ฐ ์์๋ก ์ถ๊ฐ ์์ปค๋ฅผ ๋์ ๋ค๋ฅธ ์์
์ ์ฒ๋ฆฌํฉ๋๋ค. ๊ทธ ์ค๋ ๋๊ฐ ํ๋ ค๋๋ฉด ๋ค์ ์ ์ ์ด์. CPU-bound ์์
์์ ์ฝ์ด ์๋งํผ ์ค๋ ๋๋ฅผ ๋์ฐ๋ ๊ฒ ์ผ๋ฐ์ ์ด์ง๋ง, I/O ๋น์ค์ด ํฐ ์ํฌ๋ก๋์์ oversubscription์ด throughput์ ์ฌ๋ฆฝ๋๋ค.
PPL โ ๊ณ ์์ค API
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
#include <ppl.h>
// ๋ณ๋ ฌ for
Concurrency::parallel_for(0, 1000, [](int i) {
HeavyWork(i);
});
// ๋ณ๋ ฌ for_each
std::vector<int> v(1000);
Concurrency::parallel_for_each(v.begin(), v.end(), [](int& x) {
x *= 2;
});
// ๋์ task ์คํ
Concurrency::parallel_invoke(
[]{ TaskA(); },
[]{ TaskB(); },
[]{ TaskC(); }
);
// task ๊ฐ์ฒด โ ์์กด์ฑ๊ณผ ๊ฒฐ๊ณผ ์ฒ๋ฆฌ
Concurrency::task<int> t = Concurrency::create_task([]{ return ComputeResult(); });
t.then([](int result){
UseResult(result);
});
์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ ์ ๊ฐ ํจ๊ณผ
ConcRT์ ํต์ฌ ๊ฐ์น๋ ์ฌ์ฉ์ ๋ชจ๋์์ ์์
์ค์ผ์ค๋ง์ด ๋๋๋ ์ผ์ด์ค๋ฅผ ๋๋ ค OS ์ปจํ
์คํธ ์ค์์นญ์ ์ค์ด๋ ๊ฒ์
๋๋ค. 1000๊ฐ์ parallel_for ๋ฐ๋ณต์ OS ์ค๋ ๋ 1000๊ฐ๋ก ์ฒ๋ฆฌํ๋ฉด ์ปจํ
์คํธ ์ค์์นญ์ด 1000๋ฒ ๊ฐ๊น์ด ์ผ์ด๋์ง๋ง, ConcRT๋ ์ฝ์ด ์๋งํผ์ ์ค๋ ๋ ํ์์ work stealing์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก OS ์ค์์นญ์ด ๊ฑฐ์ ์์ต๋๋ค.
MSVC ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด Concurrency Runtime์ Windows์ ํ์ค ์ค๋ ๋ ํ API์๋ ๋ณ๊ฐ์ ์ฌ์ฉ์ ๋ชจ๋ ์ค์ผ์ค๋ฌ๋ฅผ ๊ฐ์ง๋ฉฐ,
parallel_for/task๊ฐ์ ๊ณ ์์ค ์ถ์ํ๋ฅผ ํตํด ์ปจํ ์คํธ ์ค์์นญ ๋น๋๋ฅผ ๋ฎ์ถฅ๋๋ค.
12. Fiber API์ UMS โ ์ปค๋ ๊ฐ์ ์๋ ํ๋ ฅ์ ์ค์์นญ
Fiber โ ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ ์ค๋ ๋
Fiber๋ ์ฌ์ฉ์ ๋ชจ๋์์๋ง ๊ด๋ฆฌ๋๋ ํ๋ ฅ์ ์คํ ๋จ์์ ๋๋ค. OS ์ปค๋์ Fiber๋ฅผ ๋ชจ๋ฅด๊ณ , ํ OS ์ค๋ ๋ ์์์ ์ฌ๋ฌ Fiber๊ฐ ์๊ธฐ๋ค๋ผ๋ฆฌ SPยทPC๋ฅผ ๋ฐ๊ฟ์น๊ธฐํ๋ฉฐ ์คํ๋ฉ๋๋ค.
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
32
#include <windows.h>
VOID CALLBACK FiberA(PVOID lpParameter) {
while (true) {
printf("Fiber A\n");
SwitchToFiber(g_FiberB); // B๋ก ์ ํ โ ์ฌ์ฉ์ ๋ชจ๋, ์์ญ ns
}
}
VOID CALLBACK FiberB(PVOID lpParameter) {
while (true) {
printf("Fiber B\n");
SwitchToFiber(g_FiberA);
}
}
LPVOID g_FiberMain;
LPVOID g_FiberA;
LPVOID g_FiberB;
int main() {
g_FiberMain = ConvertThreadToFiber(NULL); // ๋ฉ์ธ ์ค๋ ๋๋ฅผ Fiber๋ก ๋ณํ
g_FiberA = CreateFiber(0, FiberA, NULL);
g_FiberB = CreateFiber(0, FiberB, NULL);
SwitchToFiber(g_FiberA); // ์์
DeleteFiber(g_FiberA);
DeleteFiber(g_FiberB);
ConvertFiberToThread();
return 0;
}
Fiber ํน์ฑ
| ํญ๋ชฉ | Fiber | OS ์ค๋ ๋ |
|---|---|---|
| ๊ด๋ฆฌ ์ฃผ์ฒด | ์ฌ์ฉ์ ๋ชจ๋ (์ ํ๋ฆฌ์ผ์ด์ ) | OS ์ปค๋ |
| ์ค์์นญ ๋น์ฉ | ์์ญ ns | 1~5 ฮผs (์ค๋ ๋ ์ ํ) |
| ์ค์์นญ ํธ๋ฆฌ๊ฑฐ | SwitchToFiber (์๋ฐ์ ) | ํ์ด๋จธยทI/Oยท๋๊ธฐํ (๊ฐ์ ๊ฐ๋ฅ) |
| ๋ฉํฐ ์ฝ์ด ํ์ฉ | ๋ถ๊ฐ (ํ OS ์ค๋ ๋ ์) | ๊ฐ๋ฅ |
| ์์คํ ์ฝ ์ฐจ๋จ ์ | ํธ์คํธ OS ์ค๋ ๋ ์ฐจ๋จ โ ๋ค๋ฅธ Fiber๋ ๋ฉ์ถค | ๊ทธ ์ค๋ ๋๋ง ์ฐจ๋จ |
| ์ฌ์ฉ์ฒ | ์ฌ์ฉ์ ๋ชจ๋ ์ฝ๋ฃจํด, ๊ฒ์ ์์ง ์์ ์์คํ | ์ผ๋ฐ ๋์์ฑ |
Fiber์ ํ๊ณ
OS ์ปค๋์ Fiber๋ฅผ ๋ชจ๋ฅด๋ฏ๋ก ์์คํ ์ฝ์ด ๋ธ๋กํน๋๋ฉด ๊ทธ OS ์ค๋ ๋ ์ ์ฒด๊ฐ ๋ฉ์ถ๊ณ , ๊ทธ ์์ ๋ค๋ฅธ Fiber๋ค๋ ๋ฉ์ถฅ๋๋ค. ๊ทธ๋์ Fiber๋ ์์ CPU-bound ์์ ์ ์ ํฉํ๊ณ , I/O ์์ ๊ณผ ์์ด๋ฉด ์ํํฉ๋๋ค. ๋ ๋ฉํฐ ์ฝ์ด ํ์ฉ์ด ์ ๋ฉ๋๋ค โ ํ OS ์ค๋ ๋ ์์ Fiber๋ค์ด๋ผ ์ฝ์ด ํ๋์์๋ง ๋๋๋ค(์ฝ์ด๋ฅผ ๋ ์ฐ๋ ค๋ฉด OS ์ค๋ ๋๋ฅผ ์ฌ๋ฌ ๊ฐ ๋์ฐ๊ณ ๊ฐ์ ์์ Fiber๋ค์ ๋ฌ์ผ ํจ).
Fiber์ ์ค๋ฌด ์ฌ๋ก
- ๊ฒ์ ์์ง์ ์์ ์์คํ (Naughty Dog์ GDC ๋ฐํ โParallelizing the Naughty Dog Engineโ ์ฐธ๊ณ ) โ ์๋ฐฑ ๊ฐ์ ์์ ์ OS ์ค๋ ๋ ํ + Fiber๋ก ๋ฌถ์ด ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ ๊ทน๋จ์ ์ผ๋ก ์ค์
- C++20 ์ฝ๋ฃจํด ์ด์ ์ ์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ ์ค์ผ์ค๋ง โ ํ์ฌ๋ ์ฝ๋ฃจํด์ด ๋ ์์ฐ์ค๋ฌ์ด ๋์
- ๋ ๊ฑฐ์ ํ๋ ฅ์ ๋ฉํฐํ์คํน ์๋ฎฌ๋ ์ด์
UMS (User-Mode Scheduling) โ ์ ์ถฉ ๋ชจ๋ธ
UMS๋ ์ปค๋์ ์ค๋ ๋๋ฅผ ์์ง๋ง ์ค์ผ์ค๋ง์ ์ฌ์ฉ์ ๋ชจ๋์์ ํ๋ Windows 7+ x64์ ๋ชจ๋ธ์ ๋๋ค. Fiber์ ํ๊ณ(์์คํ ์ฝ ๋ธ๋กํน ์ ์ ์ฒด ๋ฉ์ถค)๋ฅผ ํด๊ฒฐํ๋ ค๋ ์๋์์ต๋๋ค.
1
2
3
Fiber: OS ๋ชจ๋ฆ โ I/O ๋ธ๋กํน ์ ํธ์คํธ ์ค๋ ๋ ์ ์ฒด ๋ฉ์ถค
์ผ๋ฐ ์ค๋ ๋: OS ๊ด๋ฆฌ โ ์ปจํ
์คํธ ์ค์์นญ ๋น์ธ๋ I/O ์์
UMS: OS๋ ์์ง๋ง ์ฌ์ฉ์๊ฐ ์ค์ผ์ค๋ง โ I/O ์ OS๊ฐ ์ฌ์ฉ์ ์ค์ผ์ค๋ฌ์ ์๋ฆผ
UMS ๋์:
- UMS ์์ปค ์ค๋ ๋๊ฐ ์์คํ ์ฝ์์ ๋ธ๋กํน๋๋ฉด OS๊ฐ ์ฌ์ฉ์ ๋ชจ๋ ์ค์ผ์ค๋ฌ์ ์ฝ๋ฐฑ์ผ๋ก ์๋ฆผ
- ์ค์ผ์ค๋ฌ๊ฐ ๋ค๋ฅธ UMS ์์ปค๋ฅผ ์ฆ์ ๋์คํจ์น (์ฌ์ฉ์ ๋ชจ๋์์ ๊ฒฐ์ )
- ๋ธ๋กํน ํ๋ฆฌ๋ฉด OS๊ฐ ๋ค์ ์๋ฆผ โ ์ค์ผ์ค๋ฌ๊ฐ ์ฌ๋ฐฐ์น
UMS๋ ๊ฐ๋ ฅํ์ง๋ง ์ฌ์ฉ์ด ๋ณต์กํด์ ์ค๋ฌด ์ฑํ๋ฅ ์ ๋ฎ๊ณ , ํ๋ Windows์์ Concurrency Runtime + ์ฝ๋ฃจํด์ด ๋ ์ผ๋ฐ์ ์ธ ์ ๊ทผ์ ๋๋ค. MSVC ๋ฌธ์ ํธ๋ฆฌ์์๋ UMS๋ ๋ณ๋ ์น์ ์ผ๋ก ๋ค๋ค์ง์ง๋ง deprecated ํ์๊ฐ ๋ถ๋ ๊ฒฝ์ฐ๊ฐ ๋์์ต๋๋ค.
์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ ๋น๊ต (์ด์ ๋ฆฌ)
| ๋จ์ | ์ค์์นญ ๋น์ฉ | ๋ฉํฐ ์ฝ์ด | I/O ๋ธ๋กํน ์์ |
|---|---|---|---|
Fiber (SwitchToFiber) | ~์์ญ ns | X | X |
| ConcRT Context::Yield | ~์์ญ~์๋ฐฑ ns | O | ๋ถ๋ถ์ |
| UMS | ~์๋ฐฑ ns~1 ฮผs | O | O |
| OS ์ค๋ ๋ (๊ฐ์ ํ๋ก์ธ์ค) | 1~5 ฮผs | O | O |
| OS ํ๋ก์ธ์ค | 5~20 ฮผs | O | O |
13. C++ ํ์ค ๋์์ฑ์ Windows ๋งคํ
std::thread โ _beginthreadex โ CreateThread
1
2
3
4
#include <thread>
std::thread t([]{ /* ์์
*/ });
t.join();
MSVC์ std::thread ๊ตฌํ์ ๋ด๋ถ์ ์ผ๋ก _beginthreadex๋ฅผ ํธ์ถํ๊ณ , ์ด๊ฒ ๋ค์ CreateThread๋ฅผ ํธ์ถํฉ๋๋ค. _beginthreadex๋ฅผ ๊ฑฐ์น๋ ์ด์ ๋ CRT์ TLS ์ด๊ธฐํ(stdio ๋ฝ, errno, strtok ๋ฑ)๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์
๋๋ค.
1
2
3
4
5
6
7
8
9
std::thread ์์ฑ์
โ
std::_Thrd_start (C ์ธํฐํ์ด์ค ์ด๋ํฐ)
โ
_beginthreadex (CRT TLS ์ด๊ธฐํ ํฌํจ)
โ
CreateThread (Win32 ์ปค๋ ์ค๋ ๋ ์์ฑ)
โ
์ TCB ์์ฑ โ Ready ํ โ ์ค์ผ์ค๋ฌ ๋์คํจ์น โ ์ปจํ
์คํธ ์ค์์น๋ก ์์
์ค๋ ๋ ์ข
๋ฃ๋ _endthreadex๋ก CRT cleanup์ ๊ฑฐ์ณ์ผ ํฉ๋๋ค. ๊ทธ๋์ raw CreateThread + ExitThread๋ฅผ ์ง์ ์ฐ๋ฉด CRT๊ฐ ๋ฉ๋ชจ๋ฆฌ ๋์๋ฅผ ์ผ์ผํฌ ์ ์์ต๋๋ค โ MSVC ๋ฌธ์๊ฐ ์ผ๊ด๋๊ฒ _beginthreadex ์ฌ์ฉ์ ๊ถ์ฅํ๋ ์ด์ ์
๋๋ค.
std::mutex โ SRWLock or Critical Section
1
2
3
4
#include <mutex>
std::mutex m;
std::lock_guard<std::mutex> lock(m); // ์ปจํ
์คํธ ์ค์์นญ ๋น์ฉ์ SRWLock ์์ค
MSVC์ std::mutex๋ Visual Studio 2019 16.x ์ดํ SRWLock ์์ ๊ตฌํ๋์ด ์์ต๋๋ค(์ด์ ๋ฒ์ ์ Critical Section). ๋ ๋ค ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ ์ด๋ผ ๋ฌด๊ฒฝํฉ ์ผ์ด์ค์์ ์ปจํ
์คํธ ์ค์์นญ์ด ์ผ์ด๋์ง ์์ต๋๋ค.
std::shared_mutex โ SRWLock (R/W ๋ถ๋ฆฌ)
1
2
3
4
5
#include <shared_mutex>
std::shared_mutex sm;
std::shared_lock lock(sm); // ์ฝ๊ธฐ ๋ฝ โ ์ฌ๋ฌ reader ๋์
// ๋๋ std::unique_lock โ ์ฐ๊ธฐ ๋ฝ
SRWLock์ R/W ๋ถ๋ฆฌ๋ฅผ ๊ทธ๋๋ก ๋ ธ์ถ. ์์ฃผ ์ฝ๊ณ ๊ฐ๋ ์ฐ๋ ์๋ฃ๊ตฌ์กฐ(์ค์ ยท์บ์)์ ์ ๋ฆฌ.
std::condition_variable โ Windows Condition Variable
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <condition_variable>
std::mutex m;
std::condition_variable cv;
bool ready = false;
// ๋๊ธฐ ์ธก
std::unique_lock<std::mutex> lock(m);
cv.wait(lock, []{ return ready; });
// ์ฌ์ฉ์ ๋ชจ๋์์ ๋๊ธฐ โ ๊นจ์ฐ๊ธฐ ์ ์ปจํ
์คํธ ์ค์์น
// ๊นจ์ฐ๊ธฐ ์ธก
{ std::lock_guard lock(m); ready = true; }
cv.notify_one();
MSVC๋ Windows Condition Variable + SRWLock ์กฐํฉ์ผ๋ก ๊ตฌํ. ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ ์ด๋ผ ๊ฐ๋ฒผ์.
std::atomic<T> โ ์ปจํ
์คํธ ์ค์์นญ ์์
1
2
3
4
#include <atomic>
std::atomic<int> counter{0};
counter.fetch_add(1); // CPU ๋ช
๋ น(LOCK XADD) โ OS ์ง์
์์, ์ปจํ
์คํธ ์ค์์นญ ์์
Lock-free ์๊ณ ๋ฆฌ์ฆ์ ๊ธฐ์ด. CPU์ LOCK ์ ๋์ฌ ๋ช ๋ น(LOCK XADD, LOCK CMPXCHG ๋ฑ)์ ์ฌ์ฉํด ๋จ์ผ ๋ช ๋ น ์์ค์์ ์์์ฑ์ ๋ณด์ฅ. ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋์ง ์๋ ์ ์ผํ ๋๊ธฐํ ๋๊ตฌ โ ๋จ์ ์นด์ดํฐยทํ๋๊ทธยทCAS ํจํด์ ๊ฐ์ฅ ๋น ๋ฆ.
std::async / std::future โ ์ค๋ ๋ ํ ๋๋ ์ ์ค๋ ๋
1
2
3
4
#include <future>
std::future<int> f = std::async(std::launch::async, []{ return Compute(); });
int result = f.get();
std::launch::async๋ ์ ์ค๋ ๋, std::launch::deferred๋ get() ํธ์ถ ์์ ์ ๋๊ธฐ ์คํ. ์ ์ฑ
๋ฏธ์ง์ ์ ๊ตฌํ ์ ์(MSVC๋ ๋ณดํต deferred ๋๋ thread pool). MSVC์ thread pool ๊ตฌํ์ Windows์ ThreadPool API(SubmitThreadpoolWork)๋ฅผ ํ์ฉํฉ๋๋ค.
std::jthread (C++20) โ RAII ์๋ join
1
2
3
4
5
6
7
8
#include <thread>
{
std::jthread jt([](std::stop_token stoken){
while (!stoken.stop_requested()) { /* ์์
*/ }
});
// ์๋ฉธ์๊ฐ ์๋์ผ๋ก stop ์์ฒญ + join
}
C++20๋ถํฐ ํ์คํ๋ ์๋ join ์ค๋ ๋. 9๋ฒ RAII์ ๋์์ฑ ์์ฉ.
๋งคํ ์ข ํฉ ํ
| C++ ํ์ค | Windows ๊ตฌํ | ์ปจํ ์คํธ ์ค์์นญ |
|---|---|---|
std::thread | _beginthreadex โ CreateThread | ์์ฑยท์ข ๋ฃ ์ |
std::jthread (C++20) | ๊ฐ์ + stop_token | ๊ฐ์ |
std::mutex | SRWLock (๋๋ Critical Section) | ๊ฒฝํฉ ์๋ง |
std::shared_mutex | SRWLock (R/W) | ๊ฒฝํฉ ์๋ง |
std::condition_variable | Windows Condition Variable | ๋๊ธฐยท๊นจ์ฐ๊ธฐ ์ |
std::atomic<T> | CPU ๋ช ๋ น (LOCK XADD ๋ฑ) | ์์ |
std::async | ThreadPool API ๋๋ ์ ์ค๋ ๋ | ์์ ๋์คํจ์น ์ |
std::this_thread::yield | SwitchToThread | ํ๋ณด ์์ ๋ |
std::this_thread::sleep_for | Sleep ๋๋ high-res ํ์ด๋จธ | ํญ์ |
14. Thread Local Storage์ ์ปจํ ์คํธ ์ค์์นญ
TLS์ ์ญํ
TLS(Thread Local Storage, ์ค๋ ๋ ์ง์ญ ์ ์ฅ์)๋ ๋ณ์๊ฐ ์ค๋ ๋๋ณ๋ก ๋ ๋ฆฝ๋ ์ฌ๋กฏ์ ๊ฐ์ง๊ฒ ํ๋ ๋ฉ์ปค๋์ฆ์ ๋๋ค. ๊ฐ์ ๋ณ์ ์ด๋ฆ์ด์ง๋ง ์ค๋ ๋๋ง๋ค ๋ค๋ฅธ ์ธ์คํด์ค๋ฅผ ๋ด ๋๋ค.
1
2
3
4
5
__declspec(thread) int g_counter = 0; // MSVC TLS
void Worker() {
g_counter++; // ์ด ์ค๋ ๋์ g_counter๋ง ์ฆ๊ฐ โ race condition ์์!
}
ํ์ค C++์์ thread_local ํค์๋(C++11)๊ฐ ๊ฐ์ ์ญํ :
1
thread_local int counter = 0;
TLS๋ ์ด๋์ ์ ์ฅ๋๋
์ค๋ ๋๋ณ TLS ์ฌ๋กฏ์ TCB๊ฐ ๊ฐ๋ฆฌํค๋ ๋ณ๋ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ ์ ์ฅ๋ฉ๋๋ค. ์ปดํ์ผ๋ฌ๊ฐ TLS ๋ณ์ ์ ๊ทผ์ fs:[...](x86) / gs:[...](x64) ์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ ๊ธฐ์ค ์คํ์
์ผ๋ก ๋ณํํด, ํ์ฌ ์คํ ์ค์ธ ์ค๋ ๋์ TLS ์ฌ๋กฏ์ ์๋์ผ๋ก ์ฐพ์๊ฐ๋๋ค.
1
2
3
Windows x64 ๊ธฐ์ค:
gs:[0x30] = TEB (Thread Environment Block) ์ฃผ์
โโ TEB.ThreadLocalStoragePointer โ ๊ทธ ์ค๋ ๋์ TLS ์ฌ๋กฏ ๋ฐฐ์ด
์ปจํ ์คํธ ์ค์์นญ ์ TLS ๋ณด์กด
ํต์ฌ์ TLS๋ ์ค๋ ๋ ์๊ธฐ ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผํ๋ฏ๋ก ์ปจํ
์คํธ ์ค์์นญ ์ ์๋์ผ๋ก ๋ณด์กด๋๋ค๋ ์ ์
๋๋ค. OS๊ฐ TLS๋ฅผ ๋ฐ๋ก ์ ์ฅยท๋ณต์ํ ํ์๊ฐ ์์ต๋๋ค โ ๊ทธ์ TCB(๋ฐ๋ผ์ TEB์ TLS ํฌ์ธํฐ)๊ฐ ์ ์ค๋ ๋ ๊ฒ์ผ๋ก ๋ฐ๋๋ฉด gs:[...] ์ ๊ทผ์ด ์๋์ผ๋ก ์ ์ค๋ ๋์ TLS๋ฅผ ์ฐพ์๊ฐ๋๋ค.
1
2
3
์ค๋ ๋ A ์คํ: gs ๋ ์ง์คํฐ โ A์ TEB โ A์ TLS ์ฌ๋กฏ
โ ์ปจํ
์คํธ ์ค์์น (gs ๋ ์ง์คํฐ๋ B์ ๊ฒ์ผ๋ก ๊ต์ฒด)
์ค๋ ๋ B ์คํ: gs ๋ ์ง์คํฐ โ B์ TEB โ B์ TLS ์ฌ๋กฏ
๋์ TLS โ TlsAlloc / TlsGetValue
์ ์ (์ปดํ์ผ ํ์) TLS ์ธ์ ๋์ ์ผ๋ก ์ฌ๋กฏ์ ํ ๋นํ๋ API๋ ์์ต๋๋ค:
1
2
3
4
5
6
7
8
9
10
11
12
DWORD g_tlsIndex = TlsAlloc(); // ์ฌ๋กฏ ๋ฒํธ ํ ๋น (๋ณดํต 64~1088 ๋ฒ์)
void SetData(int* data) {
TlsSetValue(g_tlsIndex, data); // ์ด ์ค๋ ๋์ ์ฌ๋กฏ์ ์ ์ฅ
}
int* GetData() {
return (int*)TlsGetValue(g_tlsIndex); // ์ด ์ค๋ ๋์ ์ฌ๋กฏ์์ ๊บผ๋
}
// ์ ๋ฆฌ
TlsFree(g_tlsIndex);
DLL์์ ์์ฃผ ์ฐ๋ ํจํด โ DLL์ด ์ด๋ค ์ค๋ ๋์์ ํธ์ถ๋๋์ง ๋ชจ๋ฅผ ๋ ์๊ธฐ๋ง์ ์ค๋ ๋๋ณ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ฒ ๊ด๋ฆฌ.
CRT๊ฐ ์ฐ๋ TLS
CRT ์์ฒด๊ฐ TLS๋ฅผ ๊ด๋ฒ์ํ๊ฒ ์ฌ์ฉํฉ๋๋ค:
errnoโ ์ค๋ ๋๋ณ ์๋ฌ ์ฝ๋strtok๋ด๋ถ ์ํ- stdio ์คํธ๋ฆผ ๋ฝ
rand๋ด๋ถ ์ํ
๊ทธ๋์ raw CreateThread๋ฅผ ์ฐ๋ฉด ์ด TLS๊ฐ ์ด๊ธฐํ๋์ง ์์ ๋ฏธ๋ฌํ ๋ฒ๊ทธ๊ฐ ์๊ธฐ๊ณ , _beginthreadex๊ฐ ๊ถ์ฅ๋๋ ์ด์ ๊ฐ ๋ฉ๋๋ค.
TLS์ ์ปจํ ์คํธ ์ค์์นญ ์ํฅ
- ์ ์ฅยท๋ณต์ ์ง์ ๋น์ฉ ์์ โ ๋ฉ๋ชจ๋ฆฌ์ ์์ฃผ
- ๊ฐ์ ๋น์ฉ์ ์ผ๋ฐ ๋ฉ๋ชจ๋ฆฌ์ ๋์ผ โ ์บ์ ์ฝ๋ ์ํฅ ๋ฐ์
- ๋จ, TLS ์์ญ ์์ฒด๊ฐ ๋ณดํต ์์์(์ KB) ์บ์ ์นํ์
- ์ ์ TLS๋ ์ปดํ์ผ๋ฌ๊ฐ ์ง์ ์คํ์ ๊ณ์ฐ โ ๋น ๋ฆ
- ๋์ TLS๋
TlsGetValueํจ์ ํธ์ถ โ ์ฝ๊ฐ ๋๋ฆผ
MSVC ๋ฌธ์์ ๋ฐ๋ฅด๋ฉด
__declspec(thread)๋ ์ ์ ๋งํฌ ์์ ์ TLS ๋๋ ํฐ๋ฆฌ์ ๋ฑ๋ก๋๋ฉฐ, DLL์ ๋์ ๋ก๋ฉ(LoadLibrary)๊ณผ ํจ๊ป ์ฐ๋ฉด ์ผ๋ถ ์ ์ฝ์ด ์์ต๋๋ค(Vista ์ด์ ์ ๋์ ๋ก๋ฉ DLL์__declspec(thread)๊ฐ ๋์ ์ ํจ).
15. CRT ๋ฉํฐ์ค๋ ๋ ์ต์
โ /MT vs /MD
CRT ๋งํฌ ์ต์ 4๊ฐ์ง
| ์ต์ | ์๋ฏธ | CRT ๋งํฌ | DLL/EXE |
|---|---|---|---|
/MT | Multi-Threaded (์ ์ ) | exe์ ์ ์ ๋งํฌ | ๋จ๋ EXE |
/MTd | ์์ ๋๋ฒ๊ทธ ๋น๋ | ์ ์ ๋๋ฒ๊ทธ | ๋๋ฒ๊ทธ EXE |
/MD | Multi-threaded DLL | DLL๋ก ๋์ ๋งํฌ (UCRT) | ํ์ค |
/MDd | ์์ ๋๋ฒ๊ทธ ๋น๋ | ๋์ ๋๋ฒ๊ทธ | ๋๋ฒ๊ทธ ํ์ค |
์ด์ ์ ์๋ /ML(Single-Threaded)์ Visual Studio 2005๋ถํฐ ์ฌ๋ผ์ก์ต๋๋ค โ ๋ชจ๋ ํ๋ CRT๋ ๋ฉํฐ์ค๋ ๋ ์์ .
/MT (์ ์ CRT) ํน์ฑ
1
2
3
4
5
EXE ์์ CRT ์ฝ๋ ํต์งธ๋ก ํฌํจ
โโ ์ฅ์ : CRT DLL ์์กด์ฑ ์์ (๋จ๋
์คํ, ๋ฐฐํฌ ๊ฐ๋จ)
โโ ๋จ์ : EXE ํฌ๊ธฐ ์ปค์ง (์ MB ์ถ๊ฐ)
โโ ๋จ์ : CRT ๋ณด์ ํจ์น๋ฅผ ๋ฐ์ผ๋ ค๋ฉด ์ฌ์ปดํ์ผ ํ์
โโ ๋จ์ : ๊ฐ์ ํ๋ก์ธ์ค์ ๋ค๋ฅธ ๋ชจ๋๊ณผ CRT ์ธ์คํด์ค ๋ถ๋ฆฌ โ ๋ฉ๋ชจ๋ฆฌ ๋จํธํ
/MD (DLL CRT, UCRT) ํน์ฑ
1
2
3
4
5
CRT๋ฅผ ucrtbase.dll / vcruntime140.dll์์ ๋์ ๋ก๋
โโ ์ฅ์ : EXE ํฌ๊ธฐ ์์
โโ ์ฅ์ : Windows Update๋ก CRT ํจ์น ์๋
โโ ์ฅ์ : ๊ฐ์ CRT ์ธ์คํด์ค ๊ณต์ (๋ฉ๋ชจ๋ฆฌ ํจ์จ)
โโ ๋จ์ : CRT DLL ๋ฐฐํฌ ํ์ (๋๋ ์์คํ
์ ์ฌ์ ์ค์น)
์ปจํ ์คํธ ์ค์์นญ์ ์ํฅ์ ์ฃผ๋ ์ง์
CRT๋ ๋ฉํฐ์ค๋ ๋ ์์ ์ ์ํด ๋ด๋ถ์ ์ผ๋ก ๋ฝ์ ์. ์ด ๋ฝ์ด ์ปจํ ์คํธ ์ค์์นญ์ ์ ๋ฐํ๋ ์ผ์ด์ค:
1. stdio ๋ฝ
1
printf("Hello\n"); // ๋ด๋ถ์ ์ผ๋ก _lock_file โ ์๊ณ ๊ตฌ์ญ โ unlock
stdout์ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ์ฐ๋ฉด ์ถ๋ ฅ์ด ์์ด์ง ์๊ฒ CRT๊ฐ ๋ฝ์ ์ก์ต๋๋ค. ๊ฒฝํฉ์ด ์ฆ์ผ๋ฉด ์ปจํ
์คํธ ์ค์์นญ์ด ์ผ์ด๋ฉ๋๋ค. ๊ฒ์/์๋ฒ์์ ๋งค ํ๋ ์ printf๋ฅผ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ํธ์ถํ๋ฉด ์์ธ์ ๋ณ๋ชฉ์ด ๋ฉ๋๋ค โ ์์ฒด ๋ก๊น
์์คํ
(lock-free ํ + ํ ์์ปค ์ถ๋ ฅ)์ด ๊ถ์ฅ๋๋ ์ด์ .
2. ํ ๋ฝ (malloc/new)
1
int* p = new int(42); // ๋ด๋ถ์ ์ผ๋ก HeapAlloc โ ํ ๋ฝ โ ํ ๋น โ unlock
CRT ํ(๋๋ Windows ์์คํ ํ)์ด ๋ฉํฐ์ค๋ ๋์์ ๊ณต์ ๋๋ ๋ฝ์ด ํ์. Low-Fragmentation Heap (LFH) ์ด ํ์ฑํ๋ผ ์์ผ๋ฉด ์ค๋ ๋๋ณ ์บ์๋ก ๋ฝ ๊ฒฝํฉ์ ์ค์ด์ง๋ง, ํฐ ํ ๋น์ด๋ deallocation์ ์ฌ์ ํ ๊ธ๋ก๋ฒ ๋ฝ์ ์ก์ต๋๋ค.
ํํผ์ฑ :
mimalloc,tcmalloc,jemalloc๊ฐ์ ๋ฉํฐ์ค๋ ๋ ์นํ์ ํ ๋น๊ธฐ๋ก ๊ต์ฒด- ๊ฐ์ฒด ํ / ๋ฉ๋ชจ๋ฆฌ ํ๋ก ์ ์ฒด ํ ๋น ๋น๋ ๋ฎ์ถ๊ธฐ
- ๊ฒ์ ์์ง๋ค์ด ์์ฒด ๋ฉ๋ชจ๋ฆฌ ์์คํ ์ ์ฐ๋ ์ด์
3. errno, strtok, rand (TLS๋ก ํํผ)
์ด ํจ์๋ค์ ๋ด๋ถ ์ํ๋ฅผ ๊ฐ์ ธ ๋ฉํฐ์ค๋ ๋์์ race condition์ด ๋ ์ ์๋๋ฐ, MSVC CRT๋ ์ด ์ํ๋ค์ TLS์ ๋์ด ๋ฝ ์์ด๋ ์์ ํ๊ฒ ๋ง๋ค์์ต๋๋ค. ๋์ _beginthreadex ๊ฒฝ๋ก๋ก ์์ํ ์ค๋ ๋๋ง TLS๊ฐ ์ ๋๋ก ์ด๊ธฐํ๋ฉ๋๋ค(raw CreateThread๋ ์ํ).
4. static ์ง์ญ ๋ณ์ ์ด๊ธฐํ (C++11+ thread-safe init)
1
2
3
4
void Foo() {
static MyClass instance; // C++11๋ถํฐ ์ด๊ธฐํ๋ thread-safe ๋ณด์ฅ
// ...
}
C++11๋ถํฐ ํจ์ ๋ด static ๋ณ์์ ์ฒซ ํธ์ถ ์ด๊ธฐํ๋ ํ์ค์ด thread-safe๋ฅผ ์๊ตฌํฉ๋๋ค. MSVC๋ ์ด๊ฑธ atomic ํ๋๊ทธ + ๋ฝ์ผ๋ก ๊ตฌํ โ ์ฒซ ํธ์ถ ์ ํ ๋ฒ๋ง ๋ฝ์ด ์กํ๊ณ , ์ดํ ํธ์ถ์ fast path๋ก ๋ฝ ์์ด ํต๊ณผํฉ๋๋ค(์ผ์ข
์ double-checked locking).
์ ๋ฆฌ
1
2
3
4
5
6
7
8
9
10
/MT vs /MD ์ ํ์ ์ปจํ
์คํธ ์ค์์นญ์ ์ง์ ์ํฅ์ ์์ง๋ง
CRT ์ธ์คํด์ค ๊ณต์ ์ฌ๋ถ๊ฐ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฝ ๊ฒฝํฉ์ ์ํฅ:
๊ฐ์ ํ๋ก์ธ์ค์ ๋ชจ๋ ๋ชจ๋์ด /MD (๊ฐ์ CRT ๊ณต์ )
โ ๊ฐ์ ํ ์ฌ์ฉ โ ํ ๊ณณ์์ ํ ๋นํ๊ณ ๋ค๋ฅธ ๊ณณ์์ ํด์ ์์
โ ๋ฝ ๊ฒฝํฉ์ ํ ๊ตฐ๋ฐ๋ก ์ง์ค (LFH๋ก ์ผ๋ถ ์ํ)
์ผ๋ถ๋ /MT, ์ผ๋ถ๋ /MD
โ CRT ์ธ์คํด์ค๊ฐ ๋ถ๋ฆฌ๋จ โ ๋ค๋ฅธ ๋ชจ๋์์ ํ ๋นํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์๊ธฐ CRT๋ก ํด์ ์ ํฌ๋์
โ ๊ฐ์ ์๊ธฐ ํ์ด๋ผ ๋ฝ ๊ฒฝํฉ์ ๋ถ์ฐ๋์ง๋ง ์ํ
MSVC ๋ฌธ์๊ฐ ์ผ๊ด๋๊ฒ
/MD์ฌ์ฉ์ ๊ถ์ฅํ๋ ์ด์ ์ค ํ๋๊ฐ ์ด ๋ฉ๋ชจ๋ฆฌ/๋ฝ ์ผ๊ด์ฑ์ ๋๋ค. ๋จ๋ ๋ฐฐํฌ๊ฐ ์ ๋ง ํ์ํ ๋๋ง/MT๋ฅผ ์ฐ๋ ๊ฒ ์ปจ๋ฒค์ ์ ๋๋ค.
16. ์ธ๋ฆฌ์ผ์์์ ์ปจํ ์คํธ ์ค์์นญ โ GameThread/RenderThread/RHIThread
์ธ๋ฆฌ์ผ ์์ง์ ์ปจํ ์คํธ ์ค์์นญ์ ์ค์ด๊ธฐ ์ํด ์ค๋ ๋ ์ญํ ์ ๋ถ๋ช ํ ๋๋๊ณ , ๊ทธ ์ฌ์ด๋ฅผ ๋ช ๋ น ํ๋ก ์ฐ๊ฒฐํ๋ ์ํคํ ์ฒ๋ฅผ ์ฑํํฉ๋๋ค.
3๋ ๋ฉ์ธ ์ค๋ ๋
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
โโ Game Thread (๋ฉ์ธ)
โ โโ AActor::Tick, Component::TickComponent
โ โโ UObject ์กฐ์ (์์ฑ/์๋ฉธ/์์ฑ)
โ โโ Blueprint VM ์คํ
โ โโ UI (UMG) ์ฒ๋ฆฌ
โ โโ ์
๋ ฅ ์ฒ๋ฆฌ
โ
โโ Render Thread (๋ณ๋ ฌ)
โ โโ Game Thread์์ ๋ฐ์ ๋ช
๋ น์ผ๋ก RHI ๋ช
๋ น ๋น๋
โ โโ Material ์ปดํ์ผยทLOD ๊ฒฐ์ ยทculling
โ โโ Mesh draw call ์์ฑ
โ
โโ RHI Thread (๋ณ๋ ฌ)
โโ Render Thread์์ ๋ฐ์ RHI ๋ช
๋ น์ GPU ๋๋ผ์ด๋ฒ์ ์ ์ถ
โโ D3D12 / Vulkan / Metal API ํธ์ถ
โโ ๋ฐฑ๋ฒํผ swap, GPU sync
์ธ ์ค๋ ๋๊ฐ 1ํ๋ ์์ฉ ์ฐจ์ด๋ฅผ ๋๊ณ ํ์ดํ๋ผ์ด๋ ๋์ํฉ๋๋ค โ Frame N์ Game์ด ๋๋๋ฉด Frame N์ Render๊ฐ ์์๋๋ ๋์ Game์ Frame N+1์ ์์. ์ด๊ฒ GPU์ CPU๋ฅผ ๋์์ ํ์ฉํ๋ ํต์ฌ ํจํด์ ๋๋ค.
์ ์ค๋ ๋๋ฅผ ๋ถ๋ฆฌํ๋ โ ์ปจํ ์คํธ ์ค์์นญ ๊ด์
๊ฐ์ ์ค๋ ๋ ์์ ๋ชจ๋ ์ผ์ ๋ค ๋ฃ์ผ๋ฉด: ํ ํ๋ ์ ์์ ๊ฒ์ ๋ก์ง โ ๋ ๋ ๋ช ๋ น ๋น๋ โ GPU ํธ์ถ โ swap์ ์์ฐจ ์คํํด์ผ ํ๋ฏ๋ก GPU ๋๊ธฐ ์๊ฐ๋งํผ CPU๊ฐ ๋๊ฒ ๋ฉ๋๋ค. 60fps(16.6ms) ์์ ๋ค ๋๋ด๊ธฐ ์ด๋ ต์ต๋๋ค.
๋ถ๋ฆฌํ๋ฉด: ๊ฐ ์ค๋ ๋๊ฐ ์๊ธฐ ์ ์ฉ ์์ ์ ์ง์ค โ ์ปจํ ์คํธ ์ค์์นญ์ด ๋ฐ์ํด๋ ํ ์์ ์์์๋ง ๋ฐ์ โ ์บ์ ์ฝ๋ ์ํฅ ์ต์ํ. ๊ทธ๋ฆฌ๊ณ ๋ช ๋ น ํ๋ก ํต์ ํ๋ฏ๋ก ๋๊ธฐํ ๋น๋๊ฐ ๋ฎ์ โ ๋ฝ ๊ฒฝํฉ ์ปจํ ์คํธ ์ค์์นญ๋ ์ ์.
TaskGraph โ ์์กด์ฑ ๊ธฐ๋ฐ ์์ ๋ถํ
1
2
3
4
5
6
7
8
9
10
11
12
13
// ์์
์ ์
class FMyTask {
public:
static FORCEINLINE TStatId GetStatId() { ... }
ENamedThreads::Type GetDesiredThread() { return ENamedThreads::AnyBackgroundThreadNormalTask; }
static ESubsequentsMode::Type GetSubsequentsMode() { return ESubsequentsMode::TrackSubsequents; }
void DoTask(ENamedThreads::Type CurrentThread, const FGraphEventRef& MyCompletionGraphEvent) {
// ์์
}
};
// ๋์คํจ์น
TGraphTask<FMyTask>::CreateTask().ConstructAndDispatchWhenReady();
TaskGraph๋ ์์ ๋ค์ ์์กด ๊ด๊ณ๋ฅผ ๊ทธ๋ํ๋ก ๊ด๋ฆฌํ๊ณ , ์์ปค ํ์์ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํฉ๋๋ค. work stealing์ ์ฌ์ฉํด ์ปจํ ์คํธ ์ค์์นญ ์์ด ๋ถํ๋ฅผ ๋ถ์ฐํฉ๋๋ค โ ConcRT์ ๊ฐ์ ์๋ฆฌ.
ENamedThreads โ ์ด๋์ ์คํํ ์ง ๋ช
์
1
2
3
4
5
6
7
8
9
10
11
12
13
14
AsyncTask(ENamedThreads::GameThread, [this]() {
// ๊ฒ์ ์ค๋ ๋์์ ์คํ โ UObject ์์
MyActor->SetActorLocation(NewLocation);
});
AsyncTask(ENamedThreads::AnyBackgroundThreadNormalTask, []() {
// ์์ปค ์ค๋ ๋์์ ์คํ โ ๋ฌด๊ฑฐ์ด ์์
HeavyComputation();
// ๊ฒฐ๊ณผ๋ ๊ฒ์ ์ค๋ ๋๋ก
AsyncTask(ENamedThreads::GameThread, []() {
UpdateUI();
});
});
์ด ํจํด์ด ์ค๋ฌด์์ ๊ฐ์ฅ ํํฉ๋๋ค โ ๋ฐฑ๊ทธ๋ผ์ด๋์์ ๋ฌด๊ฑฐ์ด ์ผ, ๋๋๋ฉด ๊ฒ์ ์ค๋ ๋๋ก ๊ฒฐ๊ณผ ์ ๋ฌ. ์ปจํ ์คํธ ์ค์์นญ์ ๋ ๋ฒ ์ผ์ด๋์ง๋ง, ๋ฌด๊ฑฐ์ด ์ผ์ด ๊ฒ์ ์ค๋ ๋๋ฅผ ๋ง์ง ์์ผ๋ฏ๋ก ํ๋ ์์จ์ด ์ ์ง๋ฉ๋๋ค.
FRunnableThread โ OS ์ค๋ ๋ ์ง์ ์์ฑ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class FMyWorker : public FRunnable {
public:
virtual bool Init() override { return true; }
virtual uint32 Run() override {
while (!bStop) {
// ์์
}
return 0;
}
virtual void Stop() override { bStop = true; }
virtual void Exit() override { }
private:
FThreadSafeBool bStop;
};
FMyWorker* worker = new FMyWorker();
FRunnableThread* thread = FRunnableThread::Create(
worker,
TEXT("MyWorker"),
0, // ๊ธฐ๋ณธ ์คํ ํฌ๊ธฐ (20๋ฒ์์ ๋ค๋ฃธ)
TPri_Normal // ์ฐ์ ์์
);
๋ด๋ถ์ ์ผ๋ก Windows์์ _beginthreadex โ CreateThread๋ฅผ ํธ์ถ. std::thread์ ๊ฑฐ์ ๊ฐ์ง๋ง ๋ฉํฐ ํ๋ซํผ + ๋ผ์ดํ์ฌ์ดํด ํ
(Init/Run/Stop/Exit)์ด ํ์คํ๋ผ ์์ต๋๋ค.
IsInGameThread() โ ์์ ๊ฒ์ฆ
1
2
3
4
5
void UMyComponent::DoSomething() {
check(IsInGameThread()); // ๊ฒ์ ์ค๋ ๋์์๋ง ํธ์ถ๋์ด์ผ ํจ
MyActor->SetActorLocation(NewLocation); // UObject ์กฐ์์ ๊ฒ์ ์ค๋ ๋ ์ ์ฉ
}
UObject ์กฐ์์ ๊ฒ์ ์ค๋ ๋ ์ ์ฉ ์ปจ๋ฒค์
. ๋ค๋ฅธ ์ค๋ ๋์์ ๋ง์ง๋ฉด GC์ ์ถฉ๋ํ๊ฑฐ๋ race condition์ด ๋ฉ๋๋ค. check(IsInGameThread())๋ ๋๋ฒ๊ทธ ๋น๋์์ ์๋ชป๋ ์ปจํ
์คํธ์์์ ํธ์ถ์ ์ฆ์ ์ก์์ค๋๋ค.
์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ ์ค์ด๋ ์ธ๋ฆฌ์ผ์ ํจํด
| ํจํด | ํจ๊ณผ |
|---|---|
| ๊ฒ์/๋ ๋/RHI ์ค๋ ๋ ๋ถ๋ฆฌ + ๋ช ๋ น ํ | ๋๊ธฐํ ๋น๋ ์ต์ํ โ ๋ฝ ๊ฒฝํฉ ์ปจํ ์คํธ ์ค์์นญ ์ ์ |
| TaskGraph + work stealing | ์์ปค ํ์์ ์์ฒด ๋ถ์ฐ โ OS ์ปจํ ์คํธ ์ค์์นญ ํํผ |
ENamedThreads ๋ช
์ | ์๋ชป๋ ์ค๋ ๋๋ก ๋์คํจ์น ๋ฐฉ์ง โ ์ถ๊ฐ ์ค์์นญ ํํผ |
FCriticalSection (์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ ) | Windows Critical Section ์ง์ ๋ํ โ ๋ฌด๊ฒฝํฉ ์ ๋น ๋ฆ |
TQueue<T, EQueueMode::Mpsc> (lock-free) | ์ปจํ ์คํธ ์ค์์นญ ์๋ ์ค๋ ๋ ๊ฐ ํต์ |
TLS ํ์ฉ (FThreadSingleton) | ์ค๋ ๋๋ณ ๋ฐ์ดํฐ โ ๋ฝ ์์ด ์์ |
๊ฒ์ ์์ง์ด ์ปจํ ์คํธ ์ค์์นญ์ ๋ฏผ๊ฐํ ์ด์
1
2
3
4
5
6
1ํ๋ ์ 16.6ms (60fps)
โ 100ฮผs(์ปจํ
์คํธ ์ค์์น 1ํ) ร 100ํ = 10ms โ 60% ์์ง!
โ ๊ทธ๋์ ์ปจํ
์คํธ ์ค์์นญ์ ์ค์ด๋ ๋ชจ๋ ํธ๋ฆญ์ ๋์
๋์กฐ: ์ผ๋ฐ ์๋ฒ ์ํฌ๋ก๋ (์์ฒญ๋น 100ms ์ฒ๋ฆฌ)
โ ์ปจํ
์คํธ ์ค์์นญ 1ms๋ 1% ์ ๋๋ผ ๋ฌด์ ๊ฐ๋ฅ
์ด๊ฒ ๊ฒ์ ์์ง์ด ์์ฒด ์์ ์์คํ (TaskGraph), ์์ฒด ๋ฉ๋ชจ๋ฆฌ ํ ๋น๊ธฐ, ์์ฒด ๋๊ธฐํ ํ๋ฆฌ๋ฏธํฐ๋ธ๋ฅผ ์ ๊ทน ๋์ ํ๋ ์ง์ ์ ์ด์ ์ ๋๋ค.
17. ๊ผฌ๋ฆฌ์ง๋ฌธ ์์ ๊ฒฝ๋ก
Q1. โ์ปจํ ์คํธ ์ค์์นญ์ด ์ ํํ ๋ฌด์์ด๊ณ ์ ํ์ํ๊ฐ์?โ
์ปจํ ์คํธ ์ค์์นญ์ CPU ์ฝ์ด ์์์ ์คํ๋๋ ์ค๋ ๋(๋๋ ํ๋ก์ธ์ค)๋ฅผ ์ ์ ๋ด๋ ค๋๊ณ , ๋ค๋ฅธ ์คํ ๋จ์๋ก ๊ฐ์๋ผ์ฐ๋ OS ์์ ์ ๋๋ค. CPU ์ฝ์ด๋ ํ ์๊ฐ์ ํ๋์ ๋ช ๋ น ํ๋ฆ๋ง ์คํํ์ง๋ง OS๋ ์๋ฐฑ~์์ฒ ๊ฐ ์ค๋ ๋๋ฅผ ๋์์ ์ด์์๋ ๊ฒ์ฒ๋ผ ๋ณด์ฌ์ค์ผ ํ๋, ๋น ๋ฅด๊ฒ ๋์๊ฐ๋ฉฐ ์๊ฐ์ ์ชผ๊ฐ ์ฐ๋ ์๋ถํ (time-sharing) ๋ชจ๋ธ์ด ํ์ํฉ๋๋ค. ๊ทธ ์๋ถํ ์ ๋ณธ์ฒด๊ฐ ์ปจํ ์คํธ ์ค์์นญ์ ๋๋ค.
๋ฉ์ปค๋์ฆ์ โ ํ์ฌ ์ค๋ ๋์ CPU ์ํ(๋ ์ง์คํฐยทSPยทPCยทํ๋๊ทธ)๋ฅผ ๊ทธ ์ค๋ ๋์ TCB(Thread Control Block, ์ค๋ ๋ ์ ์ด ๋ธ๋ก)์ ์ ์ฅ โ โก ์ค์ผ์ค๋ฌ๊ฐ ๋ค์ ์ค๋ ๋ ์ ํ โ โข ์ ์ค๋ ๋์ TCB์์ ์ํ ๋ณต์ โ โฃ ๊ทธ ์ค๋ ๋๊ฐ ๋ฉ์ท๋ ์๋ฆฌ๋ถํฐ ์ฌ๊ฐ. ํ๋ก์ธ์ค๊ฐ ๋ฐ๋๋ฉด ํ์ด์ง ํ ์ด๋ธ ๋ฒ ์ด์ค(x86 CR3)๋ ํจ๊ป ๊ต์ฒดํฉ๋๋ค.
Q2. โ์ปจํ ์คํธ ์ค์์นญ์ ์ธ์ ์ผ์ด๋๋์? ์ข ๋ฅ๋ฅผ ๋ถ๋ฅํด์ฃผ์ธ์.โ
ํฌ๊ฒ ๋ค ๊ฐ์ง ํธ๋ฆฌ๊ฑฐ๊ฐ ์์ต๋๋ค.
- ํ์ด๋จธ ์ธํฐ๋ฝํธ(timer interrupt) โ OS๊ฐ ์ค๋ ๋์ ํ ๋นํ time slice(quantum, Windows ๊ธฐ๋ณธ ์ฝ 15.6ms)๊ฐ ๋ง๋ฃ๋๋ฉด ํ๋์จ์ด ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก ๊ฐ์ ์ค์์นญ์ด ์ผ์ด๋ฉ๋๋ค. ์ด๊ฒ ์ ์ ํ(preemptive) ์ค์ผ์ค๋ง์ ๋ณธ์ฒด์ ๋๋ค.
- ๋ธ๋กํน ์์คํ ์ฝ โ
read()ยทrecv()ยทWaitForSingleObject()์ฒ๋ผ ๋๊ธฐ๋ฅผ ๋๋ฐํ๋ ํธ์ถ์ ๋ง๋๋ฉด ๊ทธ ์ค๋ ๋๋ ์ฆ์ Wait ์ํ๋ก ์ ํ๋๊ณ ๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋์คํจ์น๋ฉ๋๋ค.- ๋๊ธฐํ ๊ฐ์ฒด ๋๊ธฐ โ mutexยทsemaphoreยทeventยทcondition variable์์ ์ ๋ค๋ฉด ๊ฐ์ ๊ฒฐ๊ณผ๊ฐ ์ผ์ด๋ฉ๋๋ค. Windows์ Critical Section์ด๋ SRWLock์ ์ฌ์ฉ์ ๋ชจ๋์์ ์ ๊น spinํ๋ค๊ฐ ๊ทธ๋๋ ๋ชป ์ก์ผ๋ฉด ๊ทธ๋ ์ปค๋ ์ง์ โ ์ปจํ ์คํธ ์ค์์นํฉ๋๋ค.
- ์๋ฐ์ ์๋ณด โ
Sleep(0),SwitchToThread,std::this_thread::yield๋ก ์ค๋ ๋๊ฐ ์ง์ CPU๋ฅผ ๋ด๋ ค๋๋ ๊ฒฝ์ฐ์ ๋๋ค.์ฒซ ๋ฒ์งธ๋ ๊ฐ์ , ๋๋จธ์ง ์ ์ ์ค๋ ๋ ์๋ฐ์ ํธ๋ฆฌ๊ฑฐ์ ๋๋ค.
Q3. โ๋ชจ๋ ์ค์์น์ ์ปจํ ์คํธ ์ค์์น๋ ๊ฐ์ ๊ฑด๊ฐ์?โ
๋ค๋ฆ ๋๋ค. ๋ชจ๋ ์ค์์น(mode switch)๋ ๊ฐ์ ์ค๋ ๋ ์์์ ์ฌ์ฉ์ ๋ชจ๋์ ์ปค๋ ๋ชจ๋๋ฅผ ์ค๊ฐ๋ ๊ฒ์ด๊ณ , ์ปจํ ์คํธ ์ค์์น(context switch)๋ ์คํ ์ฃผ์ฒด(์ค๋ ๋ ๋๋ ํ๋ก์ธ์ค)๊ฐ ๋ฐ๋๋ ๊ฒ์ ๋๋ค.
์์คํ ์ฝ์ด ์ฆ์ ๋๋๋ฉด(
GetCurrentProcessId๊ฐ์ ์ ๋ณด ์กฐํ) ๋ชจ๋ ์ค์์น๋ง ์ผ์ด๋๊ณ ์ปจํ ์คํธ ์ค์์น๋ ์์ต๋๋ค โ ๊ฐ์ ์ค๋ ๋๊ฐ ์ฌ์ฉ์ ๋ชจ๋๋ก ๋์์ต๋๋ค. ๋ฐ๋๋ก ์ปจํ ์คํธ ์ค์์น๋ ๋ณดํต ๋ชจ๋ ์ค์์น ์์์ ์ผ์ด๋ฉ๋๋ค โ ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก ์ปค๋ ๋ชจ๋ ์ง์ โ ์ค์ผ์ค๋ฌ โ ๋ค๋ฅธ ์ค๋ ๋๋ก ๊ฐ์๋ผ์ โ ๋ค์ ์ฌ์ฉ์ ๋ชจ๋.์์ธ๊ฐ Fiber์ธ๋ฐ,
SwitchToFiber๋ ์ฌ์ฉ์ ๋ชจ๋์์ SPยทPC๋ฅผ ์ง์ ๋ฐ๊ฟ์น๊ธฐํ๋ฏ๋ก ๋ชจ๋ ์ค์์น๋ ์ปจํ ์คํธ ์ค์์น๋ ์ผ์ด๋์ง ์์ต๋๋ค โ ๊ทธ๋์ ์์ญ nanosecond์ ๋๋ฉ๋๋ค.
Q4. โ์ปจํ ์คํธ ์ค์์นญ์ ๋น์ฉ ์์๋ฅผ ์์ธํ ์ค๋ช ํด์ฃผ์ธ์.โ
๋น์ฉ์ ์ฌ๋ฌ ์ธต์์ ๋์ ๋ฉ๋๋ค. ๋ถ๋ฆฌํด์ ๋ณด๋ฉด:
- ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ โ ์ง์ ๋น์ฉ. x86_64๋ฉด GPR 16๊ฐ + ํ๋๊ทธ + (์ ํ์ ) FPU/SIMD๋ฅผ ๋ฉ๋ชจ๋ฆฌ(TCB)๋ก ์ฎ๊ธฐ๊ณ ๋ค์ ๊ฐ์ ธ์ต๋๋ค. ๋ณดํต ์๋ฐฑ nanosecond.
- ์บ์ ์ฝ๋(cache cold) โ ๊ฐ์ฅ ํฐ ๊ฐ์ ๋น์ฉ. ์ ์ค๋ ๋์ ๋ฐ์ดํฐยท๋ช ๋ น์ด๊ฐ L1ยทL2 ์บ์์ ์์ด ์ง์ ์งํ ์ค์ค์ด ์บ์ ๋ฏธ์ค๊ฐ ๋ฐ์ํฉ๋๋ค. ์ง์ ๋น์ฉ๋ณด๋ค ์~์์ญ ๋ฐฐ ํด ์ ์์ต๋๋ค.
- TLB(Translation Lookaside Buffer, ์ฃผ์ ๋ณํ ์บ์) flush โ ํ๋ก์ธ์ค ์ ํ์์๋ง ์ผ์ด๋ฉ๋๋ค. ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ์ด ๋ฐ๋๋ฏ๋ก MMU(Memory Management Unit)๊ฐ ์บ์ฑํ๋ ๊ฐ์โ๋ฌผ๋ฆฌ ๋งคํ์ ๋น์๋๋ค. ์ดํ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ๋ง๋ค ํ์ด์ง ํ ์ด๋ธ ์ํฌ๊ฐ ๋ค์ ์ผ์ด๋ฉ๋๋ค.
- ํ์ดํ๋ผ์ธ ์ ์ง์ ๋ถ๊ธฐ ์์ธก๊ธฐ ๋ฌดํจํ โ instruction pipeline์ ๋ช ๋ น๋ค์ด ํ๊ธฐ๋๊ณ , ๋ถ๊ธฐ ์์ธก๊ธฐ ํ์ต์ด ์ด๊ธ๋ฉ๋๋ค.
- ์ปค๋ ์ง์ (๋ชจ๋ ์ค์์น) ์์ฒด ๋น์ฉ โ ๋ณดํต 100~500 nanosecond. Spectre/Meltdown ์ํ ํจ์น(KPTI) ์ดํ์ ๋ ๋น์ธ์ก์ต๋๋ค.
์ดํฉ์ผ๋ก ์ค๋ ๋ ์ ํ์ ์ฝ 1~5ฮผs, ํ๋ก์ธ์ค ์ ํ์ 5~20ฮผs ์์ค์ ๋๋ค.
Q5. โํ๋ก์ธ์ค ์ ํ๊ณผ ์ค๋ ๋ ์ ํ์ ๋น์ฉ ์ฐจ์ด๋ ์ 5~10๋ฐฐ๊ฐ ๋๋์?โ
ํต์ฌ์ TLB flush์ ์บ์ ์ฝ๋์ ๋๋ค. ์ค๋ ๋ ์ ํ์ ๊ฐ์ PCB(๊ฐ์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ) ์์์ TCB๋ง ๋ฐ๊พธ๋ฏ๋ก ํ์ด์ง ํ ์ด๋ธ ๋ฒ ์ด์ค ๋ ์ง์คํฐ(x86 CR3)๋ฅผ ๊ทธ๋๋ก ๋๊ณ TLBยทํธ๋ค ํ ์ด๋ธยท๋ฉ๋ชจ๋ฆฌ๋งต์ด ๋ณด์กด๋ฉ๋๋ค. ๊ทธ๋์ ์งํ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด ์ผ๋ฐ ์๋๋ก ์์๋ฉ๋๋ค.
ํ๋ก์ธ์ค ์ ํ์ CR3๋ฅผ ๊ต์ฒดํ๊ณ TLB๋ฅผ ๋น์์ผ ํ๋, ์งํ ๋ชจ๋ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ์ด TLB miss๋ก ์์ํด ํ์ด์ง ํ ์ด๋ธ ์ํฌ(4๋จ๊ณ ํ์ด์ง ํ ์ด๋ธ์ด๋ฉด 4๋ฒ ๋ฉ๋ชจ๋ฆฌ ์ ๊ทผ)๋ฅผ ๊ฑฐ์ณ์ผ ํฉ๋๋ค. ์บ์๋ working set ์์ฒด๊ฐ ๋ค๋ฅธ ํ๋ก์ธ์ค ๊ฒ์ด๋ผ ์ง์ ์งํ ๊ฑฐ์ ๋ชจ๋ ๋ฏธ์ค๊ฐ ๋ฐ์ํฉ๋๋ค.
๋ค๋ง ํ๋ x86์ PCID(Process Context ID), ARM์ ASID(Address Space ID)๋ก TLB ์ํธ๋ฆฌ์ ํ๋ก์ธ์ค ID๋ฅผ ํ๊น ํด์ ์ ์ฒด flush๋ฅผ ํํผํฉ๋๋ค. ๊ทธ๋๋ ์บ์ ์ฝ๋๋ ํํผ ๋ชป ํด์ ์ฐจ์ด๋ ์ฌ์ ํ ํฝ๋๋ค.
Q6. โ์ค์ผ์ค๋ง ์๊ณ ๋ฆฌ์ฆ์ด ์ปจํ ์คํธ ์ค์์นญ์ ์ด๋ป๊ฒ ์ํฅ์ ์ฃผ๋์?โ
์๊ณ ๋ฆฌ์ฆ์ด ์ปจํ ์คํธ ์ค์์นญ์ ๋น๋์ ์ ์ฑ ์ ๊ฒฐ์ ํฉ๋๋ค.
์ ์ ํ(preemptive) ์ค์ผ์ค๋ง์ ํ์ด๋จธ ์ธํฐ๋ฝํธ๋ก ๊ฐ์ ์ค์์นญ์ ์ผ์ผํค๋ ๋ชจ๋ธ๋ก WindowsยทLinux์ ํ์ค์ ๋๋ค. quantum์ด ์งง์ผ๋ฉด(์: 1ms) ์๋ต์ฑ์ ์ข์ง๋ง ์ปจํ ์คํธ ์ค์์นญ ๋น๋๊ฐ ๋์ด ์ค๋ฒํค๋๊ฐ ๋์ ๋๊ณ , ๊ธธ๋ฉด(100ms+) throughput์ ์ข์ง๋ง ์๋ต์ฑ์ด ๋๋น ์ง๋๋ค โ ํธ๋ ์ด๋์คํ์ ๋๋ค. Windows ๊ธฐ๋ณธ quantum์ ์ฝ 15.6ms์ ๋๋ค.
๋น์ ์ ํ/ํ๋ ฅ์ (cooperative) ์ค์ผ์ค๋ง์ ์ค๋ ๋๊ฐ ์๋ฐ์ ์ผ๋ก ์๋ณดํ ๋๋ง ์ค์์นญํ๋ ๋ชจ๋ธ๋ก, Fiber์ ์ฝ๋ฃจํด์ด ์ด ํจ๋ฌ๋ค์์ ๋๋ค. ์ปจํ ์คํธ ์ค์์นญ์ด ์ ์ง๋ง ํ ์ค๋ ๋๊ฐ ์๋ณด๋ฅผ ์ ํ๋ฉด ์์คํ ์ด ๋ฉ์ถฅ๋๋ค.
์๊ณ ๋ฆฌ์ฆ๋ณ๋ก๋ Round-Robin(๊ท ๋ฑ quantum), ์ฐ์ ์์ ์ค์ผ์ค๋ง(๋์ ์ฐ์ ์์ ๋จผ์ , ๊ธฐ์ ์ํ), MLFQ(Multi-Level Feedback Queue) (ํ๋ ํจํด์ผ๋ก ์๋ ๋ถ๋ฅ) ๋ฑ์ด ์๊ณ , WindowsยทLinux๋ MLFQ์ ๊ฐ๊น์ด dynamic priority ๋ชจ๋ธ์ ์ฌ์ฉํฉ๋๋ค.
Q7. โWindows์์ ๋๊ธฐํ ๊ฐ์ฒด๋ณ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ ์ด๋ป๊ฒ ๋ค๋ฅธ๊ฐ์?โ
์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ ์ด๋, ํญ์ ์ปค๋ ์ง์ ์ด๋๊ฐ ๊ฐ์ฅ ํฐ ์ฐจ์ด์ ๋๋ค.
std::atomicโ CPU ๋ช ๋ น(LOCK XADD ๋ฑ)์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋์ง ์์ต๋๋ค. ์ nanosecond.- Critical Section / SRWLock โ ์ฌ์ฉ์ ๋ชจ๋์์ ์งง๊ฒ spin โ ๊ทธ๋๋ ๋ชป ์ก์ผ๋ฉด ๊ทธ๋ ์ปค๋ ์ง์ . ๋ฌด๊ฒฝํฉ ์ผ์ด์ค์์ 50~100 nanosecond. ๋จ, ๊ฐ์ ํ๋ก์ธ์ค ๋ด์์๋ง ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค. SRWLock์ R/W ๋ถ๋ฆฌ.
- Condition Variable โ
SleepConditionVariableSRW๋ก ๊ตฌํ๋์ด ์ฌ์ฉ์ ๋ชจ๋ ์ฐ์ .- Mutex / Event / Semaphore โ ์ปค๋ ๊ฐ์ฒด๋ผ ํญ์ ์ปค๋ ์ง์ . ๋ฌด๊ฒฝํฉ์ด๋ผ๋ 1~3 microsecond. ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ๊ฐ๋ฅํ๋ค๋ ๊ฒ ์ฅ์ .
MSVC์
std::mutex๋ SRWLock ์์ ๊ตฌํ๋ผ ์์ด ๋ฌด๊ฒฝํฉ ์ ๊ฑฐ์ ๋น์ฉ์ด ์๊ณ , Mutex์ 20~50๋ฐฐ ๋น ๋ฆ ๋๋ค. ๊ทธ๋์ ๊ฐ์ ํ๋ก์ธ์ค ์์ ๋๊ธฐํ๋ Critical Section/SRWLock, ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ๊ฐ ํ์ํ ๋๋ง Mutex๊ฐ ์ปจ๋ฒค์ ์ ๋๋ค.
Q8. โConcurrency Runtime / PPL์ด ์ปจํ ์คํธ ์ค์์นญ์ ์ด๋ป๊ฒ ์ค์ด๋์?โ
ConcRT๋ OS ์์ ์ฌ์ฉ์ ๋ชจ๋ Task Scheduler๋ฅผ ๋์ด OS ์ปจํ ์คํธ ์ค์์นญ์ ์ค์ด๋ MSVC์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค(
/cpp/parallel/concrt/). ํต์ฌ ๋ฉ์ปค๋์ฆ์ด ์ธ ๊ฐ์ง์ ๋๋ค.์ฒซ์งธ work stealing โ ๊ฐ ์์ปค๊ฐ ์๊ธฐ ์์ ํ๋ฅผ ๊ฐ์ง๊ณ , ํ๊ฐํ ์์ปค๊ฐ ๋ค๋ฅธ ์์ปค์ ํ ๋์์ ์์ ์ ํ์ณ ์ฒ๋ฆฌํฉ๋๋ค. ๋ฝ ๊ฒฝํฉ ์์ด ๋ถํ ๋ถ์ฐ์ด ์ผ์ด๋ OS ์ปจํ ์คํธ ์ค์์นญ์ด ๊ฑฐ์ ์ผ์ด๋์ง ์์ต๋๋ค.
๋์งธ
Context::Block/Yield/Unblockโ ์ฌ์ฉ์ ๋ชจ๋์์ ์์ ์ปจํ ์คํธ๋ฅผ ์๋ณดยท๋ธ๋กยท์ฌ๊ฐํ๋ API. OS๊ฐ ๋ชจ๋ฅด๋ ํ๋ ฅ์ ์ค์ผ์ค๋ง์ด๋ผ ์์ญ~์๋ฐฑ nanosecond์ ๋๋ฉ๋๋ค.์ ์งธ oversubscription โ ๋ธ๋กํน ํธ์ถ ์ง์ ์
Oversubscribe(true)๋ก ์์ ์ถ๊ฐ ์์ปค๋ฅผ ๋์ ์ฒ๋ฆฌ๋์ ์ ์งํฉ๋๋ค.PPL์
parallel_forยทparallel_invokeยทtask<T>๊ฐ ๊ทธ ์์ ์นํ ๊ณ ์์ค API๋ก, 1000๊ฐ ๋ฐ๋ณต์ OS ์ค๋ ๋ 1000๊ฐ๋ก ์ฒ๋ฆฌํ๋ ๋์ ์ฝ์ด ์๋งํผ์ ํ์์ work stealing์ผ๋ก ์ฒ๋ฆฌํ๋ฏ๋ก ์ปจํ ์คํธ ์ค์์นญ์ด ๊ทน์ ์ผ๋ก ์ค์ด๋ญ๋๋ค.
Q9. โFiber์ OS ์ค๋ ๋์ ์ปจํ ์คํธ ์ค์์นญ ์ฐจ์ด๋ ๋ฌด์์ธ๊ฐ์?โ
Fiber๋ ์ฌ์ฉ์ ๋ชจ๋์์๋ง ๊ด๋ฆฌ๋๋ ํ๋ ฅ์ ์คํ ๋จ์์ ๋๋ค. OS ์ปค๋์ Fiber๋ฅผ ๋ชจ๋ฅด๊ณ , ํ OS ์ค๋ ๋ ์์์ ์ฌ๋ฌ Fiber๊ฐ ์๊ธฐ๋ค๋ผ๋ฆฌ SPยทPC๋ฅผ ๋ฐ๊ฟ์น๊ธฐํฉ๋๋ค.
SwitchToFiberํธ์ถ์ ์์ญ nanosecond๋ก OS ์ค๋ ๋ ์ปจํ ์คํธ ์ค์์น(1~5ฮผs)์ 50๋ฐฐ ์ด์ ๋น ๋ฆ ๋๋ค.๋จ์ ์ด ๋ ๊ฐ์ง์ ๋๋ค. ๋ฉํฐ ์ฝ์ด ํ์ฉ ๋ถ๊ฐ โ ํ OS ์ค๋ ๋ ์์ Fiber๋ค์ด๋ผ ์ฝ์ด ํ๋์์๋ง ๋๋๋ค. ์์คํ ์ฝ ๋ธ๋กํน ์ ํธ์คํธ ์ค๋ ๋ ์ ์ฒด ๋ฉ์ถค โ OS๊ฐ Fiber๋ฅผ ๋ชจ๋ฅด๋ ๊ทธ ์์ ๋ค๋ฅธ Fiber๋ค๋ ๊ฐ์ด ๋ฉ์ถฅ๋๋ค. ๊ทธ๋์ ์์ CPU-bound ์์ ์ ์ ํฉํ๊ณ , I/O์ ์์ด๋ฉด ์ํํฉ๋๋ค.
Naughty Dog์ ๊ฒ์ ์์ง ์์ ์์คํ ์ด OS ์ค๋ ๋ ํ + Fiber ์กฐํฉ์ผ๋ก ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ ๊ทน๋จ์ ์ผ๋ก ์ค์ธ ์ ๋ช ์ฌ๋ก์ ๋๋ค. ํ๋ C++์์ ์ฝ๋ฃจํด(C++20)์ด ๋ ์์ฐ์ค๋ฌ์ด ๋์์ด ๋์ต๋๋ค.
์ ์ถฉ ๋ชจ๋ธ์ธ UMS(User-Mode Scheduling) ๋ ์ปค๋์ด ์ค๋ ๋๋ฅผ ์๋ฉด์ ์ฌ์ฉ์ ๋ชจ๋์์ ์ค์ผ์ค๋งํ๋ Windows 7+ x64 ๊ธฐ๋ฅ์ผ๋ก, Fiber์ ํ๊ณ๋ฅผ ํด๊ฒฐํ๋ ค ํ์ง๋ง ์ฌ์ฉ ๋ณต์ก๋ ๋๋ฌธ์ ์ฑํ๋ฅ ์ด ๋ฎ์ต๋๋ค.
Q10. โC++์ std::thread, std::mutex๊ฐ Windows์์ ์ด๋ป๊ฒ ๋งคํ๋๊ณ , TLS์ CRT๊ฐ ์ปจํ ์คํธ ์ค์์นญ์ ๋ฏธ์น๋ ์ํฅ์ ๋ฌด์์ธ๊ฐ์?โ
๋งคํ๋ถํฐ ๋ณด๋ฉด,
std::thread๋ MSVC์์_beginthreadexโCreateThread๋ก ๋งคํ๋ฉ๋๋ค._beginthreadex๋ฅผ ๊ฑฐ์น๋ ์ด์ ๋ CRT์ TLS ์ด๊ธฐํ(stdio ๋ฝ, errno, strtok ๋ฑ)๊ฐ ํ์ํ๊ธฐ ๋๋ฌธ์ ๋๋ค โ rawCreateThread๋ฅผ ์ง์ ์ฐ๋ฉด CRT ํจ์๊ฐ ๋ฏธ๋ฌํ๊ฒ ๊นจ์ง ์ ์์ต๋๋ค.
std::mutex๋ Visual Studio 2019 16.x ์ดํ SRWLock ์์ ๊ตฌํ๋ผ ์์ด ๋ฌด๊ฒฝํฉ ์ผ์ด์ค์์ ์ปจํ ์คํธ ์ค์์นญ์ด ์ผ์ด๋์ง ์์ต๋๋ค.std::shared_mutex๋ SRWLock์ R/W ๋ถ๋ฆฌ๋ฅผ ๊ทธ๋๋ก ๋ ธ์ถ.std::condition_variable์ Windows Condition Variable.std::atomic์ CPU ๋ช ๋ น์ผ๋ก ์ง์ ๋งคํ๋์ด ์ปจํ ์คํธ ์ค์์นญ ์์ฒด๊ฐ ์์ต๋๋ค.TLS(Thread Local Storage) ๋ ์ปจํ ์คํธ ์ค์์นญ์ ์ํฅ์ด ๊ฑฐ์ ์์ต๋๋ค. TLS ๋ณ์๋ ์ค๋ ๋ ์๊ธฐ ๋ฉ๋ชจ๋ฆฌ(TCB๊ฐ ๊ฐ๋ฆฌํค๋ ์์ญ)์ ์์ฃผํ๊ณ , ์ปดํ์ผ๋ฌ๊ฐ
gs:[...]์ธ๊ทธ๋จผํธ ๋ ์ง์คํฐ ๊ธฐ์ค์ผ๋ก ์ ๊ทผํ๊ธฐ ๋๋ฌธ์ OS๊ฐ ๋ฐ๋ก ์ ์ฅยท๋ณต์ํ ํ์๊ฐ ์์ต๋๋ค โ TCB๊ฐ ์ ์ค๋ ๋ ๊ฒ์ผ๋ก ๋ฐ๋๋ฉด ์๋์ผ๋ก ์ TLS๋ฅผ ์ฐพ์๊ฐ๋๋ค.__declspec(thread)(MSVC) ๋๋thread_local(C++11)์ด ์ปจ๋ฒค์ ์ ๋๋ค.CRT ์ต์ ์ ๋ฏธ๋ฌํ๊ฒ ์ํฅ์ด ์์ต๋๋ค.
/MT(์ ์ CRT)์/MD(DLL CRT)๋ ๊ฐ์ ํ๋ก์ธ์ค์ ๋ชจ๋๋ค์ด ๊ฐ์ CRT ์ธ์คํด์ค๋ฅผ ๊ณต์ ํ๋๋๋ฅผ ๊ฒฐ์ ํ๊ณ , CRT ๋ด๋ถ์๋ stdio ๋ฝ, ํ ๋ฝ, static ๋ณ์ ์ด๊ธฐํ ๋ฝ์ด ์์ด ์ด๊ฒ ์๋์น ์์ ์ปจํ ์คํธ ์ค์์นญ์ ์ ๋ฐํ ์ ์์ต๋๋ค. ๋งค ํ๋ ์ ์ฌ๋ฌ ์ค๋ ๋๊ฐprintf๋ฅผ ํธ์ถํ๋ฉด stdio ๋ฝ ๊ฒฝํฉ์ผ๋ก ์ปจํ ์คํธ ์ค์์นญ์ด ๋ฐ์ํ๋ ๊ฒ ๋ํ ์ฌ๋ก์ ๋๋ค โ ๊ฒ์/์๋ฒ์์ ์์ฒด lock-free ๋ก๊น ์ ์ฐ๋ ์ด์ ์ ๋๋ค. MSVC ๋ฌธ์๊ฐ ์ผ๊ด๋๊ฒ/MD+_beginthreadex์ฌ์ฉ์ ๊ถ์ฅํ๋ ์ด์ ๊ฐ ์ด๋ฐ ๋ฉ๋ชจ๋ฆฌยท๋ฝ ์ผ๊ด์ฑ ๋๋ฌธ์ ๋๋ค.
18. ํต์ฌ ์์ฝ ์นด๋ (์ฌ๊ฒ์ฌ)
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
์ปจํ
์คํธ ์ค์์นญ = CPU ์ฝ์ด์์ ์คํ๋๋ ์ค๋ ๋/ํ๋ก์ธ์ค๋ฅผ ๋ค๋ฅธ ๊ฒ์ผ๋ก ๊ฐ์๋ผ์ฐ๋ OS ์์
.
ํ์ฌ ์ปจํ
์คํธ(๋ ์ง์คํฐยทSPยทPC) โ PCB/TCB ์ ์ฅ โ ๋ค์ ์ปจํ
์คํธ ๋ณต์.
๋ฐ์ ์์ 4๊ฐ์ง:
โ ํ์ด๋จธ ์ธํฐ๋ฝํธ โ quantum ๋ง๋ฃ (์ ์ ํ)
โก ๋ธ๋กํน ์์คํ
์ฝ โ read/recv/WaitForSingleObject
โข ๋๊ธฐํ ๊ฐ์ฒด ๋๊ธฐ โ mutex/event/condition variable
โฃ ์๋ฐ์ ์๋ณด โ Sleep(0)/SwitchToThread/std::this_thread::yield
๋น์ฉ ์์:
โ ๋ ์ง์คํฐ ์ ์ฅยท๋ณต์ โ ์ง์ , ์๋ฐฑ ns
โก ์บ์ ์ฝ๋ (cache cold) โ ๊ฐ์ , ๊ฐ์ฅ ํผ (์~์์ญ ฮผs)
โข TLB flush โ ํ๋ก์ธ์ค ์ ํ๋ง (PCID/ASID๋ก ํํผ ๊ฐ๋ฅ)
โฃ ํ์ดํ๋ผ์ธยท๋ถ๊ธฐ ์์ธก ๋ฌดํจํ
โค ์ปค๋ ์ง์
์์ฒด (๋ชจ๋ ์ค์์น)
ํ๋ก์ธ์ค ์ ํ vs ์ค๋ ๋ ์ ํ:
์ค๋ ๋ = TCB๋ง ๊ต์ฒด, ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ๋ณด์กด โ 1~5 ฮผs
ํ๋ก์ธ์ค = CR3 ๊ต์ฒด + TLB flush + ์บ์ ์ฝ๋ โ 5~20 ฮผs
โ 5~10๋ฐฐ ์ฐจ์ด (19๋ฒ ํ๊ท)
๋ชจ๋ ์ค์์น โ ์ปจํ
์คํธ ์ค์์น:
๋ชจ๋ ์ค์์น = ๊ฐ์ ์ค๋ ๋ user โ kernel (PCB ๊ต์ฒด ์์)
์ปจํ
์คํธ ์ค์์น = ์คํ ์ฃผ์ฒด ๊ต์ฒด
์ค์ผ์ค๋ง:
์ ์ ํ (WindowsยทLinux ํ์ค) vs ํ๋ ฅ์ (Fiberยท์ฝ๋ฃจํด)
Round-Robin / ์ฐ์ ์์ / MLFQ
Windows quantum ๊ธฐ๋ณธ ~15.6ms, timeBeginPeriod(1)๋ก 1ms๊น์ง
Windows ๋น์ฉ ์คํํธ๋ผ (๋ฎ์ โ ๋์):
std::atomic ์ ns (์ปจํ
์คํธ ์ค์์น ์์)
Fiber SwitchToFiber ์์ญ ns (์ฌ์ฉ์ ๋ชจ๋, ๋ฉํฐ์ฝ์ด X)
ConcRT Context::Yield ์์ญ~์๋ฐฑ ns (์ฌ์ฉ์ ๋ชจ๋ ํ๋ ฅ์ )
Critical Section / SRWLock 50~100 ns ๋ฌด๊ฒฝํฉ (์ฌ์ฉ์ ์ฐ์ , ๊ฐ์ ํ๋ก์ธ์ค๋ง)
Condition Variable ๋น์ท (์ฌ์ฉ์ ์ฐ์ )
Mutex / Event / Semaphore 1~3 ฮผs (ํญ์ ์ปค๋, ํ๋ก์ธ์ค ๊ฐ ๊ณต์ ๊ฐ๋ฅ)
OS ์ค๋ ๋ quantum ๋ง๋ฃ 1~5 ฮผs (์ค๋ ๋ ์ ํ)
OS ํ๋ก์ธ์ค ์ ํ 5~20 ฮผs (TLB flush ํฌํจ)
C++ ํ์ค โ Windows ๋งคํ:
std::thread โ _beginthreadex โ CreateThread
std::mutex โ SRWLock (VS 2019 16.x+)
std::shared_mutex โ SRWLock (R/W)
std::condition_var โ Windows Condition Variable
std::atomic โ CPU ๋ช
๋ น (LOCK XADD ๋ฑ)
std::async โ ThreadPool API or ์ ์ค๋ ๋
TLS:
__declspec(thread) / thread_local โ ์ค๋ ๋ ์๊ธฐ ๋ฉ๋ชจ๋ฆฌ ์์ฃผ
์ปจํ
์คํธ ์ค์์น ์ ์๋ ๋ณด์กด (gs:[...] ์ธ๊ทธ๋จผํธ ๋ฒ ์ด์ค ๊ต์ฒด)
TlsAlloc/TlsGetValue๋ก ๋์ ์ฌ๋กฏ๋ ๊ฐ๋ฅ
CRT ์ต์
:
/MT ์ ์ CRT โ ๋จ๋
EXE, ์ธ์คํด์ค ๋ถ๋ฆฌ (์ํ)
/MD DLL CRT โ ๊ถ์ฅ (UCRT, ๊ฐ์ ํ๋ก์ธ์ค ๋ชจ๋ ์ธ์คํด์ค ๊ณต์ )
๋ด๋ถ ๋ฝ: stdioยทheapยทstatic init โ ์๋์น ์์ ์ปจํ
์คํธ ์ค์์น ์ ๋ฐ
์ธ๋ฆฌ์ผ:
GameThread / RenderThread / RHIThread ๋ถ๋ฆฌ + ๋ช
๋ น ํ
TaskGraph + work stealing (์ฌ์ฉ์ ๋ชจ๋)
ENamedThreads ๋ช
์ (GameThread, AnyBackgroundThreadNormalTask)
FRunnableThread (CreateThread ๋ํ) / FCriticalSection (Critical Section)
TQueue<T, EQueueMode::Mpsc> (lock-free)
IsInGameThread() / check() โ ์์ ๊ฒ์ฆ
๊ธฐ์ตํ ํ ์ค:
"์ปจํ
์คํธ ์ค์์นญ์ ํผํ ์ ์๋ OS ๋ฉ์ปค๋์ฆ, ์์ง๋์ด๋ง์ ๋น๋์ ๋น์ฉ์ ์ค์ด๋ ๋ฐฉํฅ."
19. ํ๊ท ๋ค๋ฆฌ โ ๋ค๋ฅธ CS ํ์ผ ์ฐ๊ฒฐ
| ํ์ผ | ์ฐ๊ฒฐ ์ง์ |
|---|---|
| 01_runtime | ๋ฉ๋ชจ๋ฆฌ 4์์ญ(Code/Data/Heap/Stack) โ ํ์ด์ง ํ ์ด๋ธยทTLBยท์บ์์ ํ ๋. ํ๋ก์ธ์ค ์ ํ ์ ๊ฐ์ ์ฃผ์ ๊ณต๊ฐ ๊ต์ฒด์ ์ถ๋ฐ์ |
| 03_new_vs_malloc | ํ ๋ฝ(malloc/new ๋ด๋ถ)์ด ์ปจํ
์คํธ ์ค์์น ์ ๋ฐ ๊ฐ๋ฅ โ mimalloc/tcmalloc ๊ฐ์ ๋ฉํฐ์ค๋ ๋ ์นํ ํ ๋น๊ธฐ๋ก ํํผ |
| 09_rtti_raii | std::lock_guard/std::unique_lock์ด RAII๋ก ๋ฝ ์๋ ๊ด๋ฆฌ โ ์ปจํ
์คํธ ์ค์์นญ ํ unlock ๋๋ฝ ๋ฐฉ์ง |
| 11_smart_pointer | shared_ptr ์ ์ด ๋ธ๋ก์ atomic ์นด์ดํฐ โ ์ปจํ
์คํธ ์ค์์น ์์ด ์์ ํ ์ฐธ์กฐ ์นด์ดํ
|
| 16_stl_containers | STL ์ปจํ ์ด๋ thread-safety ์ปจ๋ฒค์ โ ์ธ๋ถ mutex ๋๋ lock-free ์ปจํ ์ด๋๋ก ์ปจํ ์คํธ ์ค์์น ์ ์ด |
| 19_process_vs_thread | ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ด 19๋ฒ์ ํต์ฌ ๋น๊ต ํญ๋ชฉ โ 21๋ฒ์์ ๋ฉ์ปค๋์ฆ ๊น์ด ํ์ฅ. PCB/TCBยทTLBยทCR3 ๊ฐ๋ ์ง์ ํ๊ท |
| 20_stack_overflow | ์ค๋ ๋๋ณ ๋ ๋ฆฝ ์คํ + SP๊ฐ ์ปจํ ์คํธ์ ํต์ฌ ๊ตฌ์ฑ์์ โ 20๋ฒ์์ ๋ค๋ฃฌ ์คํ ํ๊ณ์ ์ปจํ ์คํธ ๋ณด์กด์ด ๊ฐ์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ค๋ฃธ |