Exceptions : CPU 내부 동작으로부터 예외사항이 일어나는 것, 논리, 산술 연산에서 일어날 수 있음
Interrupts : 외부 I/O controller(CPU가 아닌 외부장치. OS 등..)로부터 발생
Trap(=Software Interrupt)
우리는 이러한 예외사항이 발생 시 성능 저하를 피할 수 없으므로 성능 저하를 최소화하면서 처리할 방법이 필요하다
하드웨어는 이러한 예외사항을 처리하는 소프트웨어를 위해 예외에 대한 다음의 정보들을 저장한다.
예외 발생 시 핸들러의 동작은 다음과 같다.
다음의 이유로 exception은 control hazard의 또 다른 유형이다.
overflow가 일어났는지는 EX stage에서 판단할 수 있다.
add명령어의 EX stage에서 overflow가 발생했다고 생각해보자.
add X1, X2, X1
- X1에 잘못된 값이 쓰여지는 것을 막는다.
- 이전 명령들은 제대로 완수될 수 있도록 한다.
- add 명령어와 이후 명령어들을 비운다(flush).
- ESR와 ELR의 값을 세팅한다.
- handler로 제어권을 넘긴다(handler가 처리할 수 있도록 jump).
mispredict branch가 발생 시 실행하는 루틴과 비슷하다.
예외가 발생하면 발생이후 stage(exception이 일어나기 전에 실행되던 명령어)는 그대로 실행해주고, 이전 stage는 bubble 처리(nop)를 해주어야한다.
만약 예외가 발생한 명령어가 재실행 가능하다면
ALU 연산의 결과를 보고 예외를 판단해야하기 때문에 ESR, ELR는 EX단계에 위치한다.
돌아가야될 위치가 저장된 ELR에는 PC값의 싱크를 맞추기 위해 파이프라인 레지스터에서 PC값을 가져온다.
다음과 같이 ADD명령어에서 예외가 발생했다면?
현재 instruction과 이후 instruction들 모두 flush
nop로 flush(bubble), 그리고 handler로 jump한다.
따라서 예외가 발생한 이후의 명령어는 bubble처리, 이전의 명령어는 그대로 흘러가게 nop 처리를 한다.
CPU를 어떻게 빠르게 할 수 있을까?
여러 개의 명령어를 병렬적으로 실행할 수 있으면 된다
이것에 대한 척도가 ILP이다.
ILP를 증가시키는 방법
- pipeline stage를 증가시키면 됨
- 각각의 stage마다 하는 일이 적어지면 clock cycle이 짧아져 성능이 향상됨
- 그러나 hazard와 같은 예외를 처리하기 위해서 더 많은 하드웨어 리소스와 power 소모량이 기하급수적으로 늘어나기 때문에 궁극적인 해결책은 될 수 없다
- 여러 개의 명령어를 동시에 실행 (issue: instruction fetch 과정) -> mutiple issue라고도 부른다
- 여러 개의 파이프라인을 만들어, 각 cycle마다 실행하는 명령어가 여러 개가 될 수 있음
어떤 명령어가 어느 cycle에서 실행할지 이미 결정이 되어 있는 것(컴파일러가 runtime 전에 결정)
컴파일러가 instruction들이 함께 issue될 수 있도록 묶어줌(group).
issue slots으로 패키지화함
컴파일러가 hazards를 감지하고 회피시켜 준다
컴파일러가 명령어의 그룹을 issue packet으로 만듦
issue packet이 매우 긴 명령어처럼 보이게 됨. 이런 아키텍쳐를 Very Long Instruction Word(VLIW) 라고 부름
VLIW
만약 최대 6개의 명령어를 함께 실행할거라면 32비트짜리 6개 붙여서 하나의 명령어로 보며, 데이터 타입에 따라 묶어 하드웨어 연산의 복잡도를 낮추며 데이터 타입에 따라 연산 속도가 다를 수 있다.
LEGv8에서는 서로 다른 타입의 명령어들을 2개씩 묶어 64비트의 각 명령어를 수행할 수 있다
서로 다른 타입의 명령어로 묶는 이유는 연산에 필요한 하드웨어 리소스를 줄이기 위해서이다.
명령어를 2개씩 묶어 수행할 경우 ALU와 sign-extend, 결과 데이터를 전달하는 path를 1개씩 추가하면된다
검은색 ALU : 산술 논리 연산 ALU
파란색 ALU : 메모리 address계산 ALU
Loop를 펼친다라고 생각하면 된다.
Loop를 펼침으로써 그룹핑지어 동시에 실행할 수 있는 명령어의 개수를 늘릴 수 있다(가능성을 늘린다)
데이터 종속성 문제가 있기에 펼친 개수에 비례해서 속도가 증가하는 것은 아니다.
그러나 가짜 dependency인 anti-dependencies가 존재한다.
왼쪽의 코드를 Loop Unrolling을 통해 오른쪽으로 바꾸었다.
그 결과 IPC가 1.2 -> 1.88로 증가함을 볼 수 있다