为什么要把高级语言编译为机器码,难道不能直接用高级语言制造CPU吗?

知乎热榜6个月前发布 NIUC!
1,534 0 0

invalid s的回答

简单说,CPU内部是非常复杂的;别说高级语言了,一条机器指令的执行流程都可能不是三五百字说的清的。

为什么要把高级语言编译为机器码,难道不能直接用高级语言制造CPU吗?

这是最简单的8088CPU功能框图。我们可以看到它里面包含一组通用寄存器、一组地址寄存器、一个算术逻辑单元(ALU)和一个指令队列。

每条指令要分4个步骤执行,包括取指、译码、执行、写回结果四个阶段;如果指令2需要指令1的结果才能执行,这就叫指令相关。此时指令队列就会停滞,直到指令1写回结果指令2才能执行。

同时,还有一些条件分支/跳转指令,这些指令往往也需要取得前面一条指令的执行结果后,才知道该执行哪个分支,此时指令队列中已经取指/译码的指令就可能并不是下一条要执行的指令,于是就必须清空指令队列、到正确地方读取指令后才能继续。这会大幅降低指令吞吐率。

稍微先进一些的80486还有虚拟内存管理、数学协处理器等,情况就更复杂了。

而现代CPU嘛……

为什么要把高级语言编译为机器码,难道不能直接用高级语言制造CPU吗?

这是相对简单的AMD zen CPU架构。

Zen架构将以四个核心为一个群组,AMD将其称为“CPU Complex”(CCX),也就是“CPU复合体”的意思。 [2]
每一个CPU复合体内包含四个Zen CPU核心,但它们是彼此完全独立的,不像推土机架构那样,彼此不会共享任何单元 [2]。

拾取四个x86指令 [3]、操作缓存指令、四个整数单元 [3]、两个存储/载入单元(支持72个乱序载入) [3]、两个浮点单元(128-bit FMAC) [3]、4-way 64KB一级指令缓存 [3]、8-way 32KB一级数据缓存 [3]、8-way 512KB二级缓存 [3]、8MB共享三级缓存

这一堆名词解释起来太啰嗦了。

简单说,你可以认为现代CPU内部内置了一个编译器,可以把机器码指令编译成微码micro op、然后同时驱动每个核心里面的一大堆部件同时工作。

比如说,zen可以通过scheduler单元,让6条整数micro op同时执行(包括simd指令);同时还能同时执行4条浮点micro op指令。

除此之外,它还得管理好各级cache;它的指令队列(超级流水线)更长(我记得能到40级左右),为了避免流水线载入指令无效耽误时间,现代CPU还必须搞“分支预测”,当预测正确时整条指令流水线可以同时执行;但一旦预测失误就必须清空流水线、消除已经被(错误)执行的指令造成的影响,然后重新开始——这个代价是非常大的。

换句话说,现在的机器码已经是非常高级的指令了,高级到必须先编译成micro op才能执行;而且每种CPU都有不同的硬件配置(scheduler数量、整数单元数量、SIMD单元数量、浮点单元数量等等),必须巧妙安排才能尽量让CPU核心内部所有执行单元满负荷工作。这就涉及到了乱序执行、多发射、超线程等概念。

这么多核心,数据一致性也是个极大的问题。这几年已经爆出不少安全bug,其中一部分就和CPU乱序执行时的数据一致性等问题相关。

你看,机器码翻译到微码都这么复杂了……


然后,高级语言也不是直接“翻译”成机器码就行的。它同样要做海量的优化,以求充分发挥CPU性能。这些优化同样极其复杂、很多优化还不能自动化(比如选择更加cache友好的算法、牺牲精度提高速度等等)……

这些极其复杂、还在不断变化的东西显然没法做进CPU——它已经够复杂了。

事实上,某些x86机器码完全可以看作高级语言语句了。比如movs,一次移动一整个字符串。

但,CPU已经太复杂了。把不那么“贴近硬件”的指令放进去不难,但效果并不好。

总之,你的确可以设计直接支持某种高级语言的CPU,那不过相当于在CPU里面集成个高级语言编译器罢了。但这显然是没必要的,这个功能放进CPU只会白白占用芯片面积、更易引入错误、同时使得编译器固化、难以支持最新的优化技术。

© 版权声明

相关文章

暂无评论

暂无评论...