프로세스 실행 실험 (1) 논리 CPU가 1개 일 때

리눅스에서 멀티코어 CPU는 1개의 코어가 1개의 CPU로 인식된다. 시스템에서 CPU로 인식하는 것을 논리 CPU라고 하겠다.

책에서는 1개의 논리 CPU에서 각각 100ms 가 소요되는 프로세스를 동시에 1개, 2개, 4개를 실행하며 결과를 관찰한다. 실험코드를 다운받아서 동일하게 실행해 볼 수 있다.

고찰

  • 동시에 프로세스를 여러 개 실행하더라도 특정 순간에 논리 CPU에서 동작되는 프로세스는 1개
  • 논리 CPU에는 여러 개의 프로세스가 순차적으로 1개씩 동작. 첫 번째 프로세스부터 마지막 프로세스까지 프로세스가 한 바퀴 다 돌고 나면 다시 첫 번째 프로세스부터 동작하는 라운드로빈 방식으로 동작함
  • 각 프로세스는 대략 같은 타임 슬라이스를 가짐
  • 프로세스를 종료할 때까지의 경과 시간은 프로세스 수에 비례해 증가함

컨텍스트 스위치

논리 CPU 상에서 동작하는 프로세스가 바뀌는 것을 컨텍스트 스위치라고 부른다. 컨텍스트 스위치는 프로세스가 어떤 프로그램을 수행 중이더라도 타임 슬라이스를 모두 소비하면 발생한다. 따라서 프로그램 내 특정 함수의 처리시간이 예상보다 오래걸렸을 때 처리 중 컨텍스트 스위치가 발생했을 가능성에 대해서도 고려해야한다.

프로세스의 상태

상태 의미
실행 상태 현재 논리 CPU를 사용하고 있음
실행 대기 상태 CPU 시간이 할당되기를 기다리고 있음
슬립 상태 이벤트가 발생하기를 기다리고 있으며 이벤트 발생까지는 CPU 시간을 사용하지 않음
좀비 상태 프로세스가 종료한 뒤 부모 프로세스가 종료 상태를 인식할 때까지 기다리고 있음

ps ax의 STAT 해석

STAT 상태
R 실행 상태 혹은 실행 대기 상태
S or D 슬립 상태, 시그널에 따라 실행 상태로 되돌아오는 것이 ‘S’, 그렇지 않은 것이 ‘D’
Z 좀비상태

상태 변환

[그림]

idle 상태

논리 CPU가 실행해야 할 프로세스가 없는 시간에 논리 CPU는 idle 프로세스라고 하는 아무것도 하지 않는 특수한 프로세스가 동작한다. idle 프로세스는 특수한 명령을 통해 소비 전력을 낮춰 CPU 를 대기상태로 유지한다.(노트북/스마트폰으로 아무것도 하지 않는 상태일 때 배터리가 오래가는 이유)

여러가지 상태 변환

[그림]

스루풋과 레이턴시

  • 스루풋 : 단위 시간당 처리된 일의 양으로 높을수록 좋음
  • 레이턴시 : 각각의 처리가 시작부터 종료까지의 경과된 시간으로 짧을수록 좋음
용어 계산식
스루풋 단위 시간당 처리된 일의 양으로 높을수록 좋음 완료한 프로세스의 수 / 경과시간
레이턴시 각각의 처리가 시작부터 종료까지의 경과된 시간으로 짧을수록 좋음 처리 종료 시간 - 처리 시작 시간

실제 시스템

논리 CPU가 항상 움직이는, 즉 idle 상태가 없는 경우, 그리고 실행 대기 상태의 프로세스가 없는 경우에 스루풋과 레이턴시는 모두 최대가 된다. 하지만 실제 시스템은 그렇게 이상적으로 동작하지 않는다.

idle 상태가 없으려면 프로세스가 늘 실행 상태여야 하는데, 실제 시스템에서 idle 상태 없이 cpu를 최대한 활용하려면 실행 대기 상태의 프로세스가 생긴다. 실행 대기 상태의 프로세스가 생긴다는 것은 레이턴시는 길어진다는 것이다. 그렇다고 프로세스를 논리 CPU 보다 적게 생성하면 CPU가 idle 상태가 되어 스루풋이 낮아질 것이다. 이처럼 스루풋과 레이턴시는 trade-off 관계에 있는 경우가 많다.

프로세스 실행 실험 (2) 논리 CPU가 여러 개일 때 스케쥴링

실험(1) 에서는 1개의 논리 CPU에서 각각 100ms 가 소요되는 프로세스를 동시에 1개, 2개, 4개를 실행했다.
실험(2) 에서는 2개의 논리 CPU에서 각각 100ms 가 소요되는 프로세스를 동시에 1개, 2개, 4개를 실행한다. 차이는 논리 CPU 의 수이다.
역시 실험코드를 다운받아서 동일하게 실행해 볼 수 있다.

고찰

  • 1개의 CPU에서 동시에 처리되는 프로세스는 1개
  • 여러 개의 프로세스가 실행 가능한 경우 각각의 프로세스를 적절한 길이의 시간(타임 슬라이스)마다 CPU에서 순차적으로 처리
  • 멀티 코어 CPU 환경에서 여러 개의 프로세스를 동시에 동작시키지 않으면 스루풋이 오르지 않음. 코어 n개이므로 성능이 n배! 라고 말할 수 있는 건 최선의 경우임
  • 단 1개의 논리 CPU의 경우와 마찬가지로 프로세스 수를 논리 CPU 수보다 많게 하더라도 스루풋은 오르지 않음

경과 시간과 사용시간

경과시간: 프로세스가 시작해서 종료할 때까지의 시간
사용시간: 프로세스가 실제로 논리 CPU를 사용한 시간

실험
논리 CPU 수와 10s 걸리는 프로세스 수를 조절해 가며 실험

결과

논리 CPU 수 프로세스 수 경과시간 사용시간
1 1 11.567s 11.560s
1 2 21.487s 21.480s
2 1 11.569s 11.564s
2 4 12.103s 22.424s

슬립을 사용하는 프로세스

sleep 을 사용하면, CPU가 처리할 작업이 없어 idle 상태가 되며, 경과시간은 sleep 한 시간 만큼이지만 사용시간은 0에 가깝다.

우선순위 변경

프로세스에 우선순위를 부여하기 위해서는 nice() 시스템 콜을 사용한다. 우선 순위는 -19부터 20까지 설정할 수 있으며 기본 값은 0이다. 우선순위가 높으면 CPU 시간을 더 많이 배정받는다. 우선 순위를 낮추는 것은 리눅스 사용자 계정 누구나 가능하지만 높이는 것은 root 권한있는 슈퍼유저 뿐이다.

sar 의 출력 에 나오는 %nice field는 우선순위를 변경한 프로그램을 실행한 시간의 할당량이다.