파이프라이닝과 관련된 내용을 간단히 정리해본다.
◆ 파이프라이닝
간단히 말해서 명령어를 병렬로 처리한다. 다시 말해 동시에 여러 개의 명령어를 실행하는 것이다.
명령어 동작 속도를 단축시키지는 않는다. 단지 병렬처리할 뿐이다. 시간당 처리량을 늘리는 것이다.
단일 사이클과 대비된다.
◆ 파이프라이닝 종류
컴퓨터에서 사용되는 두 가지 파이프라인은 다음과 같다.
* Arithmetic pipeline : 연산작업을 pipeline을 통해 수행하는 건데, 상용 컴퓨터에서는 이렇게 하지 않는다고 한다.
* Insturction pipeline : 명령어를 pipeline을 통해 수행하는 것이다. 상용 컴퓨터에서 모두 이 방식으로 명령어를 병렬처리한다.
여기서 Arithmetic pipeline은 다루지 않는다.
◆ 파이프라이닝 성능
파이프라이닝과 관련하여 성능의 지표가 되는 Speedup이라는 용어가 있다.
Speedup이란?
간단히 말해서, 파이프라인을 사용하지 않은 경우 시간 대비 파이프라인을 사용한 경우의 시간이다.
식은 아래와 같다.
사실 명령어 수인 n은 무한정 크게 된다. n이 커질수록 S는 k에 접근한다. 즉, pipeline의 segment 수에 따라 성능이 달라진다. 이 segment 수는 이론적인 최대 speed up이다. 하지만 이 최대 speed up은 이론적일 뿐, 실상은 얻을 수 없다.
이해 plus :
위 식을 좀 더 이해해보자.
* task가 한개 (n=1)이면 ktp
* task가 두개 (n=2)이면 ktp + tp
* task가 세개 (n=3)이면 ktp + tp + tp
이런 식으로 늘어난다.
이 말은 즉, 하나의 task를 처리하는데 한clock밖에 안 걸린다는 것이다. 이전 task를 수행하는 단계에서 이번 task도 어떤 단계를 수행하는 중이기 때문이다. 즉, 병렬처리하기 때문이다.
바로 위에서, 최대 speed up인 segment 개수 k는 이론적일 뿐이라고 했는데,
최대 speed up을 얻을 수 없는 이유는 뭘까?
: 전달시간이 가장 긴 segment의 지연 시간에 맞추어 clock 사이클이 정해진다.
그리고, 다음 segment로 넘어가기 위해 상태저장하는 register를 사용하는데 이 레지스터 사용에 의한 오버헤드가 있기 때문에 최대 speed up은 이론적일 뿐이다.
이와 관련해서 상용 컴퓨터들이 instruction 사이클을 돌릴 때 speed up이 어느 정도로 나오는지 간단히 언급하겠다.
요즘 프로세서는 instruction 사이클이 보통 6개(혹은 7개)로 나누어져있다.
1. 명령어 fetch
2. decoding
3. effective address 계산
4. opperand를 읽어와 fetch
5. execute
6. store the result
즉 6 segment를 가진다. 만약 파이프라인을 이용하지 않고 이 명령어를 sequential하게 수행하면 6 clock이 걸린다. 만약 1GHz 컴퓨터라고 가정하면 instruction 수행에 6ns 걸린다. 만약 6 segment 파이프라인을 사용해서 명령어를 처리한다면 하나의 명령어를 처리하는데 이상적으로 1ns가 걸린다. 역시 이 6배 빠르다는 것은 이상적인 계산일 뿐이고, 실제로 결과적으로는 3배정도 나온다고 한다. 그 이유는 위에서 언급한 최대 speed up을 얻을 수 없는 이유를 보면 된다.
그리고 이어서, instruction pipeline의 문제점도 존재한다.
◆ instruction pipeline에서의 문제점
* 각 segment의 수행시간이 다르다. execute 단계의 시간이 가장 오래 걸리기 때문에, clock 속도를 제일 오래 걸리는 segment인 execute에 맞추어 주어야 한다. 사실 이는 instruction 파이프라인 뿐만 아니라 모든 파이프라인에서의 문제점이다.
* instruction에 따라서 일부 단계(특정 segment)는 스킵될 수 있다. (지난 번에 16비트 컴퓨터 설계에서 배웠듯이 memory-reference instruction은 effective address 계산 단계를 거치지만, 이외의 명령어들은 이 단계를 건너뛴다)
Pipeline의 Hazard
▶ Structural Hazard : 파이프라인 구조로 인한 문제
resource conflict 문제
▶ Data Hazard : Data에 대한 sequence가 엇갈리며 발생하는 문제
data dependence confilct 문제
▶ Control Hazard
branch instruction의 문제
.
.
Structural Hazard,
resource conflict가 발생 : 메모리 access는 한 순간에 하나의 레지스터만 할 수 있다고 했다. (BUS 배웠을 때를 생각하자. BUS의 조건: 메모리 접근시 bus master는 단 하나의 레지스터만 될 수 있다는 그 내용) 그러나 명령어를 병렬처리하는중에 동시에 두 개의 segment에서 메모리에 access라고 한다면 resource conflict가 발생한다. (부연설명: 위의 6단계 instruction cycle을 보면 1단계에서 '메모리로부터' 명령어를 fetch하고, 4단계에서 '메모리로부터' opperand를 fetch한다. 만약 어쩌다 이 두 segment 처리가 중첩되면 resource confilct라는 것이다) 이 문제는 어떻게 해결할까?
Resource conflict는 다양한 방법으로 해결할 수 있는데, 간단한 이해를 위해 그중 하나만 정리하겠다.
추가적인 하드웨어인 캐시메모리를 이용해보자.
instruction cache와 data cache에 명령자체와 데이터를 따로 분리하여 저장하자. 하나의 segment는 insturction cache에 access하게 하고, 다른 segment는 data cache로 access하게 하면 resource confilt를 생기지 않게 할 수 있다. (리소스가 분리되어있다)
Data Hazard,
* data dependence conflict : 참고링크
치명적인 hazard다. 예를 들면 r1 + r2 연산보다 r1 = a1 * a2가 (레지스터나 메모리에)저장되는 것이 선행되어야 한다. 하지만 a1 * a2연산이 만약 store단계를 수행중인데, r1+r2가 execute중이라면 data dependency 문제가 발생한다. 즉 어떤 명령어가 완전히 store되고 cycle을 나간 뒤에, 그와 연관된 어떤 명령어가 정상적으로 수행될 수 있다. 이 문제는 어떻게 해결할까?
이 data hazard도 다양한 방식으로 해결할 수 있는데, 일단 하나만 정리하겠다.
delayed load 삽입 방식 (Freezing the pipeline) (stall)
하드웨어적으로 no-operation(nop) instruction이라는 더미 명령을 통해 한 클락을 진전시켜 data dependency를 해소한다.
Control Hazard,
* branch instruction의 문제 : 갑자기 어떤 명령어로 branch하게되면 PC가 변하면서 이전까지 파이프라인에 뒤따라오던 명령어들을 다 무산시키고 branch한 명령어를 수행해야 한다. branch를 수행하면 일단 현재 주소를 저장해두고 브랜치대상 PC로 가서 명령 처리 후 원래 주소로 돌아온다. 그럼 원래 많은 명령이 진행되던 파이프라인은 stall이 발생하여 당연히 성능 문제가 생긴다. 그럼 이 브랜치명령의 문제는 어떻게 해결할까?
이 control hazard도 다양한 방식으로 해결할 수 있지만 일단 하나만 정리하겠다.
delayed branch 방식 사용! - 다양한 단점이 존재하기는 하다.
컴파일러가 branch명령을 적절한 위치에 재위치시켜서, conditional branch의 조건을 판단할 때 다른 하나 이상의 명령어를 진전시킬 수 있게 한다. 그러면 branch의 조건을 따지는 동안 stall되는 문제를 방지할 수 있다. 즉, conditional branch에 대한 영향을 최소화할 수 있다. 이 작업은 컴파일러의 최적화 능력에 따른다.
만약 branch 조건문이 참으로 나와서 점프해야 한다면, 점프한 곳에 있는 명령어를 실행해야 하므로 원래 실행해야 했을 명령어를 nop으로 쭉 밀어버린다.
이렇게 파이프라이닝에 관련된 내용을 예제 없이 가볍게 정리해보았다.
+ 잘못된 내용이 있으면 코멘트 남겨주세요. 감사합니다~!
'컴퓨터구조 & OS' 카테고리의 다른 글
도커는 호스트 시스템에 영향을 받는다 2편 - tensorflow 관련 ImportError (1) | 2023.07.05 |
---|---|
도커는 호스트 시스템에 영향을 받는다 1편 - platform 속성? amd64와 arm64/v8 (CPU 아키텍처) (2) | 2023.07.05 |
[컴퓨터구조] 16비트 컴퓨터에서 프로그래밍하기 - Assembler가 어셈블리 프로그램을 기계어로 번역하는 과정 (0) | 2021.10.18 |
[컴퓨터구조] 16비트 컴퓨터에서 프로그래밍 하기 | assembly로 쓰여진 프로그램의 구조 (0) | 2021.10.18 |
[컴퓨터구조] 16비트 컴퓨터 설계하기 - instruction 실행의 종합적인 흐름 | flowchart (0) | 2021.10.16 |