KoreanFoodie's Study
[C++ 게임 서버] 1-13. CPU 파이프라인 (feat. 코드 재배치) 본문
[C++ 게임 서버] 1-13. CPU 파이프라인 (feat. 코드 재배치)
핵심 :
1. 컴파일러는 어셈블리어를 배치하는 과정에서 코드 재배치를 할 수 있다. 이 과정에서 의도치 않은 결과가 도출될 수 있다.
2. CPU 파이프라인은 CPU 가 명령어를 효율적으로 하기 위한 시스템이다.
CPU 파이프라인에 대해 공부를 하게 되면, 최적화를 위해 컴파일러가 임의로 어셈블리 코드를 재배치한다는 것을 알 수 있다.
싱글 쓰레드에서는 순차적으로 로직이 실행됨이 보장되지만, 멀티 쓰레드에서는 꼭 의도대로 프로그램이 동작하지 않을 수 있는데... 다음 코드를 보자.
volatile bool ready = false;
// 가시성, 코드 재배치
int32 x = 0;
int32 y = 0;
int32 r1 = 0;
int32 r2 = 0;
void foo()
{
while (!ready)
;
x = 1; // store x
r1 = y; // Load y
}
void poo()
{
while (!ready)
;
y = 1; // store y
r2 = x; // Load x
}
int main()
{
int count = 0;
while (true)
{
ready = false;
count++;
x = y = r1 = r2 = 0;
thread t1(foo);
thread t2(poo);
ready = true;
t1.join();
t2.join();
if (r1 == 0 && r2 == 0)
{
break;
}
}
cout << count << " 번 만에 빠져나옴!" << endl;
}
싱글 쓰레드에서는 main 함수에서의 while 문이 break 되는 경우가 없겠지만, 멀티 쓰레드 환경에서는 이와 같은 동작이가능하다.
그 이유는, foo 와 poo 에서 store 과 load 의 순서를 바꾸어 컴파일러가 실행될 수도 있기 때문이다. 컴파일러 입장에서 store 과 load 사이에는 로직상의 연관성이 없으므로, 임의로 바꾸어 실행을 할 수 있게 된다 😅 (꼭 그런 것은 아니고, 효율적이라고 판단했을 때 그런 행동을 할 것이다)
실제로 CPU 에서의 작업은 instruction 단위로 이루어져 있는데, store, load 등의 순서를 최적화하는 과정에서 우리가 의도하지 않은 결과가 나타날 수 있다는 것만 알아두자! 😊
'Game Dev > Game Server' 카테고리의 다른 글
[C++ 게임 서버] 1-15. Thread Local Storage (0) | 2023.07.24 |
---|---|
[C++ 게임 서버] 1-14. 메모리 모델 (atomic, 코드 재배치) (0) | 2023.07.21 |
[C++ 게임 서버] 1-12. 캐시 (Temporal Locality, Spatial Locality) (0) | 2023.07.19 |
[C++ 게임 서버] 1-11. future, promise, packaged_task (0) | 2023.07.18 |
[C++ 게임 서버] 1-10. Condition Variable (조건 변수) (0) | 2023.07.14 |
Comments