나만의 작은 도서관

[TIL][C++] 250704 MMO 서버 개발 51일차: 작업에 따라 스레드는 항상 CPU를 열심히 사용하지 않을 수 있다.(CPU bound, I/O bound) 본문

Today I Learn

[TIL][C++] 250704 MMO 서버 개발 51일차: 작업에 따라 스레드는 항상 CPU를 열심히 사용하지 않을 수 있다.(CPU bound, I/O bound)

pledge24 2025. 7. 4. 23:20
주의사항: 해당 글은 일기와 같은 기록용으로, 다듬지 않은 날것 그대로인 글입니다. 

작업에 따라 스레드는 항상 CPU를 열심히 사용하지 않을 수 있다.

  • 스레드가 CPU 점유권을 얻었다고 해서 time slice가 끝날 때까지 열심히 CPU에서 연산을 할 것이라 보장할 수 없다. 중간중간에 멀리 있는 메모리 데이터(ex. 메인 메모리, 원격 메모리)를 가져오는 I/O 작업을 하거나, 시스템콜을 하면 코드 진행이 블로킹(Blockin)되고, 블로킹되어 있는 동안 CPU를 활용하지 않기 때문이다.
  • 그래서 CPU 스케쥴러는 스레드가 배정된 time slice 동안 계속해서 CPU를 사용하지 않는 순간들을 알뜰하게 활용하기 위해 블로킹된 스레드를 CPU에서 내리고, 다른 스레드를 점유시키게 한다.
  • 즉, 스레드가 맡은 작업에 따라 전체 작업 시간 중 CPU 연산을 하지 않는 시간이 더 길 수도 있다는 것이다.

 

프로세스의 인생은 CPU 버스트와 I/O 버스트의 연속

  • 버스트(burst)란 “어떤 형상이 짧은 시간에 집중적으로 일어나는 일”을 의미한다. 프로세스의 관점에서 버스트의 종류는 아래와 같이 크게 두 가지가 있다.
    • CPU 버스트: 임의의 프로세스가 CPU에서 한 번에 연속적으로 실행되는 시간
    • I/O 버스트: 프로세스가 I/O 작업을 요청하고 결과를 기다리는 시간
  • 프로세스(또는 스레드)는 종료될 때까지 CPU 버스트와 I/O 버스트를 번갈아가며 실행한다.

 

CPU bound, I/O bound

  • 위 두 내용을 토대로, 프로세스(또는 스레드)는 작업을 시작해서 끝날 때까지 CPU 버스트와 I/O 버스트의 비율이 다를 수 있다는 것을 알 수 있다. 이때 어느 쪽에 더 비율이 높냐에 따라 아래와 같이 부른다.
    • CPU bound: CPU burst가 많은 프로세스 또는 스레드. 작업의 전체 시간 중 많은 시간을 CPU의 연산 작업을 하는데 할애한다. (ex. 동영상 편집 프로그램, 머신러닝 프로그램)
    • I/O bound: I/O burst가 많은 프로세스 또는 스레드. 작업의 전체 시간 중 대부분의 시간이 I/O 작업 대기 시간이다. (ex. 일반적인 백엔드 서비스)

 

CPU bound의 버스트 길이와 time slice

  • CPU bound 타입이라면 얼마나 오랫동안 CPU 연산작업을 진행할까? 아래 그림을 보면 알 수 있듯, 많은 경우에서 8ms 이내의 버스트 길이를 가진다.

  • 이 “8ms”라는 것을 알면 time slice에 대해 연관 지어 고민해야 할 부분이 있다. 바로 “단발성 작업이 여러 time slice에 걸쳐 실행되는 경우가 있을까?”이다. 스레드가 CPU 코어를 점유했을 때 배정받은 time slice 내에 작업을 끝내지 못한다면 CPU 전체가 busy 상태일 때 다른 스레드에게 자리를 내어줄 수 있기 때문이다.
CPU 스케쥴러의 Cache Affinity
CPU 스케쥴러는 되도록이면 같은 스레드에게 같은 코어를 재배정해주려고 한다.(cache affinity) 왜냐하면 같은 코어를 재배정해주면 context swtiching이 발생하지 않아 성능을 높일 수 있기 때문. 하지만 해당 코어가 비정상적으로 뜨겁거나(hot spot), 모든 코어가 busy 상태이고 ready 상태 스레드가 오랜 시간 대기 중이었다면, 그 자리를 내어줄 수밖에 없다.
  • 하지만 대부분의 OS의 경우 time slice의 길이는 가변적이다. 그래서 “하나의 time slice내에 작업이 끝나지 않아 작업이 끝나지 않는 경우”, OS는 time slice를 동적으로 늘려 해결한다. 아래는 각 OS에 따른 대략적인 time slice의 길이이다.
플랫폼 / OS 타임 슬라이스 길이(대략)
Windows (현대 버전) 10 ~ 20ms
Linux (CFS 스케줄러 기준) 1 ~ 100ms (가변적)
macOS 1 ~ 10ms
실시간 OS (RTOS) 수십 μs ~ 수 ms