49
프프프프프가 가가가 프프프프 CPU 프프프 Story 13, 14 가 2011. 06. 11 가가가 가가가 ( http://andstudy.com ) 가가가 ( [email protected] )

프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

프로그래머가 몰랐던멀티코어 CPU 이야기

Story 13, 14 장

2011. 06. 11아꿈사 스터디 ( http://andstudy.com )

윤석윤 ( [email protected] )

Page 2: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

Story 13

If 문은 그냥 실행되는 것이 아니다 .

Story 14

가상 함수에 담긴 복잡함

Page 3: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

Story 13

If 문은 그냥 실행되는 것이 아니다 .

Story 14

가상 함수에 담긴 복잡함

Page 4: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기문 명령어와 프로그래밍 언어

분기문 (branch)

분기문은 프로그램의 실행 흐름 , PC(program counter) 값이 바뀔 수 있는 명령어를 가리킨다 .

분기 여부를 따지는 방식조건분기 (conditional branch)무조건 분기 (unconditional branch)

분기 목적지를 얻는 방식직접 분기문 (direct branch)간접 분기문 (indirect branch)

Page 5: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기문 명령어와 프로그래밍 언어

분기문 (branch)

조건 분기특정 연산 결과가 어떤 조건 만족 시 분기(For, while, do, until)

무조건 분기항상 해당 목적지로 분기(goto, jump)

Page 6: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기문 명령어와 프로그래밍 언어

분기문 (branch)

직접 분기문분기 목적지를 바로 얻을 수 있는 경우

간접 분기문메모리를 한번 참조해서 목적지를 얻음( 콜백 , 프로시저 리턴 , 가상함수 호출 , C# 델리게이트 )

Page 7: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

컨트롤 의존성분기문은 컨트롤 의존성을 만듬

파이프라인 프로세서에서 컨트롤 해저드가 되어 파이프라인의 효율 저하

IF ID OF EXE OSIf a== 0 goto 5

IF ID OF EXE OSa = a + 1stal

lstal

lStal

l

IF ID OF EXE OSb = a + 2stal

lstal

lStal

l

Page 8: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

컨트롤 의존성분기문은 컨트롤 의존성을 만듬

파이프라인 프로세서에서 컨트롤 해저드가 되어 파이프라인의 효율 저하

IF ID OF EXE OSIf a== 0 goto 5

IF ID OF EXE OSa = a + 1stal

lstal

lstal

l

IF ID OF EXE OSb = a + 2stal

lstal

lstal

l

분기문이 exe 단계에서 밝혀진다면 파이프라인 스톨이 발생

Page 9: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

컨트롤 의존성MIPS 프로세서는 분기문 해결을 최대한 앞 단계에서 해결하여 파이파인 스톨 횟수를 줄임컴파일러가 분기문의 결과와 상관없이 실행되는 명령어를 배치할 수도 있음 ( 지연슬롯 )간접 분기문 역시 컨트롤 해저드를 유발

IF ID OF EXE OSJump[100]

IF ID OF EXE OSa = 10stal

lstal

lIF ID OF EXE OSb = a + 10

stall

stall

Page 10: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

컨트롤 의존성MIPS 프로세서는 분기문 해결을 최대한 앞 단계에서 해결하여 파이파인 스톨 횟수를 줄임컴파일러가 분기문의 결과와 상관없이 실행되는 명령어를 배치할 수도 있음 ( 지연슬롯 )간접 분기문 역시 컨트롤 해저드를 유발

IF ID OF EXE OSJump[100]

IF ID OF EXE OSa = 10stal

lstal

lIF ID OF EXE OSb = a + 10

stall

stall

100 번지에 저장된 값 , 20 으로 분기하므로 이 값을 읽으려면 기다려야 한다 .

Page 11: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

분기 예측 (branch prediction)

무조건 분기문은 계산이 필요하지 않고 , 직접 분기문은 메모리 참조가 필요 없이 바로 명령어만 해독하면 분기 지점을 알 수 있다 .

하지만 CISC 구조처럼 복잡한 명령어에서는 이 작업도 바로 이루어 지기 어려워 파이프라인 스톨 발생

분기문이 파이프라인의 첫 단계에서 그 결과가 알려 진다면 파이프라인 스톨 없이 파이프라인은 작동 할 수 있다 .

Page 12: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

분기 예측 (branch prediction)

그러나 파이프라인을 해결하는 방법은 일반적인 정수 연산에 버금간다 .

분기예측을 이용해 분기문의 결과가 나오지 않았음에도 분기문의 결과를 예측해 파이프라인을 진행시킨다 .

Page 13: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

분기 예측 (branch prediction)

분기 방향 예측 (taken)주어진 조건 분기문이 분기하느냐 (taken) 아니면 분기하지 않느냐 (not taken) 를 예측 ( 0 or 1)

IF ID OF EXE OSIf a== 0 goto 5

IF ID OF EXE OSa = a +1

b = a +2 IF ID OF EXE OS

분기 결과 예측

Page 14: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

분기 예측 (branch prediction)

분기 목적지 예측 (target)분기문이 어디로 분기할지 목적지 (target) 를 예측 .

가능한 모든 분기 목적지 중 하나를 고르는 것이므로 훨씬 더 많은 대상 가운데 예측해야 하는 어려움이 있다

IF ID OF EXE OSJump[100]

IF ID OF EXE OSa = 10

b = a +10 IF ID OF EXE OS

분기 목적지 예측

Page 15: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측이 필요한 이유

분기 예측 (branch prediction)

프로세서가 순차든 비순차든 상관 없음

파이프라인 프로세서이고 컨트롤 해저드로 파이프라인 스톨이 발생하는 경우라면 분기 예측은 항상 필요하다

분기 예측은 미래에 벌어질 일을 예측하는 것이므로 100% 완벽하다는 것은 있을 수 없다 .

분기문이 틀릴 경우를 대비해야 한다 .

Page 16: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측에 기반한 투기적 실행

투기적 실행 (speculative execution)

불확실한 예측을 기반으로 더 나은 성능을 가져오는 방향으로 명령어를 처리하는 일반적인 개념

분기문의 예측 값이 실제와 같다면 명령어 완료 사이클을 단축

예측 값과 다르다면 처리한 명령어를 삭제

IF ID OF EXE OSIf a== 0 goto 5

IF ID OF EXE OSa = a +1

b = a +2 IF ID OF EXE OS

IF ID OF EXE OS

IF ID OF EXE OS

c = b +3

a = a +10

Page 17: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 예측에 기반한 투기적 실행

투기적 실행 (speculative execution)

예측에 기반해 확실하지 않은 일을 미리 수행해서 그 결과가 맞기를 기대

투기적 실행에 필요한 장치

1 미래를 예측하는 장치

2 결과가 확실하지 않아도 실행을 계속 진행시킬 수 있는 장치 (ROB)

3 예측이 틀렸을때 원상태로 복구하는 장치 (UNDO)

Page 18: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

정적 분기 예측정해진 규칙에 따라서만 움직임

실시간으로 프로그램의 내역을 분석하는 능동적인 대처는 없다 .

과거 프로세서에서 장치를 많이 넣을 수 없었던 시절에 사용한 방법

1. 모든 분기문을 분기하게 한다 (always taken)2. 모든 분기문을 분기하지 않게 한다 (always not taken)3. 뒤로 가는 분기문은 분기하게 , 앞으로 가는 분기문은 분기하지

않게 한다 .(BTFNT)4. 프로그램의 프로파일 정보를 활용한다

Page 19: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

동적 분기 예측실제 프로그램의 실행 내역으로 미래에 일어날 분기를 예측

캐시의 원리와 흡사 ( locality), 과거 정보를 활용해서 아직 일어나지 않은 미래를 예측

예제- 과거 분기 예측기 단순 과거 비교만을 수행하므로 어쩌다 한번 일어나는 분기 결과 값으로 빗나간 예측을 하게 됨

- 2 비트를 활용한 분기 예측기 단순히 분기 여부만을 기억하는 것이 아니라 강도까지 기억 ( 약간의 저항을 적용 )

Page 20: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

더 똑똑한 과거 기반의 예측웹 브라우저의 다운로드 폴더의 예- 파일 종류와 함께 폴더 이름을 기억- 더 많은 과거 정보 , 어떤 사건들 사이의 관계를 이용하여 예측 성능 향상- 특정 분기문의 과거 결과만으로 미래를 예측하는 것보다 정보를 기억하여 예측 성능을 높임

순서 1 2 3 4 5 6

파일 종류 그림 그림 그림 PDF 그림 PDF

브라우저 예측 D:\Downloads D:\Picture D:\Picture D:\Downloads D:\Picture D:\Document

적중 여부 X O O X O O

Page 21: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

히스토리를 이용한 분기 예측한 분기문의 결과를 예측하는데 다른 분기문의결과를 함께 고려해 예측하는 것

모든 결과를 기억할 수는 없으므로 가장 최근의N 개의 분기문의 결과만 기억

Page 22: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

초기값 0 0 0 0 0 0 0 0

관찰한 모든 분기문의결과를 비트 벡터로 표현

Page 23: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

초기값 0 0 0 0 0 0 0 0

taken

관찰한 모든 분기문의결과를 비트 벡터로 표현

Page 24: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

초기값 0 0 0 0 0 0 0 1 (shift)

taken

관찰한 모든 분기문의결과를 비트 벡터로 표현

Page 25: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

초기값 0 0 0 0 0 1 0 1

taken

not taken

taken

관찰한 모든 분기문의결과를 비트 벡터로 표현

Page 26: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

분기 예측 시 , 분기문의 PC 주소와 현재 BHR 획득

PC

BHR

Page 27: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

분기 예측 시 , 분기문의 PC 주소와 현재 BHR 획득

PC

BHR

BHR 의 값에 따라 4 개 중 하나의 테이블을 선택

Page 28: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

분기 예측 시 , 분기문의 PC 주소와 현재 BHR 획득

PC

BHR

BHR 의 값에 따라 4 개 중 하나의 테이블을 선택

2 비트 분기 예측기와 동일하게 작동

Page 29: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터 PC

BHR

BHR 을 이용하고 그 뒤에 PC 를 이용하므로 Two-level branch predictor 라고 부른다

Page 30: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터 PC

분기문의 결과 기록을 전역으로 하지 않고 각 분기문에 국한해서 선택

로컬 BHR테이블

Page 31: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터 PC

분기문의 결과 기록을 전역으로 하지 않고 각 분기문에 국한해서 선택

로컬 BHR테이블

테이블의 크기는 한정적이므로 모든 PC 마다 만들 수는 없고 겹쳐지는 일이 발생

Page 32: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터 PC

분기문의 결과 기록을 전역으로 하지 않고 각 분기문에 국한해서 선택

로컬 BHR테이블

테이블의 크기는 한정적이므로 모든 PC 마다 만들 수는 없고 겹쳐지는 일이 발생

예측 시 PC 에 해당하는 로컬 BHR 을 찾아 분기 예측 테이블을 선택 , PC 를 이용해 엔트리를 찾고 2 비트 카운터 값을 예측

Page 33: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터 PC

로컬 BHR테이블

비효율적… ..어떤 BHR 과 PC 조합 값은 잘 나타나지 않을수도 있으므로 많은 테이블이 놀게 된다 .

Page 34: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

PC

BHR

PC 와 BHR 을 합쳐서…

XOR

Page 35: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

2 비트 카운터

PC

BHR

PC 와 BHR 을 합쳐서…

XORgShare 분기 예측기

Page 36: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

프리디케이션 (predication)

컨트롤 의존성을 데이터 의존성으로 바꾸는 방법으로 분기문을 변환

컴파일러는 최대한 분기 흐름이 없는 곧은 상태의 코드에서 최적화를 더 많이 수행 할 수 있다 .

If (rand() %2) a = 10;else a = 20;

predicate = (rand %2);a = 10 (predicate); // predicate 가 true 일 때만 실행a = 20 (predicate); // predicate 가 false 일 때만 실행

Page 37: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

프리디케이션 (predication)

프리디케이션 레지스터가 필요하고 명령어가 프리디케이션 레지스터를 쓸 수 있게 확장해야 한다 .

하드웨어를 대폭적으로 수정해야 하므로 특별한 명령어 구조를 제외하고 제한적으로 지원된다 .

X86 은 CMOV 라는 명령어로 프리디케이션을 지원하나 그 성능이 프로세서 세대마다 구조마다 차이가 있어 조심스럽게 사용해야 한다 .

분기 예측이 어려운 비교적 짧은 분기문에 적합하나 실제로 실행되지 않는 명령도 함께 수행되므로 파이프라인 자원과 전력이 낭비된다 .

Page 38: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

결론

분기예측은 아직 실행되지 않은 분기문의 결과 , 분기 방향과 분기 목적지를 미리 예측해 쉬지 않고 파이프라인에 명령어를 넣을 수 있게 한다 .

예측이 맞으면 프로세서의 성능은 크게 향상된다 .

분기 예측은 실패할 수 있기에 적절한 장치를 두어 복구하도록 한다 . 이러한 기법을 투기적 실행이라고 한다 .

Page 39: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

미래를 예측하는 장치

결론

분기 예측기가 부정확 하면 적은 명령어 밖에 인출하지 못하게 된다 .

이것은 ILP( 명령어 수준의 병렬성 ) 와 연관성이 있어 성능의 저하를 일으킴

한 사이클당 최대로 인출할 수 있는 명령어 수가 결국 IPC( 사이클 당 완료 명령어 수 ) 의 상한값 이기에 분기 예측기의 성능은 더 높은 IPC 를 얻기 위한 기본 조건이다 .

Page 40: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

Story 13

If 문은 그냥 실행되는 것이 아니다 .

Story 14

가상 함수에 담긴 복잡함

Page 41: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 목적지 예측

직접 분기문 ( direct branch )

분기 목적지가 명령어에 인코딩 되어 있음

명령어만 해독하면 목적지를 알아 낼 수 있다 .

x86 같은 CISC 명령은 명령어 인출 2~3 사이클이 지나야 해독이 가능 .

경우의 수가 최대 두 가지 밖에 없음

Page 42: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

분기 목적지 예측

간접 분기문 ( indirect branch )

분기 목적지가 레지스터 또는 메모리에 있어 한번 더 참조해야 한다 .

분기문의 분기 목적지를 얻는 것은 레지스터 파일이나 메모리 접근이 필요하기에 직접 분기문 보다 더 오랜 시간이 걸린다 .

파이프라인 단계 중 EXE 를 지나야 알 수 있다 .

가능한 경우의 수가 훨씬 많기 때문에 어렵다 .

Page 43: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

간접 분기문의 분기 목적지 예측

RAS( Return Address Stack )

어떤 함수가 불리고 할 일이 끝났으면 함수를 부른 곳으로 다시 돌아가야 한다 .

이때 돌아가는 주소는 프로그램이 직접 수행 될 때 알 수 있다 .

일반적으로 돌아갈 주소는 레지스터에 들어 있어 함수 리턴 역시 간접 분기문으로 구현된다 .

0x200

0x100

1. 함수 호출시 리턴 주소를 push

2. 함수 리턴시 pop 하고 이 값으로 분기 목적지를 예측

Page 44: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

간접 분기문의 분기 목적지 예측

콜백 함수와 가상 함수

Object* p = new Computer;p->NoVirtual();00BA15D9 mov ecx,dword ptr [p]00BA15DC call Object::NoVirtual (0BA1028h) p->TurnOn(10);00BA15E1 push 0Ah ; 함수 인자 1000BA15E3 mov eax,dword ptr [p] ; eax = p00BA15E6 mov edx,dword ptr [eax] ; edx = *p00BA15E8 mov ecx,dword ptr [p] ; this = p00BA15EB mov eax,dword ptr [edx+8] ; eax = *(*p + 8)00BA15EE call eax

Page 45: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

간접 분기문의 분기 목적지 예측

콜백 함수와 가상 함수

일반 함수의 호출은 직접 분기문으로 구현된다 .

가상 함수는 컴파일할 때 함수 목적지를 알 수 없다 .- 다이나믹 디스패쳐라고 부르며 의미와 작동 방식은 C++ 언어가 규정하지만 컴파일러가 이것을 어떻게 구현할지는 컴파일러마다 다르다 .- 일반적으로 Virtual table 이라는 테이블을 참조하여 프로그램이 실행될 때 포인터가 실제로 기리키는 곳을 읽어 해당 타입에 맞는 구현을 호출할 수 있다 .- 가상 함수라 할지라도 표현만 다를 뿐이지 실제 구현은 콜백 함수와 같은 간접 분기문으로 이루어진다 .

Page 46: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

간접 분기문의 분기 목적지 예측

점프 테이블

switch-case 구문에서 case 구문의 개수가 적다면 if-else 로 구현

case 구문의 개수가 많다면 비교 횟수를 최악의 경의 case 구문수 만큼 늘리게 된다 .

컴파일러는 특정 조건이 만족할 때 switch-case 를 점프 테이블이라는 것으로 대체한다 .

일종의 해시 테이블로 switch 값에 대해 분기할 곳의 주소를 미리 테이블로 만들어 두어서 비교 없이 바로 목적지로 간다 .

Page 47: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

간접 분기문의 분기 목적지 예측

iBTB( 간접 분기문을 위해 특화된 BTB)

콜백 함수 , 가상 함수 , switch-case 는 함수 리턴과는 상당히 다른 어려움을 가지고 있다

분기할 대상이 여러 개가 될 수 있기에 단순히 과거 값만 기억하는 BTB 로는 좋은 성능을 낼 수 없다 .

히스토리 ( 이전 다른 분기문의 결과 ) 를 활용하면 예측률이 더 높아진다 . 잘 돌아가는 이유는 분기문 사이에 서로 관련이 많기 때문이다 .

Page 48: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장

간접 분기문의 분기 목적지 예측

결론

기본적인 BTB 는 직접 분기문에서는 잘 작동하지만 간접 분기문에서는 그렇지 않다 .

간접 분기문은 종류에 따라 각기 특화된 알고리즘으로 예측률을 높인다 .

함수 리턴에 의한 간접 분기문은 RAS 로 , 가상함수 , 콜백 함수 , 스위치 문은 히스토리를 이용한 iBTB 를 이용한다 .

Page 49: 프로그래머가 몰랐던 멀티코어 CPU 이야기 13, 14장