사전 CPU
개념

CPU

gabury1

컴퓨터에서 계산을 실제로 해내는 장치입니다. 메모리에 적힌 명령을 하나씩 읽어 그대로 실행합니다. 다음에 무엇을 할지는 지금 어디를 읽고 있는지가 정합니다.

상세

조리법을 한 줄씩 읽어가며 그대로 따라 하는 요리사를 떠올리면 됩니다. 어디까지 읽었는지는 손가락으로 짚어 둡니다.

CPU(Central Processing Unit, 중앙처리장치)는 메모리에 놓인 명령어를 하나씩 가져와 해독하고 실행하는 장치입니다. 무엇을 계산할지는 장치 안에 미리 새겨져 있지 않습니다. 메모리에 적힌 명령어가 그때그때 정합니다. 같은 장치가 다른 프로그램을 돌릴 수 있는 이유가 이것입니다.

명령어와 데이터는 같은 메모리에 함께 놓입니다. 1945년 EDVAC 보고서는 메모리 안의 한 덩이가 수인지 명령인지를 맨 앞 비트 하나로 가른다고 적습니다. 값을 담는 자리와 명령을 담는 자리가 따로 있는 것이 아닙니다. 같은 자리를 읽는 쪽이 무엇으로 보느냐가 다를 뿐입니다.

장치는 자기 안에 작은 저장 자리를 몇 개 둡니다. 계산의 중간값을 담는 자리를 레지스터라고 부릅니다. 메모리보다 훨씬 작지만 명령어가 직접 지목해 쓰는 자리입니다. 이 레지스터들과 별개로 자리가 하나 더 있습니다. 지금 실행 중인 명령어가 메모리의 어디에 있는지를 담는 자리입니다. 이 자리를 프로그램 카운터라고 부릅니다.

배경

초기의 계산 기계는 계산 순서를 바꾸려면 배선을 다시 꽂아야 했습니다. 무엇을 계산할지가 기계의 생김새에 박혀 있었습니다. 다른 계산을 시키는 일은 기계를 다시 만드는 일에 가까웠습니다.

필요한 것은 계산 순서를 기계 바깥에 두는 방법이었습니다. 순서를 적은 것도 결국 값이니 수를 담는 곳에 같이 담자는 것이 답이었습니다. EDVAC 보고서가 적은 구조가 이것입니다. 메모리에는 수와 명령이 섞여 놓입니다. 맨 앞 비트 하나가 둘을 가릅니다.

그러면 그 메모리를 읽어 명령을 실제로 수행하는 자리가 하나 필요해집니다. 계산과 판단이 그 한 자리로 모입니다. 여기에 붙은 이름이 중앙처리장치입니다.

동작

한 명령어를 처리하는 일은 몇 단계로 나뉩니다. 먼저 프로그램 카운터가 가리키는 주소에서 명령어를 읽어 옵니다. 이 읽기를 인출이라고 부릅니다. 명령어를 실행할 때마다 인출이 반드시 일어납니다. 읽어 온 비트가 무슨 명령인지를 해독합니다. 그다음 그대로 실행합니다. 결과는 레지스터나 메모리에 적습니다. 명령어에 따라서는 명령어를 읽어 오는 것 말고는 메모리에 손대지 않기도 합니다. 메모리를 읽고 쓰는 명령어는 따로 있습니다. 그 명령어가 어느 주소에 손댈지를 정합니다.

flowchart TD
    PC["프로그램 카운터"] --> F["인출"]
    F --> D["해독"]
    D --> X["실행"]
    X --> W["결과 쓰기"]
    W --> PC
    IRQ["인터럽트"] -.-> PC

한 바퀴가 끝나면 다음 바퀴로 넘어갑니다. 어디서 다시 시작할지는 프로그램 카운터가 정합니다. 이 값을 바꾸는 명령어가 흐름을 꺾습니다. 조건 없이 옮겨 가는 것과 조건을 보고 갈라지는 것, 두 갈래가 있습니다. 조건문과 반복문이 결국 이 자리로 내려옵니다.

바깥에서 신호가 들어와 흐름이 꺾이기도 합니다. 실행 중인 명령어와 상관없이 비동기로 들어오는 외부 사건을 인터럽트라고 부릅니다. 인터럽트는 진행 중이던 흐름을 예상 밖의 자리로 옮길 수 있습니다. 실행 중인 명령어 자체에서 생긴 이상한 상황은 예외라고 따로 부릅니다. 둘 중 무엇 때문이든 정해진 처리 자리로 넘어가는 것을 트랩이라고 부릅니다.

예시

RISC-V 의 ADD

RISC-V 명령어 집합에서 산술 명령 한 줄이 무엇을 하는지는 이렇게 정해져 있습니다. 기본 정수 명령 집합인 RV32I 는 레지스터 둘을 원본으로 쓰는 산술 명령을 여럿 정합니다. 이 명령들은 rs1 과 rs2 레지스터를 읽어 원본으로 삼고, 결과를 rd 레지스터에 적습니다. 어떤 연산인지는 명령어 안의 funct7 과 funct3 자리가 고릅니다. ADD 는 rs1 과 rs2 를 더합니다. SUB 는 rs1 에서 rs2 를 뺍니다. 자리 넘침은 무시하고 결과의 아래 XLEN 비트만 rd 에 적습니다. XLEN 은 레지스터 한 자리의 폭을 가리키는 이름입니다.

리눅스 sysfs 의 CPU 토폴로지

리눅스는 CPU 를 몇 개로 보고 있는지를 파일로 내보냅니다. 자리는 /sys/devices/system/cpu/cpuX/topology/ 입니다. 몇몇 아키텍처의 /proc/cpuinfo 출력과 비슷한 항목이 놓입니다. 그 위 디렉터리에는 전체를 세는 파일들이 있습니다.

kernel_max: 31
offline: 2,4-31,32-63
online: 0-1,3
possible: 0-31
present: 0-31

present 는 시스템에 있다고 확인된 CPU, possible 은 자원이 잡혀 있어 실제로 있기만 하면 온라인으로 올릴 수 있는 CPU, online 은 지금 온라인이라 스케줄링을 받는 CPU 입니다. kernel_max 는 커널 설정이 허용하는 최대 인덱스입니다. 커널 문서의 이 예에서는 시스템에 CPU 가 64개지만 nr_cpus 설정이 32로 잡혀 있어 32번부터 63번까지가 커널 최대치를 넘습니다.

cgroup v2 의 cpu.max

운영체제는 CPU 를 세기만 하는 것이 아니라 나눠 주기도 합니다. cgroup(control group) v2 의 cpu.max 가 그 몫을 정하는 파일입니다. 루트가 아닌 cgroup 에 있습니다. 읽고 쓸 수 있습니다.

cpu.max
max 100000

$max $period 꼴입니다. 그 그룹이 매 $period 동안 $max 까지 쓸 수 있다는 뜻입니다. $max 자리의 max 는 제한이 없다는 뜻입니다. 기본값은 max 100000 입니다. 이 파일은 공정 클래스 스케줄러 아래의 프로세스에만 걸립니다.

POSIX 의 sysconf

프로그램이 CPU 개수를 물을 때 쓰는 표준 창구입니다. POSIX(Portable Operating System Interface) 표준의 sysconf() 는 설정 가능한 시스템 한계나 옵션의 현재 값을 알려 줍니다. CPU 와 관련해서는 두 이름이 있습니다. _SC_NPROCESSORS_CONF 는 스레드를 돌리도록 만들어 줄 수 있는 실행 단위의 최대 개수입니다. _SC_NPROCESSORS_ONLN 은 지금 쓸 수 있는 실행 단위의 최대 개수입니다. 표준은 여기에 단서를 붙입니다. 실행 단위가 무엇인지, 쓸 수 있다는 것이 정확히 어떤 조건인지, 하나가 몇 개의 스레드를 나란히 돌릴 수 있는지는 구현이 정합니다.

Python 의 os.cpu_count

같은 물음을 언어 표준 라이브러리에서도 던질 수 있습니다. os.cpu_count() 는 시스템의 논리 CPU 개수를 돌려줍니다. 알아내지 못하면 None 을 돌려줍니다. 지금 프로세스의 호출 스레드가 실제로 쓸 수 있는 논리 CPU 개수는 process_cpu_count() 로 얻습니다.

관련 항목

CPU를 이루는 구성 요소

명령어 집합 · 레지스터 · 프로그램 카운터 · 파이프라인 · 분기 예측 · MMU(Memory Management Unit) · 코어 · 하이퍼스레딩 · 클럭 · 어셈블리어

명령어와 데이터를 함께 담는 저장소

메모리 · 메모리 계층 · CPU 캐시

한 명령어가 거치는 처리 단계

인출 · 해독 · 실행 · 결과 쓰기

실행 흐름을 꺾고 되돌리는 사건과 장치

인터럽트 · 예외 · 트랩 · 컨텍스트 스위칭 · 커널 모드와 유저 모드 · 스케줄러 · 스케줄링

여러 코어가 메모리를 함께 볼 때 지키는 성질

원자적 연산 · 캐시 일관성 · 메모리 계층

운영체제가 CPU를 세고 나누는 방식

프로세스 · 스레드 · cgroup · sysfs · CPU 사용률 · CPU 시간 · 하드웨어 핫플러그 · 커널 · 운영체제 · Linux · 인덱스

CPU 개수를 프로그램이 묻는 창구

POSIX · sysconf · Python · os.cpu_count · process_cpu_count · 표준 라이브러리

CPU 개념이 비롯된 배경

폰 노이만 구조 · EDVAC · ENIAC

CPU와 맞세워지는 처리장치

GPU(Graphics Processing Unit)

CPU 동작을 규정하는 명령어 집합 표준

RISC-V · RV32I · hart

CPU를 실제로 구현하는 회사

Intel · ARM · AMD

다른 이름: Central Processing Unit · 중앙처리장치 · 프로세서