🧱 CPU 파이프라인 구조란?

CPU는 명령어를 아래와 같은 여러 단계로 나누어 병렬로 실행한다.

  • IF (Instruction Fetch): 명령어 읽기
  • ID (Instruction Decode): 명령어 해석
  • IE (Instruction Execute): 실행
  • RW (Read/Write): 메모리 접근

📌 모든 명령어가 위 단계들을 거치며, 각 명령어는 서로 다른 시점에 병렬로 처리된다. 이 구조 덕분에 성능이 향상되지만, 동시에 순서 보장이 어려워지는 문제가 있다.


🧨 코드 재배치와 멀티 쓰레드의 위험

🔍 예제 코드 (문제 상황)

int32 x = 0, y = 0, r1 = 0, r2 = 0;
volatile bool ready = false;

void Thread_1() {
    while (!ready);
    y = 1;
    r1 = x;
}

void Thread_2() {
    while (!ready);
    x = 1;
    r2 = y;
}

int main() {
    int 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 << " 번만에 빠져나옴.\n";
}

😨 문제 분석

  • 싱글 쓰레드라면 r1 == 0 && r2 == 0는 절대 일어나지 않음.
  • 하지만 실제 실행해보면 수천 번 반복 후 발생함.

🎯 이유는?

  1. 코드 재배치(Code Reordering)

    • 컴파일러는 store, load 간 연관이 없다고 판단하면 순서를 변경하여 성능을 높이려 한다.
    • 이로 인해 예상치 못한 실행 순서가 발생할 수 있다.
  2. 가시성(Visibility) 문제

    • CPU의 각 코어마다 캐시가 존재한다.
    • 다른 스레드의 최신 값을 읽지 못하고, 자신의 캐시된 값을 사용하게 되는 경우도 있다.

🛠 해결 방법

✔️ 1. 원자적 연산 사용 (std::atomic)

#include <atomic>
std::atomic<int> x(0), y(0);
int r1, r2;

void Thread_1() {
    x.store(1, std::memory_order_relaxed);
    r1 = y.load(std::memory_order_relaxed);
}

void Thread_2() {
    y.store(1, std::memory_order_relaxed);
    r2 = x.load(std::memory_order_relaxed);
}
  • std::atomic동기화와 가시성을 보장한다.
  • memory_order_relaxed는 순서를 보장하진 않지만 데이터 경쟁 없이 안전한 접근 가능.

✔️ 2. 뮤텍스 사용 (std::mutex)

#include <mutex>
std::mutex mtx;

void Thread_1() {
    std::lock_guard<std::mutex> lock(mtx);
    x = 1;
    r1 = y;
}
  • std::mutex동시에 하나의 스레드만 공유 자원에 접근하도록 보장
  • 간단하지만 병목이 생길 수 있음

🧺 파이프라인을 빨래로 비유해보면?

  • 한 벌의 빨래가 있다고 가정할 때, 세탁 → 건조 → 다림질 → 개기의 과정을 각각 파이프라인 스테이지라고 하자.
  • 모든 빨래가 세탁을 마칠 때까지 기다리는 것보다, 하나의 빨래가 세탁을 마치는 순간 다음 빨래가 세탁기에 들어가는 것이 더 효율적이다.

이렇게 파이프라인 방식으로 처리하면 CPU는 더 많은 일을 동시에 수행할 수 있다. 하지만 순서 문제가 생길 수도 있음에 유의해야 한다!


profile
李家네_공부방

0개의 댓글