跳到主要内容
Itanium 不是输给编译器,是输给“编译时”

Itanium 不是输给编译器,是输给“编译时”

画唠
画唠

· 阅读约 2 分钟

“Itanium 怎么死的?”这题有一句流传最广的标准答案:编译器没跟上。架构超前,软件拉胯,理想编译器要是写出来,它就成了。

先把话放这儿:这句话是错的,而且错得挺彻底。HN 上有个讨论翻 Itanium 的旧账(从 Windows XP for Itanium 那台机器聊起的),一堆当年在场的人出来回忆,我顺着把这事重新画了一遍——画完发现,Itanium 缺的根本不是编译器的智力,是编译时压根不存在的信息。

我第一版的理解跟所有人一样,画出来是条挺顺的线:

   VLIW 架构 ──► 需要聪明的编译器 ──► 编译器没写出来 ──► 性能拉胯 ──► 死

顺吧。太顺了。顺到后来我反应过来 HP 和 Intel 里那帮人不可能全是傻子,才开始怀疑这张图本身。

画张图。VLIW 干的事,本质是把“哪几条指令同时发出去”这个决定,从硬件手里搬到编译器手里:

        谁来决定"这几条指令同时执行"?

   x86 乱序:  ●运行时,硬件看着现场定
   VLIW:      ●编译时,编译器提前排死

打个比方:一家餐厅排班。x86 是店里有个领班,客人进门了看现场随手调人;VLIW 是厨师长提前一周把下周的班表排死——而他排表的那一刻,不知道下周三晚上来的是三十人的旅行团还是三个散客。

厨师长不够聪明吗?不是。是他排表的时候,那批客人还没决定来不来。

这张图我盯着看了半天,咔哒一下扣上了 ✨ 问题从来不在“编译器什么时候能写出来”,在“编译器干活的那个时刻,运行时的信息还不存在”。分支往哪走,取决于用户输入;cache 里还剩什么,取决于隔壁进程上一毫秒干了什么。这些在编译时就是随机的。

等等等等,先别急。要是这么明显,当年那帮人为什么信?

去翻 VLIW 的学术底子就明白了。讨论里有人引了学术界的账:VLIW 研究长期拿科学计算、数值程序的指令轨迹当基准。两类负载的轨迹放一起,差别是这样:

   科学计算:
   load → 浮点乘 → 浮点加 → store → load → …
   (循环整齐,内存访问规律,分支几乎不拐弯)

   通用程序:
   if → 调用 → 返回 → if → 异常? → cache miss → …
   (三步一个岔路,五步一个意外)

在第一张轨迹上,静态调度是真的成立。循环体翻来覆去就那几步,编译器提前排好,一点毛病没有。所以当年的性能数据没造假——都是真的,只是全来自一个“世界永远循规蹈矩”的平行宇宙。

然后是那个让我盯着看了半天的细节。Bob Colwell 的口述历史里说,早期 Itanium 的性能预测,依据是三十行手写汇编跑出来的模拟。有人当场觉得不对劲,Andy Grove 把质疑打断,接着推。三十行。手工调度。浮点例程。也就是说

画唠
画唠

把被讲玄的概念用图 + 比喻 + 动手实验拆到咔哒扣明白,错的也保留。

查看主页 →