가시성과 코드 재배치 예시
int32 x = 0;
int32 y = 0;
int32 r1 = 0;
int32 r2 = 0;
volatile bool ready;
void Thread_1()
{
while(!ready){}
y = 1;// Store y
r1 = x;// Load x
}
void Thread_2()
{
while (!ready) {}
x = 1;// Store x
r2 = y;// Load y
}
int main()
{
int32 count = 0;
while (true)
{
ready = false;
count++;;
x = y = r1 = r2 = 0;
thread t1(Thread_1);
thread t2(Thread_2);
ready = true;
t1.join();
t2.join();
if (r1 == 0 && r2 == 0)
break;
}
cout << count << " 번만에 빠져나옴" << endl;
}
위의 코드를 실행해 보면 환경이나 상황에 따라 다르겠지만
break를 빠져나오는 경우가 일부 발생한다
Thread_1 함수와 Thread_2 함수 중 간발의 차로 누군가는 먼저 실행이 될 것이다
만약 Thread_1 함수의 y = 1; 코드가 먼저 실행되거나
Thread_2 함수의 x = 1; 코드가 먼저 실행될 것이다
그러면, 결과적으로 r1과 r2는 0이 되는 경우는 없어야 하는 것이 맞다
그런데 0이 되며 break를 빠져나오는 경우가 발생하는
그 이유는 가시성과 코드 재배치와 연관이 있다
가시성
데이터를 처리할 때, RAM이 아닌 캐시를 이용해 작업하는 경우가 발생한다
이러한 경우에는 우리가 실행한 코드가 RAM에 의해 관리된다는 보장이 없다
단일 스레드 기준으로는 상관이 없지만
멀티 스레드 기준으로는 이러한 상황이 우리의 예상과는 매우 달라질 수 있다
예를 들어,
위의 코드에서 r1 = x; 라는 코드에서
x를 캐시에 올라와있는 데이터로 이용하게 된다면
이전에 다른 스레드에서 x를 바꿨다고 하더라도 의미가 없어지는 상황이 발생하며
이러한 상황을 가시성이라고 한다
C# volatile
C#에서는 volatile 키워드를 활용하면
컴파일러 최적화도 막을 수 있고
캐시 메모리가 아닌 RAM에서 데이터를 관리 및 처리하도록 하는
기능이 제공되어 가시성을 해결할 수 있다
코드 재배치
가시성이 해결되었다하더라도 위의 코드에서 발생하는 문제는 여전하다
그 이유는 코드 재배치 때문이다
코드 재배치는 컴파일러 최적화와 CPU 최적화에서 발생한다
이 두가지 최적화로 인해서
우리가 작성한 코드의 순서가 마음대로 바뀔 수 있다는 것이다
코드 재배치 - 컴파일러 최적화
컴파일러 최적화는
우리가 작성한 코드들을 효율적으로 처리하기 위해서
컴파일러가 코드를 재배치한다
재배치된 결과는 어셈블리어를 통해서 확인할 수 있다
코드 재배치 - CPU 최적화
컴파일러 최적화와는 달리 CPU 최적화는 우리가 직접 확인할 수 없다
그래서 사실상 이러한 코드 재배치를 우리가 직접 관리하기 위해서
C++ 11부터 멀티 스레드 환경을 위한 다양한 메모리 관리 문법들이 추가되었다
CPU 파이프라인과 코드 재배치(CPU 최적화)
CPU에서 명령을 처리하는 단계는
총 4단계로 Fetch(가져오기), Decode(해석), Execute(실행), Write-back(반환)으로 구성되어 있다
여러 단계를 병렬적으로 처리하기 위해서
하나의 명령이 진행될 때 나머지 명령들이 대기하고 있는 것이 아닌
한 단계에 하나의 명령만 존재하도록 한 상태를 지키고
여러 단계들이 병렬적으로 진행된다
이러한 과정에서 명령들이 정해진 순서대로 처리되는 것이 아닌
CPU의 판단에 따라서 효율적으로 순서가 재배치된다
이로 인해서, CPU 최적화로 인한 코드 재배치가 발생한다
'게임 서버' 카테고리의 다른 글
[게임서버 섹션2 Note] Thread Local Storage (0) | 2024.12.31 |
---|---|
[게임서버 섹션2 Note] 메모리 모델 (0) | 2024.12.31 |
[게임서버 섹션2 Note] 캐시 (0) | 2024.12.30 |
[게임서버 섹션2 Note] Future (0) | 2024.12.30 |
[게임서버 섹션2 Note] Condition Variable (0) | 2024.12.30 |