인텔이 프로세서에서 내부 RISC 코어를 숨기는 이유는 무엇입니까?


90

Pentium Pro (P6 마이크로 아키텍처)부터 인텔은 마이크로 프로세서를 재 설계하고 이전 CISC 지침에 따라 내부 RISC 코어를 사용했습니다. Pentium Pro 이후 모든 CISC 명령어는 더 작은 부분 (uops)으로 분할 된 다음 RISC 코어에 의해 실행됩니다.

처음에는 인텔이 새로운 내부 아키텍처를 숨기고 프로그래머가 "CISC 쉘"을 사용하도록 강요한다는 것이 분명했습니다. 이 결정 덕분에 인텔은 호환성을 깨지 않고 마이크로 프로세서 아키텍처를 완전히 재 설계 할 수 있었기 때문에 합리적입니다.

그러나 한 가지 이해가되지 않습니다. 인텔이 내부 RISC 명령 세트를 수년 동안 숨긴 이유는 무엇입니까? 프로그래머가 이전 x86 CISC 명령어 세트를 사용하는 것과 같은 RISC 명령어를 사용하도록 허용하지 않는 이유는 무엇입니까?

인텔이 이전 버전과의 호환성을 오랫동안 유지한다면 (우리는 여전히 64 비트 모드 옆에 가상 8086 모드가 있음) CISC 명령을 우회하고 RISC 코어를 직접 사용하도록 프로그램을 컴파일하도록 허용하지 않는 이유는 무엇입니까? 이것은 현재 더 이상 사용되지 않는 x86 명령 세트를 천천히 포기하는 자연스러운 방법을 열 것입니다 (이것이 인텔이 내부에서 RISC 코어를 사용하기로 결정한 주된 이유입니다.).

새로운 Intel 'Core i'시리즈를 보면 AVX, SSE4 등을 추가하는 CISC 명령 세트 만 확장됩니다.


1
특정의 x86 CPU를가하는 것으로 내부 RISC 명령어 세트가 노출
phuclv는

답변:


92

아니요, x86 명령어 세트는 확실히 더 이상 사용되지 않습니다. 그 어느 때보 다 인기가 있습니다. 인텔이 내부적으로 RISC와 유사한 마이크로 명령어 세트를 사용하는 이유는 더 효율적으로 처리 할 수 ​​있기 때문입니다.

따라서 x86 CPU는 x86 명령어를 받아들이고 백엔드가 처리 할 수있는 최적화 된 내부 형식으로 변환하는 프런트 엔드에 상당히 무거운 디코더를 사용하여 작동합니다.

이 형식을 "외부"프로그램에 노출하는 것과 관련하여 두 가지 사항이 있습니다.

  • 안정적인 형식이 아닙니다. 인텔은 특정 아키텍처에 가장 적합하도록 CPU 모델간에 변경할 수 있습니다. 이를 통해 효율성을 극대화 할 수 있으며, 내부 사용 및 외부 사용을 위해 고정되고 안정적인 명령어 형식을 결정해야하는 경우 이러한 이점을 잃게됩니다.
  • 그렇게해서 얻을 수있는 것은 아무것도 없습니다. 오늘날의 거대하고 복잡한 CPU에서 디코더는 CPU의 상대적으로 작은 부분입니다. x86 명령어를 디코딩해야하는 것은 더 복잡해 지지만 나머지 CPU는 영향을받지 않으므로 전반적으로 얻을 수있는 것이 거의 없습니다. 특히 "레거시"코드를 실행하려면 x86 프런트 엔드가 여전히 있어야하기 때문입니다. . 따라서 x86 프런트 엔드에서 현재 사용되는 트랜지스터도 저장하지 못할 것입니다.

이것은 완벽한 배열은 아니지만 비용이 상당히 적고 완전히 다른 두 개의 명령 세트 를 지원하도록 CPU를 설계하는 것보다 훨씬 더 나은 선택 입니다. (이 경우 CPU의 내부 아키텍처에 가장 잘 맞도록 자유롭게 조정할 수 있기 때문에 내부 사용을위한 세 번째 마이크로 작업 세트를 발명하게 될 것입니다. )


1
좋은 점. RISC는 GOOD가 실행 속도가 빠르며 올바르게 구현할 수 있음을 의미하는 좋은 코어 아키텍처이며 CISC 아키텍처 기록을 가진 x86 ISA는 이제 엄청난 기록과 엄청난 양의 바이너리 소프트웨어를 사용할 수있는 명령 세트 레이아웃입니다. , 저장 및 처리에 효율적입니다. 그것은 CISC 쉘이 아니라 업계의 사실상의 표준 ISA입니다.
Warren P

2
@Warren : 마지막 부분에서는 실제로 그렇게 생각하지 않습니다. 잘 설계된 CISC 명령어 세트는 예, 스토리지의 측면에서 더 효율적이지만, 내가 본 몇 가지 검사에서 "평균"x86 명령어는 인 4.3과 같은 넓은 바이트 이상 은 보통의 것보다 RISC 아키텍처. x86은 수년에 걸쳐 너무 무질서하게 설계되고 확장 되었기 때문에 많은 스토리지 효율성을 잃습니다. 그러나 당신이 말했듯이, 그것의 주요 강점은 역사와 엄청난 양의 기존 바이너리 코드입니다.
jalf

1
나는 그것이 "잘 설계된 CISC"가 아니라 "거대한 역사"라고 말하지 않았습니다. GOOD 부품은 RISC 칩 설계 부품입니다.
Warren P

2
@jalf-실제 바이너리 검사에서 x86의 명령어 크기는 각각 평균 ​​약 3 바이트입니다. 물론 훨씬 더 긴 지침이 있지만 실제 사용에서는 작은 지침이 지배적 인 경향이 있습니다.
srking

1
평균 명령어 길이는 코드 밀도의 좋은 척도가 아닙니다. 일반적인 코드에서 가장 일반적인 x86 명령어 유형은로드 및 저장입니다 (데이터를 처리 할 수있는 위치로 이동 한 다음 다시 메모리, RISC 프로세서 및 약 ½ CISC가 레지스터가 많기 때문에 이렇게 많이 할 필요가 없습니다 .. 또한 하나의 명령어가 얼마나 많은 일을 할 수 있는지 (arm 명령어는 약 3 가지 일을 할 수 있습니다)
ctrl-alt-delor

20

진짜 대답은 간단합니다.

RISC 프로세서 구현의 주요 요인은 복잡성을 줄이고 속도를 높이는 것이 었습니다. RISC의 단점은 명령어 밀도가 감소한다는 것입니다. 즉, RISC 형식으로 표현 된 동일한 코드는 동등한 CISC 코드보다 더 많은 명령어가 필요합니다.

이 부작용은 CPU가 메모리와 동일한 속도로 실행되거나 적어도 둘 다 합리적으로 유사한 속도로 실행되는 경우에는 그다지 의미가 없습니다.

현재 CPU 속도와 비교 한 메모리 속도는 클럭에서 큰 차이를 보입니다. 현재 CPU는 때때로 주 메모리보다 5 배 이상 빠릅니다.

이 기술 상태는 CISC가 제공하는보다 조밀 한 코드를 선호합니다.

캐시가 RISC CPU의 속도를 높일 수 있다고 주장 할 수 있습니다. 그러나 CISC cpus에 대해서도 마찬가지입니다.

동일한 크기의 캐시가 CISC가 제공하는 고밀도 코드에 더 많은 영향을 미치기 때문에 RISC 및 캐시보다 CISC 및 캐시를 사용하면 더 큰 속도 향상을 얻을 수 있습니다.

또 다른 부작용은 RISC가 컴파일러 구현에서 더 어렵다는 것입니다. CISC CPU에 대한 컴파일러 최적화가 더 쉽습니다. 기타

인텔은 그들이 무엇을하고 있는지 알고 있습니다.

ARM에는 Thumb이라는 더 높은 코드 밀도 모드가 있습니다.


1
또한 내부 RISC 코어는 CISC CPU의 트랜지스터 수를 줄입니다. 모든 CISC 명령어를 하드 와이어 링하는 대신 마이크로 코드를 사용하여 실행할 수 있습니다. 이는 서로 다른 CISC 명령어에 대해 RISC 마이크로 코드 명령어를 재사용하므로 다이 영역을 더 적게 사용합니다.
Sil

16

인텔이 이전 버전과의 호환성을 오랫동안 유지한다면 (우리는 여전히 64 비트 모드 옆에 가상 8086 모드가 있음) CISC 명령을 우회하고 RISC 코어를 직접 사용하도록 프로그램을 컴파일하도록 허용하지 않는 이유는 무엇입니까? 이것은 현재 더 이상 사용되지 않는 x86 명령 세트를 천천히 포기하는 자연스러운 방법을 열 것입니다 (이것이 인텔이 내부에서 RISC 코어를 사용하기로 결정한 주된 이유입니다.).

이것의 비즈니스 각도를 봐야합니다. 인텔은 실제로 x86에서 벗어나려고 시도했지만 회사에 황금 알을 낳는 것은 거위입니다. XScale과 Itanium은 핵심 x86 비즈니스가 가진 성공 수준에 가까워지지 않았습니다.

당신이 기본적으로 요구하는 것은 인텔이 개발자의 따뜻한 보풀을 대가로 손목을 자르는 것입니다. x86을 약화시키는 것은 그들의 이익이 아닙니다. 더 많은 개발자가 x86을 대상으로 선택하지 않아도되는 것은 x86을 약화시킵니다. 그것은 차례로 그들을 약화시킵니다.


6
예, 인텔이이를 시도했을 때 (Itanium) 시장은 어깨를 으쓱하는 것만으로 반응했습니다.
Warren P

Itanium이 실패하는 동안 다양한 요인이 있었으며 새로운 아키텍처이기 때문 만이 아니라는 점에 유의해야합니다. 예를 들어, 실제로 목표를 달성하지 못한 컴파일러에 CPU 스케줄링을 오프로드합니다. Itanium이 x86 CPU보다 10 배 또는 100 배 빠르다면 핫케익처럼 팔렸을 것입니다. 그러나 그것은 더 빠르지 않았습니다.
Katastic Voyage

5

대답은 간단합니다. 인텔은 개발자를 위한 CPU를 개발 하지 않습니다 ! 그들은 구매 결정을 내리는 사람들을 위해 개발하고 있습니다. BTW는 전 세계 모든 회사가하는 일입니다!

인텔은 오래 전에 CPU가 이전 버전과의 호환성을 유지할 것이라고 약속했습니다. 사람들은 새로운 Intel 기반 컴퓨터를 구입할 때 현재의 모든 소프트웨어가 이전 컴퓨터에서와 동일하게 실행 된다는 것을 알고 싶어 합니다. (하지만, 더 빨리!)

또한 인텔은 한때 다른 길을 가려고했기 때문에 그 약속이 얼마나 중요한지 정확히 알고 있습니다. Itanium CPU로 얼마나 많은 사람들 알고 계십니까?!?

마음에 들지 않을 수도 있지만 x86을 유지하기로 한 결정은 인텔을 세계에서 가장 잘 알려진 비즈니스 이름으로 만든 것입니다!


2
나는 인텔 프로세서가 개발자에게 친숙하지 않다는 암시에 동의하지 않습니다. 수년 동안 PowerPC와 x86을 프로그래밍해온 저는 CISC가 훨씬 더 프로그래머 친화적이라고 믿게되었습니다. (지금은 인텔 작동하지만 내가 고용되기 전에이 문제에 대한 내 마음을했다.)
제프 몬

1
@Jeff 그건 내 의도가 아니었다! 문제는 인텔이 개발자가 사용할 수 있도록 RISC 명령 세트를 열지 않은 이유입니다. x86이 개발자에게 친숙 하지 않다는 것에 대해서는 아무 말도 하지 않았습니다 . 제가 말한 것은 이와 같은 결정은 개발자 를 염두에두고 결정된 것이 아니라 엄격하게 비즈니스 결정이라는 것입니다.
geo

5

@jalf의 답변은 대부분의 이유를 다루지 만 언급하지 않은 흥미로운 세부 사항이 하나 있습니다. 내부 RISC와 유사한 코어는 ARM / PPC / MIPS와 같은 명령어 세트를 실행하도록 설계되지 않았습니다. x86 세는 전력이 많이 소모되는 디코더뿐만 아니라 코어 전체에 걸쳐 어느 정도 지불됩니다. 즉, 단지 x86 명령어 인코딩이 아닙니다. 이상한 의미를 가진 모든 명령어입니다.

Intel이 명령 스트림이 x86이 아닌 작동 모드를 생성했다고 가정 해 보겠습니다. 명령은 uop에 더 직접적으로 매핑됩니다. 또한 각 CPU 모델에이 모드에 대한 자체 ISA가 있다고 가정 해 보겠습니다. 따라서 원하는 경우 내부를 자유롭게 변경할 수 있으며이 대체 형식의 명령 디코딩을 위해 최소한의 트랜지스터로 노출 할 수 있습니다.

아마도 x86 아키텍처 상태에 매핑 된 동일한 수의 레지스터 만 가질 수 있으므로 x86 OS는 CPU 별 명령 세트를 사용하지 않고도 컨텍스트 스위치에서이를 저장 / 복원 할 수 있습니다. 그러나 실제적인 제한을 버리면 일반적으로 마이크로 코드 1에 예약 된 숨겨진 임시 레지스터를 사용할 수 있기 때문에 레지스터를 몇 개 더 가질 수 있습니다 .


이후 파이프 라인 단계 (실행 단위)를 변경하지 않고 대체 디코더 만 있으면 이 ISA에는 여전히 많은 x86 편심이 있습니다. 아주 좋은 RISC 아키텍처는 아닐 것입니다. 단일 명령이 매우 복잡하지는 않지만 x86의 다른 광기 중 일부는 여전히 존재합니다.

예를 들어 : 왼쪽 / 오른쪽 시프트는 시프트 카운트가 1이 아니면 오버플로 플래그를 정의되지 않은 상태로 둡니다.이 경우 OF = 일반적인 부호있는 오버플로 감지입니다. 회전에 대한 유사한 광기. 그러나 노출 된 RISC 명령어는 플래그없는 시프트 등을 제공 할 수 있습니다 (일반적으로 복잡한 x86 명령어로 들어가는 여러 uop 중 하나 또는 두 개만 사용할 수 있음). 따라서 이것은 실제로 주요 반론으로 유지되지 않습니다.

RISC ISA를위한 완전히 새로운 디코더를 만들려는 경우 RISC 명령으로 노출 될 x86 명령의 일부를 선택하고 선택할 수 있습니다. 이것은 코어의 x86 전문화를 다소 완화합니다.


단일 uop이 많은 데이터를 보유 할 수 있기 때문에 명령어 인코딩은 고정 크기가 아닐 것입니다. 모든 여관의 크기가 같으면 말이되는 것보다 훨씬 많은 데이터. 단일 마이크로 퓨즈 uop은 2 개의 레지스터와 32 비트 변위가있는 주소 지정 모드를 사용하는 32 비트 즉시 및 메모리 피연산자를 추가 할 수 있습니다. (SnB 이상에서는 단일 레지스터 주소 지정 모드 만 ALU 작업과 마이크로 융합 할 수 있습니다.)

uop은 매우 크고 고정 너비 ARM 명령어와 매우 유사하지 않습니다. 고정 너비 32 비트 명령어 세트는 한 번에 16 비트 즉시 만로드 할 수 있으므로 32 비트 주소를로드하려면로드 즉시 하위 절반 /로드 상위 즉시 쌍이 필요합니다. x86은 그렇게 할 필요가 없습니다. 따라서 레지스터에서 상수를 유지하는 기능을 제한하는 15 개의 GP 레지스터만으로는 끔찍하지 않습니다. (15 개는 7 개 레지스터에 비해 큰 도움이되지만 31 개로 다시 두 배로 늘리면 훨씬 덜 도움이된다고 생각합니다. 일부 시뮬레이션이 발견 된 것 같습니다. RSP는 일반적으로 범용이 아니므로 15 개의 GP 레지스터와 스택에 가깝습니다.)


요약 :

어쨌든,이 대답은 "x86 명령 세트는 아마도 x86 명령을 빠르게 실행할 수 있어야하는 CPU를 프로그래밍하는 가장 좋은 방법 일 것입니다"로 요약되지만, 그 이유에 대해 약간의 빛을 비추 길 바랍니다.


프런트 엔드 대 백 엔드의 내부 uop 형식

Intel CPU에서 프런트 엔드 대 백엔드 uop 형식이 나타낼 수있는 차이점의 한 가지 사례 는 마이크로 퓨전 및 주소 지정 모드 를 참조하십시오 .

각주 1 : 마이크로 코드에 의해 임시로 사용되는 "숨겨진"레지스터가 있습니다. 이러한 레지스터는 x86 아키텍처 레지스터와 마찬가지로 이름이 바뀌므로 다중 uop 명령어는 순서가 맞지 않게 실행할 수 있습니다.

xchg eax, ecx를 들어 Intel CPU에서 3 uops로 디코딩합니다 ( 왜? ). 우리의 최선의 추측은 이것들이 tmp = eax; ecx=eax ; eax=tmp;. 그 순서대로 dst-> src 방향의 지연 시간을 ~ 1 사이클에서 측정하고 다른 방법으로는 2 사이클을 측정하기 때문입니다. 그리고 이러한 움직임 uops는 일반 mov지침 과 같지 않습니다 . 지연 시간이없는 이동 제거의 후보가 아닌 것 같습니다.

PRF 크기를 실험적으로 측정하려고 시도하고 숨겨진 레지스터를 포함하여 아키텍처 상태를 유지하는 데 사용되는 물리적 레지스터를 고려해야한다는 언급은 http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ 를 참조하십시오 .

디코더 이후의 프런트 엔드에서 레지스터 이름을 물리 레지스터 파일로 변경하는 발급 / 이름 변경 단계 이전에 내부 uop 형식은 x86 reg 번호와 유사한 레지스터 번호를 사용하지만 이러한 숨겨진 레지스터를 처리 할 공간이 있습니다.

uop 형식은 비 순차적 코어 (ROB 및 RS), 일명 백엔드 (발급 / 이름 변경 단계 이후) 내에서 약간 다릅니다. int / FP 물리 레지스터 파일은 각각 Haswell에 168 개의 항목이 있으므로 uop의 각 레지스터 필드는 그 개수를 처리 할 수있을만큼 충분히 넓어야합니다.

이름 변경자는 HW에 있으므로 정적으로 예약 된 지침을 백엔드에 직접 제공하는 대신 사용하는 것이 더 나을 것입니다. 따라서 우리는 x86 아키텍처 레지스터 + 마이크로 코드 임시만큼 큰 레지스터 세트로 작업하게됩니다.

백엔드는 WAW / WAR 위험을 피하는 프런트 엔드 이름 변경자와 함께 작동하도록 설계되었으므로 원하는 경우에도 순차 CPU처럼 사용할 수 없었습니다. 이러한 종속성을 감지하는 인터록이 없습니다. 문제 / 이름 변경으로 처리됩니다.

문제 / 이름 변경 단계의 병목 현상없이 백엔드에 uop를 공급할 수 있다면 깔끔 할 수 있습니다 (예 : Skylake의 4 와이드 대 4 개의 ALU + 2 개의로드 + 1 개의 저장소 포트). 백엔드). 하지만 그렇게했다면 레지스터 재사용을 피하기 위해 코드를 정적으로 예약하고 캐시 미스가 오랫동안로드를 지연시킬 경우 여전히 필요한 결과를 밟을 수 없다고 생각합니다.

따라서 우리는 uop을 이슈 / 이름 변경 단계에 제공해야합니다. 아마도 uop 캐시 나 IDQ가 아닌 디코딩 만 우회 할 것입니다. 그런 다음 정상적인 위험 감지와 함께 정상적인 OoO exec를 얻습니다. 레지스터 할당 테이블은 16 개 + 몇 개의 정수 레지스터의 이름을 168 개 항목 정수 PRF로 변경하도록 설계되었습니다. 우리는 HW가 더 큰 논리적 레지스터 세트의 이름을 같은 수의 물리적 레지스터로 바꾸는 것을 기대할 수 없었습니다. 더 큰 RAT가 필요합니다.


-3

CISC 명령을 우회하고 RISC 코어를 직접 사용하도록 프로그램 컴파일을 허용하지 않는 이유는 무엇입니까?

이전 답변 외에도 또 다른 이유는 시장 세분화입니다. 일부 명령어는 하드웨어가 아닌 마이크로 코드로 구현되는 것으로 생각되므로 누구나 임의의 마이크로 연산을 실행할 수 있도록 허용하면 "새로운"성능이 더 우수한 CISC 명령어를 사용하여 새 CPU 판매를 저해 할 수 있습니다.


1
나는 이것이 말이되지 않는다고 생각한다. RISC는 마이크로 코드를 사용할 수 있습니다. 특히 x86 프런트 엔드에 RISC 디코더를 추가하는 것에 대해 이야기하는 경우 더욱 그렇습니다.
Peter Cordes

2
그것은 여전히 ​​잘못되었습니다. AES 새 명령어 (및 곧 출시 될 SHA 명령어) 및 PCLMULQDQ와 같은 기타 항목에는 전용 하드웨어가 있습니다. Haswell에서 AESENC는 단일 uop ( agner.org/optimize )로 디코딩 하므로 확실히 마이크로 코딩되지 않습니다. (디코더 는 4 uops 이상으로 디코딩하는 명령어에 대해 마이크로 코드 ROM 시퀀서를 활성화하기 만하면 됩니다.)
Peter Cordes

1
일부 새로운 명령어는 x86 명령어에서 사용할 수없는 방식으로 기존 기능을 사용하는 것이 맞습니다. 좋은 예는 BMI2 것 SHLX 그래서, 당신은 CL의 수를 놓을 필요없이, 그리고 여분의 마이크로 연산을 침해하지 않는 범위 내에서 가변 카운트 변화는 시프트 카운트가 0 인 경우 플래그는 수정되지 않은 있습니다 (진절머리 나는 86 플래그의 의미를 처리하는 데 필요한 수행 할 수 있습니다, SHL r/m32, cl이 FLAGS에 대한 입력 종속성이며 Skylake
Peter Cordes

귀하의 의견에 감사드립니다.
KOLANICH
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.