벤치리뷰·뉴스·정보/아키텍처·정보분석

[분석정보] 명령의 실행 순서를 바꿔 고속화 하는 아웃 오브 오더

tware 2010. 9. 27. 22:00

 

슈퍼 스칼라와 아웃 오브 오더는 세트 기술

 슈퍼 스칼라 다음에 소개하는 기술은 아웃 오브 오더이다. 아웃 오브 오더는 슈퍼 스칼라을 전제로 하는 기술이다. 아웃 오브 오더 없이 슈퍼 스칼라는 있지만, 슈퍼 스칼라 없이 아웃 오브 오더는 있을 수 없다 (이말은 의미가 없다) 때문에 현실적으로 슈퍼 스칼라 가정의 기술이라 생각해도 좋을 것이다.

 아웃 오브 오더의 언어의 의미는 "흐트리다(어지럽히다), 미치다(돌았다), 고장났다"로 미국에서 고장난 자판기 같은 것에 "Out of order" 라고 벽보가 있거나 한다. 물론 여기서 다루는 것은 다른 의미. "흐트리다, 미치다 '에 가까운데, 이를테면 "명령의 실행 순서를 바꾸어 버리는 "것이다. 이렇게 쓰면 "그러면 이전의 명령어의 정렬과 무엇이 다른가? "라고 물을것 같은데, 실은 "반은" 같은 것이다.

 아웃 오브 오더는 위에 쓴대로 "주어진 명령을 한번 확장하고 종속성이 없는 순서로 순차적으로 실행"방식이다. 이전 "명령의 정렬"로 설명했던 다음 정렬 예가 이미 아웃 오브 오더 인 것이다.

명령 1 정렬 전
정렬 후
 명령 2 R1 = Data1
R1 = Data1
 명령 3 R2 = Data2
R2 = Data2
 명령 4 R3 = R1 + R2
R4 = Data3
 명령 5  R4 = Data3
R5 = Data4
 명령 6  R5 = Data4
 R3 = R1 + R2
 명령 7  R6 = R4 + R5
 R6 = R4 + R5

 

다시 말하면 본래의 명령의 정렬 순서를 CPU 내부에서 바꿔넣게 된다.이에 의한 효과는 전회 말했던대로 매우 크다.

 그럼, 전회에는 아웃 오브 오더 에는 너무 적극적으로 손대지 않았던 것도 있고 전통적인 파이프 라인의 연장인 구도를 나타 냈지만, 본래의 아웃 오브 오더 파이프 라인은 [그림 1]과 같다. 전회와 달리 "Re-Order Buffer" 라고 부르는 것이 새롭게 출현하고 있는 것으로, 이것이 아웃 오브 오더 간(간장.내부,내장) 부분이다.

 

<-명령 1차 캐시                                      데이터 1차 캐시->

 

우선 명령 캐시에서 Fetch를 거쳐 거두어진 명령어는 Decode로 해석된다. 여기까지 "인 오더"즉 어디까지나 거두어진 순서대로 처리된다. 해석이 끝난 명령어는 일단 스케줄러에 들어간다. 여기에서 명령의 정렬이 행해진다. 이 예로 말하면 왼쪽의 4명령은 우선 처리되고 오른쪽의 2 명령은 뒤로 밀린다.

 

우선 처리
후 처리
R1 = Data1
R3 = R1 + R2
R2 = Data2
 R6 = R4 + R5
R4 = Data3
 
R5 = Data4
 

 

그런데, 전회의 설명에서 "이 결과가 Writeback 된다" 라고 돌연 정리했지만, 실제로는 좀 더 복잡하다. 연산의 결과가 정말 메모리에 넣어지는 경우에 있으면, 여기서 재기록에 들어간다. 그렇지만 위의 예에서는 R1/R2/R4/R5 라는 레지스터에 결과가 저장되고, 게다가 그 값은 다음의 명령으로 이용되는 만큼 이를 일일이 캐시로 재기록 하게 되는 것은 시간적으로 충분치 않다. 여기서 레지스터로 재기록은 Re-Order Buffer에 행한다.

 왜 이것이 Re-Order Buffer 라고 부르냐 하면, 이것도 전회 (슈퍼 스칼라에 의한 고속화) 설명한 Register Renaming에 관계해 있다. 전회의 예 에서는 표의 왼쪽 열을 오른쪽 열로 변환하여 실행한다고 설명했다.

 

  변환 전
 변환 후
 명령 1
 R1 = Data1
R101 = Data1
 명령 2
 R2 = Data2
R102 = Data2
 명령 3
 R3 = R1 + R2
R3 = R101 + R102
 명령 4
 R1 = Data3
 R103 = Data3
 명령 5
 R2 = Data4
 R104 = Data4
 명령 6
 R4 = R1 + R2
 R4 = R103 + R104

 

사실은 이것도 다소 설명을 생략한 것이다.Register Renaming을 제대로 하면, 내부적으로 다음과 같이 등록되는 것이 보통이다.

 

명령 1 R101 = Data1
명령 2 R102 = Data2
명령 3 R103 = Data3
명령 4 R104 = Data4
명령 5 R3 = R105 + R106 (= R101 + R102)
명령 6 R4 = R107 + R108 (= R103 + R104)

 

Re-Order Buffer는 기본적으로 하나의 명령어에 대해 하나씩 결과를 저장하는 신규 엔트리가 만들어지고 거기에 결과가 할당되는 방법이다. 그때문에 명령 5와 명령 6은 "명령 1 ~ 4가 완료 되는 것을 기다리는"것이 아니라 "R105 ~ R108이 채워져 이용 가능이 됨을 기다린다."라는 형태로 스케줄러에서 대기한다.

 한편, 명령 1 ~ 4에 의해 R101 ~ R104이 채워지면 이것이 명령 5,6은 R105 ~ R108에 값이 채워진 것으로 보여지는 구조다. 이러한 느낌으로 "레지스터 이름이 바뀐다"는 것으로, Re-Order Buffer 라는 이름이 되었다.

 

이야기를 아웃 오브 오더로 되돌린다. 아웃 오브 오더라고 한마디로 말하지만, 실제로는 2 종류가 있다.

명령 발행에 인 오더 / 아웃 오브 오더
명령 완료에 인 오더 / 아웃 오브 오더


 아웃 오브 오더 발행은 스케줄러에서 순서를 바꿔넣어 명령을 발행하는 것을 의미하며, 아웃 오브 오더 완료는 ALU 라든지 Load / Store 라든지의 출력이 본래 명령의 줄과 다른 순서로 Re- Order Buffer에 들어가는 것을 의미한다.

 이 조합도 여러가지 있다. 인텔의 "P​​entium" 이나 그 전에 나온 CPU, VIA 경우 "C7"정도까지 기본적으로 인 오더 발행 / 인 오더 완료이다. 한편, 인텔의 "P​​entium Pro"나 AMD의 "K6" 이후는 아웃 오브 오더 발행 / 아웃 오브 오더 완료이다.

 x86에서는 거의 볼 수 없지만, AMD의 "Am29000"등은 인 오더 발행 / 아웃 오브 오더 완료가 일부 구현되어 있었다. 아웃 오브 오더 발행 / 인 오더 완료 CPU는 그렇다고 하지만 본 적이 없다. 이것은 실행 유닛의 처리 레이턴시에 관계하는 부분이다.

 지금까지의 예에서는 ALU와 Load / Store 처리 시간은 어떤 명령도 같다는 것을 전제로 설명해 왔다. 그러나 실제로는 명령에서 처리 시간이 다른 것이 일반적이다. 현재 x86 프로세서 에서도 명령에 의해 명령을 받은 것 부터 처리가 끝날 때 까지의 시간 "레이턴시"와 그 명령을 발효하는 대기시간 "쓰루풋 처리량" 은 다르다. 레이턴시가 3 클럭라면, 그 명령의 처리에 3 클럭이 걸린다. 쓰루풋이 3 클럭이라면 3 클럭 마다 그 명령울 실행할 수 있다는 의미가 된다.

 [그림 2]는 2 개의 ALU가 탑재 된 구성으로 레이턴시가 1 ~ 4 클럭의 각기다른 명령 1 ~ 6을 처리하는 경우를 생각한 것이다. 우선 스케줄러의 시점에서 명령 1 ~ 6은 그림 왼쪽과 같은 대기 시간을 제각각 갖는다고 가정한다. 이것을 ALU1과 ALU2에 분산 한 것이 중앙이다. 이 예 에서는 훌륭히 두개의 ALU에 명령을 분산 시켰다고 가정하고 있지만 ※1 문제는 출력이다.

※1 실제로 ALU 내부도 파이프 라인화 되어 있는 것이 보통이기 때문에 이렇게 단순하게는 안된다. 설명을 위해 단순화 한다.

 

 

[그림 2] 아웃 오브 오더 완료의 설명도


 각 ALU의 출력은 [그림 2] 오른쪽처럼 우선 처리시간이 짧은 명령 2의 결과가 나오고, 명령 1과 3이 따른다. 그 후에는 명령 5,4와 6이 나온다는 구성으로 순서없이 결과가 나온다. 아웃 오브 오더 완료는 이러한 각기다른 순서로 처리를 끝내는 것을 허하는 구조,라고 생각하면 된다.

 

아웃 오브 오더 에서 해저드를 방지하려면
명령어의 실행 순서를 보증하는 구조가 필요


 마지막으로 아웃 오브 오더에서 발생하는 파이프 라인 해저드에 대해 설명하고자 한다. 예전회 에서 파이프 라인 해저드에 대해 설명했지만,이 예제에서는 인 오더 파이프 라인의 이야기로 심플했다. 그러나 아웃 오브 오더는 또 다른 해저드가 있다. 소위 "명령의 의존성"에 관계하는 것이다.

 인 오더의 경우 파이프 라인화 되어 있으면 다음 예제에서는 명령 1이 완료 될 때까지 명령 2는 실행할 수 없다.

명령 1 R1 = R2 + R3
명령 2   R4 = R1 + R2


 이것을 "RAW 해저드"(Read After Write)라고 한다. 이 케이스에는 R1의 Write가 끝날때 까지 R1의 Read 가능하지 않기 때문이다. 그런데 아웃 오브 오더의 경우는 이외에도 다음과 같은 케이스가 생각된다.

명령 1 R1 = R2 + R3
명령 2 R2 = R4 + R5


 이 명령의 순서는 인 오더에서는 아무런 문제가 없다. 그런데 아웃 오브 오더의 경우 명령 2 전에 명령 1이 실행되는 보증이 없기에, 명령 2가 먼저 처리되어 버리면 R2 값이 바껴 써지고 끝나기에, 명령 1의 결과가 이상해진다. 이것을 "WAR 해저드"(Write After Read)라고 부른다. 이것을 피하기 위해서는 반드시 명령 1을 명령 2 앞에서 실행하는 것을 보증하는 기구가 필요하다.

명령 1 R1 = R2 + R3
명령 2   R4 = R1 + R4
명령 3 R1 = R2-R3


 위와 같은 케이스도 있다. 이 경우, 만일 명령 1의 앞에 명령 3이 실행되면, R1이 다른 값으로 써져 바뀌고, 명령 2의 값이 이상해질 가능성이 있다. 이것은 "WAW 해저드"(Write After Write)라고 부르고 있다. 이것에 대해서도 실행 순서를 보증하는 구조가 필요하다.

 이러한 파이프 라인 해저드의 해소는 기본적으로 스케줄러의 단계에서 처리하게 되는데, 지금까지 알듯이 명령을 적절하게 순서를 바꾸는 것으로도 상당히 힘든 얘기다. 거기에 더해 해저드 방지의 메커니즘도 필요하기 때문에 스케줄러는 상당히 복잡해진다. 일반론으로 말하면, 되도록 많은 명령을 모아 순서를 바꾸는 방법이 의존관계나 해저드를 해소하기 쉬운 경향은 있다. 그러나 그만큼 회로는 복잡해지는 한편이다.

 그러나 작금의 반도체 제조 공정의 미세화에 의해 사용 가능한 트랜지스터 수가 비약적으로 늘어난 점도 있고, 스케줄러 단계에서 보유하는 명령 수는 점점 증가하고 있다. Pentium Pro부터 시작된 P6 아키텍처에서는 이 스케줄러 단 (P6의 경우 Reservation Station라고 부른다)에서는 20 명령을 보유했다. 한편, 요전에 IDF 2010에서 발표된 "Sandy Bridge"에서는 54 명령까지 늘리고 있다. 늘리면 (무조건)좋다 라는 것은 아니지만, 적은것 보다는 많은 쪽이 좋다.

 다음은 명령 변환의 이야기를 하고 싶다.

 

 

 

 

[분석정보] CPU 고속화의 기본 수단 파이프라인 처리의 기본 1/2

 

 

[분석정보] CPU 고속화의 기본 수단 파이프라인 처리의 기본 2/2

 

 

[분석정보] 슈퍼 스칼라에 의한 고속화와 x86의 문제점은

 

 

 

[분석정보] x86을 고속화하는 조커기술 명령변환 구조

 

 

[분석정보] CPU와 메모리의 속도 차이를 해소하는 캐시의 기초지식

 

 

[분석정보] 캐쉬 구현 방식으로 보는 AMD와 인텔이 처한 상황

 

 

[고전 2005.11.30] 마이크로 아키텍처의 변화를 반영하는 "Core"브랜딩

 

 

[분석정보] 20년 후인 지금도 곳곳에서 살아남은 펜티엄 아키텍처

 

 

[분석정보] 5W 이하의 저전력 프로세서의 개발로 향하는 Intel

 

 

[분석정보] intel의 듀얼 코어 CPU 1번타자 Montecito

 

 

[분석정보] 멀티 코어 + 멀티 스레드 + 동적 스케줄링으로 향하는 IA-64

 

 

[정보분석] Penryn의 1.5 배 CPU 코어를 가지는 차세대 CPU "Nehalem"

 

 

 

[고전 2002.10.04] Pentium 8 후보 Nehalem 아키텍처

 

 

[고전 2002.09.12] Hyper-Threading Technology를 지원하는 HTT Pentium 4 3.06GHz

 

 

 

[고전 1998.02.13] Intel에 의한 AGP 레퍼런스 "Intel 740"