developer tip

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

copycodes 2020. 9. 19. 11:28
반응형

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


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 명령어 세트 만 확장됩니다.


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

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

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

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

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


진짜 대답은 간단합니다.

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

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

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

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

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

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

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

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

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


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

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

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


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

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

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

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


@jalf's answer covers most of the reasons, but there's one interesting detail it doesn't mention: The internal RISC-like core isn't designed to run an instruction set anything like ARM/PPC/MIPS. The x86-tax isn't only paid in the power-hungry decoders, but to some degree throughout the core. i.e. it's not just the x86 instruction encoding; it's every instruction with weird semantics.

Let's pretend that Intel did create an operating mode where the instruction stream was something other than x86, with instructions that mapped more directly to uops. Let's also pretend that each CPU model has its own ISA for this mode, so they're still free to change the internals when they like, and expose them with a minimal amount of transistors for instruction-decode of this alternate format.

Presumably you'd still only have the same number of registers, mapped to the x86 architectural state, so x86 OSes can save/restore it on context switches without using the CPU-specific instruction set. But if we throw out that practical limitation, yes we could have a few more registers because we can use the hidden temp registers normally reserved for microcode1.


If we just have alternate decoders with no changes to later pipeline stages (execution units), this ISA would still have many x86 eccentricities. It would not be a very nice RISC architecture. No single instruction would be very complex, but some of the other craziness of x86 would still be there.

For example: left/right shifts leave the Overflow flag undefined, unless the shift count is one, in which case OF= the usual signed-overflow detection. Similar craziness for rotates. However, the exposed RISC instructions could provide flag-less shifts and so on (allowing use of just one or two of the multiple uops that usually go into some complex x86 instructions). So this doesn't really hold up as the main counter-argument.

If you're going to make a whole new decoder for a RISC ISA, you can have it pick and choose parts of x86 instructions to be exposed as RISC instructions. This mitigates the x86-specialization of the core somewhat.


The instruction encoding would probably not be fixed-size, since single uops can hold a lot of data. Much more data than makes sense if all insns are the same size. A single micro-fused uop can add a 32bit immediate and a memory operand that uses an addressing mode with 2 registers and a 32bit displacement. (In SnB and later, only single-register addressing modes can micro-fuse with ALU ops).

uops are very large, and not very similar to fixed-width ARM instructions. A fixed-width 32bit instruction set can only load 16bit immediates at a time, so loading a 32bit address requires a load-immediate low-half / loadhigh-immediate pair. x86 doesn't have to do that, which helps it not be terrible with only 15 GP registers limiting the ability to keep constants around in registers. (15 is a big help over 7 registers, but doubling again to 31 helps a lot less, I think some simulation found. RSP is usually not general purpose, so it's more like 15 GP registers and a stack.)


TL;DR summary:

Anyway, this answer boils down to "the x86 instruction set is probably the best way to program a CPU that has to be able to run x86 instructions quickly", but hopefully sheds some light on the reasons.


Internal uop formats in the front-end vs. back-end

See also Micro fusion and addressing modes for one case of differences in what the front-end vs. back-end uop formats can represent on Intel CPUs.

Footnote 1: There are some "hidden" registers for use as temporaries by microcode. These registers are renamed just like the x86 architectural registers, so multi-uop instructions can execute out-of-order.

e.g. xchg eax, ecx on Intel CPUs decodes as 3 uops (why?), and our best guess is that these are MOV-like uops that do tmp = eax; ecx=eax ; eax=tmp;. In that order, because I measure the latency of the dst->src direction at ~1 cycle, vs. 2 for the other way. And these move uops aren't like regular mov instructions; they don't seem to be candidates for zero-latency mov-elimination.

See also http://blog.stuffedcow.net/2013/05/measuring-rob-capacity/ for a mention of trying to experimentally measure PRF size, and having to account for physical registers used to hold architectural state, including hidden registers.

In the front-end after the decoders, but before the issue/rename stage that renames registers onto the physical register file, the internal uop format use register numbers similar to x86 reg numbers, but with room to address these hidden registers.

The uop format is somewhat different inside the out-of-order core (ROB and RS), aka back-end (after the issue/rename stage). The int/FP physical register files each have 168 entries in Haswell, so each register field in a uop needs to be wide enough to address that many.

Since the renamer is there in the HW, we'd probably be better off using it, instead of feeding statically scheduled instructions directly to the back-end. So we'd get to work with a set of registers as large as the x86 architectural registers + microcode temporaries, not more than that.

The back-end is designed to work with a front-end renamer that avoids WAW / WAR hazards, so we couldn't use it like an in-order CPU even if we wanted to. It doesn't have interlocks to detect those dependencies; that's handled by issue/rename.

It might be neat if we could feed uops into the back-end without the bottleneck of the issue/rename stage (the narrowest point in modern Intel pipelines, e.g. 4-wide on Skylake vs. 4 ALU + 2 load + 1 store ports in the back-end). But if you did that, I don't think you can statically schedule code to avoid register reuse and stepping on a result that's still needed if a cache-miss stalled a load for a long time.

So we pretty much need to feed uops to the issue/rename stage, probably only bypassing decode, not the uop cache or IDQ. Then we get normal OoO exec with sane hazard detection. The register allocation table is only designed to rename 16 + a few integer registers onto the 168-entry integer PRF. We couldn't expect the HW to rename a larger set of logical registers onto the same number of physical register; that would take a larger RAT.


Why don't they allow us compile programs so they will bypass CISC instructions and use RISC core directly?

In addition to the previous answers, the another reason is market segmentation. Some instructions are thought to be implemented in microcode rather than in hardware, so allowing anyone to execute arbitrary microoperations can undermine sells of new cpus with "new" more performant CISC instructions.

참고URL : https://stackoverflow.com/questions/5806589/why-does-intel-hide-internal-risc-core-in-their-processors

반응형