Skip to content

Latest commit

 

History

History
231 lines (143 loc) · 16.2 KB

File metadata and controls

231 lines (143 loc) · 16.2 KB

CPU 구조 및 동작 프로세스 정리

CPU 주요 구성 요소

  • ALU (Arithmetic Logic Unit) : 계산기 역할. 산술 및 논리 연산 수행.
  • 레지스터 (Register) : CPU 내부의 매우 빠른 저장 장치.(캐시들보다 당연히 더 빠름)
    • 예: 프로그램 카운터(PC)도 레지스터 중 하나.
    • 멀티코어 환경에서는 코어마다 독립적으로 존재하며, 가장 빠르고 가까운 저장소.
  • 제어장치 (Control Unit) : 명령어 해석 및 제어신호 전송 담당. ALU, 메모리 등 하드웨어에 신호를 보냄.
  • 캐시 (Cache) : 레지스터 다음 단계의 저장 장치로, 메모리 접근보다 빠름. L1 -> L2 -> L3 순으로 속도가 느려지고 용량이 커질 수 있다.
    • L1, L2 캐시: 각 코어별로 존재함.
    • L3 캐시: 모든 코어가 공유하는 캐시로, CPU의 후방에 위치한 마지막 캐시 단계.

멀티 코어, 멀티 스레드라면?

구성 요소 구조 및 개수 (8코어 16스레드 기준)
ALU 각 코어마다 최소 1개 이상 존재 → 총 8개 이상 (일반적으로 2~4개/코어)
레지스터 각 코어마다 독립된 레지스터 집합 보유 → 총 8세트
제어장치 각 코어에 하나씩 존재 → 총 8개
L1 캐시 보통 코어마다 L1d(데이터) + L1i(명령어) → 총 16개 이상
L2 캐시 일반적으로 코어별로 존재 → 총 8개
L3 캐시 전체 코어가 공유 → 1개 (CPU 전체에서 공유하는 큰 캐시)

오늘날에는 멀티코어 CPU가 매우 흔하다.(사실상 전체 제품에 대해 그렇다.)

흔히 컴퓨터 구조를 공부할 때 배우는 명령어를 실행하는 부품(ALU, 제어장치, 레지스터..로의 한 세트)을 우리는 코어라고 하며 CPU제품의 코어 수만큼 명령어를 실행하는 부품(코어)를 사용하게 되는 것이다.

2025년 기준 약 3000여만원의 최고 성능을 자랑하는 서버용 AMD CPU(AMD EPYC 9655P)의 경우 96코어 192스레드라는 엄청난 양의 코어를 가진다.

CPU의 쓰레드는 무엇인가?

스레드란 실행 흐름의 단위라고 정의된다.

헷갈리는 지점은 OS를 공부할 때도, 자바를 공부할 때도, 하드웨어인 CPU를 공부할 때도 쓰레드란 용어가 등장한다는 것이다.

우선 쓰레드는 개념적 이해를 위해 하드웨어적 스레드소프트웨어적 스레드로 나눌 수 있다.

하드웨어 쓰레드는 하나의 코어가 동시에 처리하는 기계어 명령어 단위로 이해해야한다.

즉 CPU가 명령어를 처리할 때 1코어당 2스레드라면 하나의 코어에서 동시에 두 개를 처리할 수 있다는 것이다.

CPU가 8코어 16스레드라면 8코어가 16개의 명령어를 동시에 처리할 수 있다는 것이다.

Intel사의 경우 이렇게 코어보다 더 많은 스레드를 두어 명령어를 쓰레드 수만큼 동시에 처리할 수 있는데,

이러한 기술을 하이퍼 스레딩이라고 한다.

하지만 소프트웨어 스레드 1개에 존재하는 번역된 순차적인 기계어 명령어들이 8코어로 나뉘어 배정되지는 않는다.

더해서 특정 코어에 배정되는 것이 아니라, 특정 코어의 특정 스레드에 배정되어 실행된다.

만약 기계어 명령어를 이쪽 하드웨어 스레드에서도, 저쪽 하드웨어 스레드에서도 처리된다면 순차성을 확립하는데 어려움이 있기 때문이다.

소프트웨어 스레드의 경우 하나의 프로그램에서 독립적으로 실행되는 단위이다.

소프트웨어의 스레드는 그렇기에 하드웨어 스레드보다 훨씬 많이 생성될 수 있으며 하드웨어 스레드는 OS에 지휘에 따라 소프트웨어의 스레드 즉 독립된 작업들에서 뿜어져나오는 기계어 명령어들을 8코어16스레드로 OS가 부여한 시간에 따라 빠르게 처리하는 것이다.

시분할 기법을 통해 1코어 1스레드 CPU로도 여러 소프트웨어 스레드를 처리할 수 있다는 것을 알 수 있다.

압도적인 속도로 마치 동시에 실행되는 것 처럼 보이게 하는 것이다.

CPU 코어 하나를 논리적 분리로 하여금 코어가 동시에 두 일을 할 수있도록 구성한 이유는 하나의 소프트웨어 스레드를 하나의 코어에서 실행할 때 여러 유닛들이 동시에 열심히 활성화되지 않기 때문이다.

누군가는(레지스터 연관 기능이 동작중이라면) 쉬게 되는데, 이때는 ALU연산을 수행할 수 있을 것이다.

그렇기에 논리적 분할로 하여금 두 작업을 하나의 코어가 동시에 처리하는 것정도는 효율성을 챙길 수 있다는 것이다.

CPU 코어들 내부의 여러 유닛들(레지스터, ALU, 제어장치...)은 코어당 하나의 쓰레드로는 전부 가동되지 않기 때문에, 즉 가장 바쁠 때 코어가 놀게하지 않기 위해 코어 내부에 논리적 다중 스레드 구조를 만들어 코어가 최대 바쁘게 돌아갈 때 유닛의 활용도를 최대한으로 올리기 위함이다.

ALU(계산 회로)

입력 관점에서 ALU는 레지스터로부터 피연산자를 받아들이고, 제어장치로부터 제어신호를 받아들인다.

출력 관점에서 ALU는 계산 결괏값을 다시 레지스터에 보내고, 연산결과에 대한 부가정보를 플래그란 형태로 플래그 레지스터에 보낸다.

부가정보에는 예를 들어 양수, 음수가 있다.(캐리 발생 여부, 오버플로우 여부 또한 포함될 수 있다.)

왜 결괏값에 양,음수를 포함하지 않고 플래그를 활용하는가?

예를 들어 결과가 음수이면 점프하라는 명령을 처리할 때, 매번 결과 값의 최상위 비트를 꺼내서 비교하는 건 귀찮고 느리다.

제어장치

제어장치는 메인보드에 있는 클럭 제너레이터에서 생성된 클럭 신호를 클럭 주기에 따라 받고, 명령어 레지스터(Instruction Register, IR)로부터 해석할 명령어를 받게 된다.

또한 입출력 장치를 비롯한 다른 하드웨어에서의 제어버스(메인보드 제어신호 전용회로)를 통해 제어신호를 받기도 한다.

제어장치는 이를 해석하여 제어신호들을 보낸다. 이 제어신호들은 CPU내부(ALU, 레지스터)로도 외부로도 갈 수 있다.(메모리, 입출력장치)

CPU는 PC(프로그램 카운터)에 들어있는 명령어 주소를 통해 명령어를 메모리나 캐시로부터 가져온다.

이것은 명령어 사이클의 가장 첫번째로 명령어 인출(Fetch)에 해당한다.

제어장치는 명령어 인출(Fetch) 그 다음 진행되는 명령어 해석(Decode)를 수행하는데,

만약 x에 t을 더하라 와 같은 명령어를 해석한다고 가정하면 우리는 x, t를 인출해서 레지스터에 넣어야한다.

이러한 과정또한 제어장치가 수행한다.

즉 명령어 해석과정에서 다시 인출이 진행될 수 도 있다.

x, t가 레지스터에 잘 안착했다면 제어장치는 연산장치들에 신호를 보내어 연산을 수행시킨다.

클럭

우리가 흔히 CPU 사양에서 언급하는 클럭은 이 제어장치와 연관이 깊다.

제어장치의 동작은 이 클럭 신호에 맞추어 동작한다.

만약 5200MHz 클럭을 가진 CPU라면 그리고 그 CPU가 8코어라면 각 코어마다의 제어장치들은 1초에 52억번(클럭 주기) 명령을 실행할 수 있는 기회를 가진다.

컴덕들이 즐겨 하는 CPU 오버클럭이란 CPU 코어의 최대 클럭을 제조사가 설계한 것보다 최대 클럭을 의도적으로 더 높게 설정하여 CPU의 처리량을 늘리려는 목적이다.

모니터링 시스템에서 현재 내 코어가 어떤 벤치마크 프로그램에 의해 모든 코어가 5200MHz으로 가동된다면 이는 1초에 52억번 명령을 수행할 준비중이라는 것이다.

예시의 상황으로, 평소에는 1400MHz로 돌고있다. 그렇다는 것은 코어가 1초에 14억번 명령을 수행할 수 있는 기회를 가지는 상황인데,

참고로 1400MHz라는 것이 1초에 14억번 명령 수행을 보장하지는 않는다.

그만큼의 명령어 실행 가능 속도를 가진다는 뜻이며, 대부분의 상황에서 명령어가 이 기회를 꽉차게 부여잡아 1400MHz에 대응하여 14억번을 수행하지는 않을 것이다.

14억번 수행이 필요한 경우라면 아마 CPU는 더 높은 MHz의 클럭으로 올라갈 것이다.(최대 클럭이 허용한다면)

코어는 최대 클럭으로 항상 동작하지 않고 CPU는 동적으로 클럭을 구성한다.

항상 5200MHz로 돌게한다면 항상 빠른 클럭에 의한 높은 성능을 유지할 수 있을 것이다.

하지만 cpu의 최대클럭까지 올리기 위해서는 높은 전압이 필요하다. 높은 전압은 높은 온도를 가져온다.

사실 cpu 제품에 제조사가 의도적으로 최대 클럭이란 제한을 두는 이유는 온도 때문이다.

지나친 온도는 CPU나 메인보드에 손상을 줄 수 있어 제조사들은 안전한 가이드라인으로 최대클럭&최대온도를 두고 지나친 온도상승이 이루어지면 클럭을 강제로 내리고 전압을 내려 성능을 포기하고 안정성을 택한다.

그렇기에 제조사가 설정한 한계온도까지 밀어붙이는 행위는 좋지 않다.

클럭이 동적으로 바뀌는 원인은 OS가 아니라 CPU 자신만의 로직이다. 전력과 발열 상황에 따라 클럭을 조절하며 CPU 내부의 성능 카운터인 PMU에 의해 부하에 대한 판단을 할 수 있다.

레지스터 (Register)

레지스터는 CPU 내부에 존재하는 가장 빠른 저장 장치이며,
모든 연산과 명령 실행은 이 레지스터를 중심으로 진행된다.

속도 면에서는 캐시보다도 빠르고,
위치상으로는 ALU나 제어장치 바로 옆에 있어 데이터 접근 시간이 매우 짧다.

  • 초고속, 초소용량 저장 공간 (보통 수십~수백 개, 총 용량은 수백 바이트 수준)
  • 특정 용도에 따라 이름과 기능이 다름
  • 각 코어마다 독립적으로 존재 (멀티코어 CPU라면 레지스터 세트도 코어마다 있음)

CPU는 메모리보다 레지스터에서 데이터를 읽고 쓰는 속도가 훨씬 빠르기 때문에,
모든 계산은 가능하면 레지스터에 값을 올려놓고 처리하려고 한다.

실제로 명령어 대부분은 레지스터 간 이동이나 연산을 전제로 한다.

최신 x86-64 CPU 코어 기준으로 보면 코어당 대략 550-620개 정도의 레지스터가 존재한다고 볼 수 있다.

주요 레지스터 종류

레지스터 설명
일반 목적 레지스터 (General Purpose Register) 데이터 연산에 사용되는 범용 저장소 (예: x86에서 eax, ebx 등)
명령어 레지스터 (Instruction Register, IR) 현재 실행 중인 명령어 자체를 저장
프로그램 카운터 (Program Counter, PC) 다음에 실행할 명령어의 메모리 주소를 가리킴
스택 포인터 (Stack Pointer, SP) 현재 스택의 최상단 위치를 가리킴
상태 레지스터 / 플래그 레지스터 (Flags Register) ALU 결과에 대한 상태(예: 0인지, 음수인지, 캐리 발생 여부 등)를 저장
인덱스/포인터 레지스터 메모리 주소 계산, 배열 인덱싱 등에 사용됨

CPU는 메모리보다 레지스터에서 데이터를 읽고 쓰는 속도가 훨씬 빠르기 때문에,
모든 계산은 가능하면 레지스터에 값을 올려놓고 처리하려고 한다.
실제로 명령어 대부분은 레지스터 간 이동이나 연산을 전제로 한다.

CPU 명령어 실행 프로세스 (Instruction Cycle)

  1. Program Counter(PC)를 확인
    • 제어장치가 PC를 참조하여 다음 실행할 명령어의 메모리 주소 확인
  2. 명령어 Fetch 시도
    • 우선 L1 I-Cache에서 해당 주소의 명령어를 찾음
    • L1에 없으면 L2 → L3 → RAM 순으로 탐색
  3. 명령어를 레지스터에 로드
  4. 제어장치가 명령어를 해석(Decode)
    • 예: 이 명령어는 덧셈인가? 점프인가?
  5. 명령어 실행
    • ALU를 호출하거나, 메모리 접근 등 해당 동작 수행
  6. Program Counter를 업데이트
    • 일반적으로 +1 증가하거나, 점프 명령일 경우 새 주소로 설정
  7. 다음 명령어로 이동

해석 및 의문지점

CPU 제어장치는 자신의 작업 흐름을 PC(Program Counter) 에 따라 진행하는 구조이다. 하지만 PC의 값은 운영체제가 주도적으로 제어한다.

  • 운영체제는 CPU와의 유일한 접점인 PC를 통해 CPU의 명령 실행 순서를 조율함.
  • CPU는 PC가 가리키는 주소대로 명령어를 해석하고 실행하는 순수한 실행 장치일 뿐이다.
  • 결과적으로 CPU는 OS가 넣어준 계획대로 동작하는 하드웨어 처리기이며, CPU는 계획을 짜지 않고, 오로지 실행만 한다는 점에서 일종의 생각없이 일하는 '노예'처럼 동작한다고 볼 수 있다.

이러한 구조는 컨텍스트 스위칭(context switching)과도 연결된다.

운영체제가 각 프로세스의 PC 값을 저장하고, CPU에 할당될 때 해당 PC 값을 복원함으로써 프로세스의 명령 흐름을 제어할 수 있다.

여기서 자연스럽게 나올 수 있는 질문이, “그럼 여러 쓰레드 작업을 GPU로 돌리면 더 빠른 거 아님?”인데, 사실 그건 틀린 얘기다.

GPU는 똑같은 일을 수천 개의 데이터에 동시에 반복할 때 효용적인 도구지, 수많은 서로 다른 일을 수행하는 것에는 안 어울린다.

CPU 스레드는 각자 독립적인 작업 흐름과 다양한 조건문, 분기처리를 수행하는데, GPU는 이런 복잡하고 가변적인 실행 경로를 효율적으로 처리하기 어려운 구조이다.

결국 일반적인 스레드 실행이나 OS 수준의 작업은 현재로서는 CPU가 가장 적합하다. GPU는 병렬 처리의 강자이지만, 그 강점은 단순하고 반복적인 연산에 최적화되어 있고, 운영체제의 스레드 제어 같은 유연하고 복잡한 작업에는 적합하지 않은 구조이다.

즉 질문에 포함된 여러 쓰레드 작업은 GPU가 소화할 수 없는 복잡한 작업이라는 것이다.

GPU는 그렇기에 화면 출력과 같은 같은 작업 고반복에 사용된다.

왜 모니터 화면 출력은 같은 작업 고반복에 해당할까?

1920 x 1080 FHD 스펙의 144hz를 지원하는 모니터를 사용한다고 가정해보자.

1920 x 1080, 144Hz라면: 1920 × 1080 × 144 = 약 298,598,400개

즉 1초에 약 3억 개의 픽셀을 계산해서 화면에 뿌려야한다.

분명 픽셀마다 다른 RGB를 보여주고 같은 픽셀의 다음 RGB값이 다르다.

GPU의 같은 작업 고반복이라는 특징에서 같은 작업의 뜻은, GPU 연산이 항상 같은 결과를 내보내는 것은 아니지만 하지만 연산과정은 동일하다는 것에 있다.

GPU는 같은 함수를 3억번 호출해야할 때 이를 하나씩 고속으로 순차적으로 처리하는 것이 아니라 동시에 여러개를 한번에 처리하는 것이다.


정리

  • CPU는 ALU, 레지스터, 캐시, 제어장치 등으로 구성되어 있고, 명령어 실행은 명확한 fetch-decode-execute 흐름을 따른다.
  • L1/L2는 코어별로, L3는 코어공유로 존재하며, AMD의 X3D 시리즈는 L3 캐시를 물리적으로 확장해 성능을 끌어올린다.
  • 명령어 흐름의 중심은 PC이며, 그 PC조차도 운영체제가 관리함으로써 전체 프로그램 흐름은 OS가 주도한다.
  • CPU는 명령어 해석과 실행에만 충실한 구조다.