第 8 章

极客滥用与算力暗流

二十一世纪初的某个秋天,圣何塞。城市边缘一家汽车旅馆的会议室里,空气凝重而躁动。这里聚集着三十多人,多数穿着随意,胸前的名牌透着学术机构或小型技术公司的名字。没有媒体,没有商业展示,盘子里堆着些硬实的饼干。这是一场自发的、甚至带点地下色彩的聚会。他们自称“通用计算拓荒者”,探讨的议题在当时主流科技界听来近乎天方夜谭:如何让那块躺在个人电脑机箱里、只为游戏和三维设计服务的图形处理器(GPU),去解决流体动力学、分子模拟或者金融衍生品定价的数学难题。

房间前方,投影幕布上滚动着一段晦涩的代码。主讲人是斯坦福的一位博士研究生,名叫伊恩·巴克。他个子很高,语速急促,眼中闪烁着发现秘密的兴奋。“我们想算二维涡旋,”他指着屏幕,“超级计算机排队要几周。但我们有这个。”他弯腰从桌下拖出一台打开侧盖的台式机,内部一块显卡的散热风扇嗡嗡作响。“英伟达的GeForce3。它的片段着色器,理论上每秒能处理上亿个像素的浮点运算。我们‘骗’它。”

幻灯片切换,屏幕上并非游戏画面,而是色彩剧烈变化的流体涡旋图案。“数据伪装成纹理坐标,存进显存。计算公式被硬塞进本该计算光照和颜色的着色器程序里。GPU以为自己在高速绘制一幅复杂的、不断变化的画,实际上,它在帮我们解方程。”台下传来理解的低笑。这正是他们的日常苦役:将科学数据——速度、压力、能量——精心包装成图形API能识别的“货物”,如纹理、顶点、颜色值,然后塞进为渲染优化的图形管线里,期待硬件在“绘画”过程中,意外地完成通用数学运算。

“但代价巨大,”巴克声音低沉下来,投影切换到布满错误代码的终端界面,“最大的瓶颈不是计算,是伪装本身。把物理模型硬塞进图形管线的‘格式转换’和‘着色器游戏’,比设计算法还耗时。更关键的是,硬件是黑箱。我想直接管理显存特定区域,或者精细调度着色器单元?门都没有。图形API像一道森严的海关,所有数据必须伪装成‘纹理’或‘顶点’才能通关。我们需要的是钥匙,能打开后面那道通往计算引擎的大门!”

共鸣在房间里迅速蔓延。一位来自德国马克斯·普朗克研究所的研究员举手:“我们上周用片段着色器做蛋白质折叠的势能计算。为了绕开限制,不得不玩‘渲染到纹理’的把戏——把中间结果画到一张看不见的纹理上,下一帧再读出来。性能损失相当可观,代码变成一团乱麻,而且完全依赖特定型号显卡驱动的行为。一次驱动更新,就可能让几个月的工作归零。”

“我们试过更激进的,”角落里一位来自初创公司的程序员压低声音,“直接操作显卡的底层寄存器。”提到“底层寄存器”,房间气氛微妙一凝,随即被更兴奋的低语打破。“逆向出手册了?”“部分,靠猜和试错。”他展示了屏幕上一段截图,那是异常简陋、布满十六进制数和神秘注释的C代码片段。“看这里,直接向GPU某个控制单元写入指令,绕过OpenGL。理论上,可以强制把顶点着色器当作纯粹的向量处理器,忽略几何变换要求。我们在实验室几块卡上跑通过,速度提升明显。问题是,这完全是非官方的,像走钢丝,而且每个新架构都得从头逆向。”

这段粗糙的、试图突破标准API封锁的代码,以及开发者脸上混合着创造快感与巨大挫折的神情,正是那个时代通用计算于图形处理器(GPGPU)探索的缩影。他们是一群在“特许农场”里偷偷开垦“荒地”的拓荒者。驱动力是纯粹的“算力饥渴”:科学计算、信号处理乃至早期机器学习模型对并行浮点运算的需求爆炸式增长,而中央处理器(CPU)的性能提升曲线已然放缓。GPU内部,成千上万个简单的着色器核心排列整齐,理论上提供着恐怖的并行吞吐量,却被一套为实时图形严格优化的、封闭且固定的软硬件管线牢牢禁锢。

这场聚会及其弥漫的亢奋与挫败,以各种零散的速度和渠道,渗透回英伟达位于圣克拉拉的总部。最初,这些声音在公司内部激不起太大涟漪。英伟达正全神贯注于一场关乎生死存亡的图形王座争夺战。GeForce3技术虽领先,但竞争对手步步紧逼;同时,微软Xbox项目带来的庞大订单与苛刻要求消耗着巨量工程资源。从近乎夭折到登顶王座的惊险历程,让整个公司神经紧绷。在市场部和大多数产品团队眼中,GPU的价值坐标清晰无误:更高的游戏帧率、更逼真的光影效果、更复杂的三维场景——一切服务于玩家和设计师。那些在大学实验室和小众论坛里流传的、把GPU当数学协处理器来“折磨”的古怪代码,在多数人看来是边缘群体的猎奇,或至多是“有趣的学术演示”,与公司的核心商业逻辑隔着一道鸿沟。

然而,并非所有人视而不见。在英伟达的硬件架构团队,以及少数直接与外部开发者打交道的工程师中,这些“滥用”行为激起了复杂的波澜与深刻的思索。巴克在聚会上遇到的那位抱怨API转换成本的开发者,此前就曾通过电子邮件,直接向英伟达一位负责开发者技术支持的工程师倾诉:“……我们在用你们的硬件做非凡的事,但你们的软件在设置重重障碍!我们把GPU当成强大的并行计算引擎,你们却只把它当作画图工具出售。如果能提供一个更直接、更开放的计算接口,哪怕只是实验性的,你们硬件的潜力将被释放十倍,应用领域将远超你们想象……”

这封邮件没有消失在收件箱的海洋。它被转发到了更多内部人士那里,包括几位资深架构师。他们开始有意识地收集散落的信息:学术会议上那些用着“图形加速”委婉措辞却实质进行通用计算的论文;来自国防与能源部门国家实验室、语气模糊却需求强烈的算力呼吁;甚至一些量化交易团队对超高吞吐数值运算流露出的兴趣。这些信号杂乱、微弱,淹没在季度财报会议上关于游戏市场份额的喧嚣讨论中,但对于具有技术洞察力和战略敏感度的工程师及中层管理者而言,它们汇聚成一股隐约的“暗流”。

这股暗流的核心,在于硬件冗余算力与软件封闭性之间日益扩大的裂痕。GPU的晶体管数量遵循摩尔定律狂飙,但图形应用——尤其是游戏——对算力的消耗模式并非完全线性。画面复杂到一定程度后,单纯增加多边形带来的视觉提升边际效应递减,芯片内部的着色器单元时常处于“闲置”状态。与此同时,为了确保图形渲染的绝对稳定和实时性,驱动程序和图形API层构建了一套复杂、严格且不透明的资源管理与调度机制。任何试图突破这套机制的“通用计算”尝试,都会遭遇效率暴跌和兼容性噩梦。

一个更具体的案例引起了内部更广泛的关注。一家名为PeakStream的小型初创公司(成立于2006年),尝试利用GPU集群进行金融风险建模。他们取得了惊人的初步性能结果,远超同期CPU集群。然而,他们在技术博客上大吐苦水,称最大瓶颈并非计算本身,而是数据在CPU内存与GPU显存之间传输的延迟,以及将计算任务“图形化”的繁琐过程。他们不得不投入巨资定制特殊硬件接口和修改驱动,成本高昂且难以维护。PeakStream的遭遇,像一盏聚光灯,照亮了GPGPU道路上最根本的障碍:缺乏一条为通用计算设计的、高效且标准化的数据通路和编程模型。他们的困境极具代表性,公司虽后来被谷歌收购,但其揭示的技术痛点在英伟达内部报告中被反复引用。

英伟达内部,关于“是否以及如何回应”的讨论,开始在茶水间、会议室、甚至食堂的餐桌旁悄然进行。反对的声音依然强大且理由充分:开发一套全新的、面向通用计算的硬件接口和编程环境,意味着巨额研发投资,会分散图形主业的资源;这可能会激怒微软等操作系统与API提供商,他们倾向于将计算功能纳入自身的DirectX或未来系统API统一管理;最关键的是,市场在哪里?游戏公司不需要,消费用户更不需要,专业可视化有OpenGL,谁会为了一小撮科学家和黑客的“玩具”买单?这看起来是一条投入产出比极低、风险极高的歧路。

但支持者——主要是那些直接接触过GPGPU开发者、深谙芯片架构潜力的工程师——看到了不同的图景。他们关注的不是当下的小市场,而是潜在的巨大生态位。他们认为,如果英伟达不主动打开这扇门,迟早会有别人打开。或许是竞争对手(ATI也在进行类似的低调探索),或许是未来的计算架构(如Cell处理器)会侵蚀GPU的潜在价值。更深层的思考在于,他们隐约感觉到,将GPU的能力从“渲染像素”解放到“处理任何可并行化数据”,不仅仅是增加一个新功能,而可能从根本上重新定义“GPU是什么”,以及“英伟达卖的究竟是什么”。这不再是卖一块更快的游戏显卡,而是卖一种通用的“并行计算能力”。

这种思考,与公司最高层弥漫的战略焦虑产生了微妙共鸣。正如前一章所揭示,英伟达在登顶图形霸主后,已切身感受到来自微软DirectX的软件主导权、英特尔集成显卡的侵蚀、以及PC产业周期性波动的巨大压力。公司命运被捆绑在游戏和PC行业的战车上,天花板清晰可见。黄仁勋和他的核心团队,正处在一种“在辉煌巅峰仍未停止为生存思考”的状态。他们知道必须离开脚下这片看似稳固的山峰,但通往更广阔天地的“窄门”究竟在何处?

极客们近乎“暴力破解”的“滥用”行为,以及由此暴露出的硬件潜力与软件枷锁之间的尖锐矛盾,意外地为英伟达指明了方向。它并非来自营销部门的市场调研,也非来自华尔街的增长预测,而是来自技术边缘地带最真实、最原始的实践与呐喊。这些开发者用非官方甚至非法的手段,证明了GPU内部并行计算引擎的巨大价值,同时也尖锐地揭示了现有图形软件生态对此的严重束缚。

真正的转折,发生在英伟达内部一次技术评审会上。资深架构师约翰·尼科尔斯,长期关注芯片的计算效率与可编程性,提交了一份经过深思的提案。他没有纠缠于具体产品型号或市场份额,而是展示了一系列数据:GPGPU相关研究论文的增长曲线、PeakStream类公司的案例、以及内部模拟显示的、若能突破图形管线限制后GPU理论计算吞吐量的飞跃。然后,他提出了一个概念:“我们一直在优化一个为特定应用(图形)设计的专用处理器。但如果,我们将其中大规模并行计算的核心单元,从图形管线的‘后台工厂’推到‘前台’,并为它创建一个全新的、直接面向通用计算的前端呢?一个与图形API平行,但更底层、更开放、更专注于数据并行计算的编程模型。”

这个提议在当时听起来近乎革命,甚至有些危险。它意味着要撼动公司赖以成功的图形技术栈的根基,创建一个全新的软件平台。会议室里质疑声再起:“谁来写程序?市场部能卖掉它吗?”尼科尔斯回答:“初期,就是那些正在‘欺骗’我们硬件的人。他们会成为第一批用户,也是最热忱的布道者。他们带来的不只是用例,更是对计算本质的洞察。然后,我们可以围绕他们构建工具、库和社区。这就像……为一片已经自发开垦的土地,提供规划、灌溉和道路系统。”

黄仁勋全程沉默倾听。他不易被单纯的技术愿景打动,决策始终基于对竞争格局和长期生存能力的冷酷计算。但尼科尔斯的陈述,与他内心的危机感和战略直觉强烈共振。他看到两个关键点:第一,将GPU通用化,是摆脱对微软DirectX等外部软件框架过度依赖的潜在路径——如果英伟达能自己定义计算的编程模型,就能在价值链上占据更核心的位置。第二,这可能是将公司从周期性极强的“图形芯片公司”,转型为持续增长的“计算平台公司”的历史性机遇。算力,而非图形,才是未来数字世界的硬通货。

他提出了一个问题,后来在公司内部被反复引用:“如果我们打开底层,释放这些算力,我们是在制造风险,还是在创造一种新的、无法被轻易替代的价值?” 片刻沉默后,他自己给出了答案:“那些极客已经在用我们的硬件做这件事了,无论我们是否允许。我们无法阻挡趋势。但如果我们不主动提供一条平坦的大路,他们就会继续在荆棘丛中开辟小径,最终可能绕过我们,或者促使竞争对手提供这条路。那么,我们将沦为纯粹的硬件供应商,利润被软件生态锁死。我们必须成为那个提供‘平坦大路’的人。我们必须成为标准。”

“必须成为标准。”这句话为争论定下了基调。这不是一次基于现有市场的决策,而是一次面向未来生态的、带有强烈赌性的投资。决策的核心,不是研发一款新显卡,而是要启动一个代号为“CUDA”的秘密项目。CUDA,Compute Unified Device Architecture,计算统一设备架构。它的目标宏伟而清晰:为英伟达的GPU创建一套全新的、开放的、面向通用并行计算的软硬件架构。这需要设计新的指令集、新的内存层次模型、新的线程调度机制,以及至关重要的,一套全新的编程语言扩展和编译器工具链,让开发者能够用类似C语言的语法直接编写在GPU上运行的计算程序,彻底告别“伪装数据”的荒诞时代。

这是一个巨大的承诺。它意味着英伟达未来的产品线将同时维护两套截然不同的软件栈:图形(DirectX/OpenGL)和计算(CUDA)。研发资源将被大幅分流。初期几乎看不到明确的商业回报,只会增加成本和复杂度。华尔街的分析师们完全无法理解——一家图形公司为何要耗费巨资去触碰一个看似毫无“钱途”的学术和小众市场?黄仁勋的决定,在当时的外部世界看来,近乎不可理喻。

然而,从这一年开始,CUDA项目在高度保密的状态下,在英伟达内部悄然启动。资源被配置,最顶尖的架构师和软件工程师被抽调组建团队。与此同时,那些散布在全球高校与实验室里的GPGPU先驱们,依然在用他们粗糙的代码和“欺骗”手段继续着计算梦想。他们尚不知晓,在圣克拉拉,一场旨在响应他们呐喊、并意图从根本上重塑计算版图的工程浩劫已然拉开序幕。他们的“滥用”与“破解”,即将催生一个前所未有的、正式的通用计算生态。

当极客们仍在为绕过图形API的层层关卡而绞尽脑汁时,他们无意中施加的持续压力,已与芯片内部涌动的算力暗流汇聚,终于冲开了硬件厂商战略决策的闸门。CUDA的种子,在边缘需求的持续敲打与公司顶层生存焦虑的共同催化下,开始萌芽。这并非天才的灵光乍现,而是一个组织在敏锐感知到底层技术脉动后,做出的一次关乎未来身份的、沉重而关键的结构性回应。通用计算的赌桌已经摆好,筹码正在悄然堆叠,而牌局的参与者,远不止英伟达一家。一个以算力为核心竞争力的时代,在隐秘的代码、艰难的决策与边缘群体的执着探索中,正悄然逼近。

就在英伟达内部关于“是否打开底层”的争论逐渐平息,代号CUDA的秘密项目开始艰难爬升之时,另一场更为具体、也更为磨人的战役,在公司的软件工程部门内部悄然打响。硬件架构团队提出的计算单元分离和独立内存访问模型的构想,落到软件团队面前,变成了一道几乎无解的方程式:如何为一个尚未存在的硬件抽象,设计一套人类可读、可写、可调试的编程语言和编译工具链?

抽调来组建核心团队的工程师,大多是图形驱动和编译器领域的佼佼者,习惯于在既定且严苛的图形API框架内,将性能压榨到极限。如今,他们面临的却是一片空白。他们的任务不是优化,而是创造。早期的技术头脑风暴会,常常陷入僵局。一位资深的编译器架构师,习惯性地在白板上画出复杂的指令调度流程图,试图套用CPU编译器优化的经验,却发现GPU成千上万线程的并发执行模型、层次化的内存结构(全局内存、共享内存、纹理内存、寄存器文件),与他熟悉的顺序执行或粗粒度线程模型截然不同。“我们像是在为外星文明设计书写系统,”他在一次会议后沮丧地对同事说,“我们甚至不确定他们如何‘思考’。”

转折点来自对“滥用”代码的逆向解读。团队收集了巴克那类开发者散落在网络论坛、学术附录和私人邮件列表中的代码片段。这些代码凌乱、充满注释和“hack”,但却是理解用户如何与扭曲的GPU硬件“搏斗”的最佳教材。他们看到,开发者们最痛苦的根源,在于被迫进行的“角色扮演”:将计算任务精心包装成图形渲染的各个阶段。数据必须伪装成纹理(适合存储大量浮点数),计算核心被强行塞入着色器程序(顶点着色器做粗粒度并行计算,片段着色器做更细粒度的像素级计算),而计算结果的输出,更是依赖“渲染到纹理”这种迂回而低效的方式,将帧缓冲区的内容读回。

一个更清晰的认知开始浮现:用户不需要一个更聪明的“画家”GPU,他们需要一个坦率承认自己是“计算引擎”的GPU。这意味着,新的编程模型必须抛弃“伪装”的思维。它应该提供显式的数据搬运指令,告诉硬件“把这些浮点数从CPU内存直接搬到我指定的GPU计算区域”,而不是假装在传输纹理。它应该允许程序员定义纯粹的计算函数(后来称为“内核”),并直接调度成千上万个线程去执行它,而不是费力地将算法拆解成图形管线的顶点和片段处理阶段。这本质上是一种“去图形化”的宣言,它要求软件栈与硬件最核心的计算单元进行一种前所未有的、直接的对话。

然而,这种直接性带来了新的复杂性。图形API的复杂性,在于它为了解决实时渲染中的一系列棘手问题(遮挡剔除、纹理过滤、多重采样抗锯齿等)而构建了庞大而固定的管线。而新的计算模型,则把并行编程本身的复杂性——线程管理、内存一致性、竞争条件、负载均衡——直接暴露给了程序员。这相当于从一个精心打理、规则繁复但路径固定的“皇家园林”,一下子来到一个需要自己开垦、规划并承担所有风险的“原始荒野”。

团队内部爆发了激烈争论。一方主张应提供高度的抽象和自动化,像图形API一样隐藏硬件细节,让“科学计算领域的专家”也能轻松使用。另一方,尤其是那些深谙并行计算和性能关键应用的工程师,坚持认为,那些真正的目标用户——正是现在那些不惜写畸形代码也要榨取GPU性能的极客和科学家们——他们渴望的正是控制和透明度。“他们不是来画画的游客,”一位架构师在争吵中拍桌子,“他们是来征服雪山的登山者!你给他们缆车和铺好的小路,他们反而会觉得你侮辱了他们的能力。他们需要的是精良的装备、详尽的地图和对危险地形的完全掌控!”

最终,一种妥协但偏向后者的理念占据了上风:提供一套底层、高效、接近硬件本质的编程接口,同时辅以较高层次的库和工具来降低入门门槛。程序员可以选择像操作CPU内存一样操作GPU内存(通过显式的cudaMemcpy等API),也可以选择使用简化内存管理的运行时。他们需要编写在GPU上并行执行的代码块,并通过特殊语法(如<<<grid, block>>>启动配置)来指明如何将计算任务映射到成千上万的硬件线程上。这无疑增加了初期学习曲线,但一旦掌握,用户将获得对硬件能力的直接洞察和控制,这正是当前“滥用”行为中他们梦寐以求的。

就在软件团队苦苦寻觅语言设计和编译器实现的路径时,硬件架构团队的另一项发现,为他们提供了至关重要的启示。在分析新一代GPU架构(NV40及后续)的设计时,一位架构师注意到,图形管线中一个关键阶段——像素着色器——在内部实现上,已经开始表现出超越其原定图形功能的灵活性。这些着色器单元被设计为高度可编程,能够执行复杂的数学指令序列。更重要的是,其内部的指令发射和寄存器文件设计,为了支持图形算法的多样性,已经隐含了对通用标量和向量运算的潜在支持。

这个发现像一道闪电。团队意识到,他们不必从零开始设计一个全新的“计算核心”。图形管线的可编程着色器单元,其底层硬件逻辑已经具备了通用计算引擎的雏形。CUDA编程模型的任务,从某种意义上说,是“解放”这些单元,将它们从图形管线的序列化流(顶点->光栅化->片段)中剥离出来,变成可以独立、并行、自主地获取数据并执行计算任务的“计算客户端”。这需要在硬件上增加直接的数据加载/存储通道(后来的“Load/Store”单元),在软件上设计一种新的、更通用的指令集(PTX,一种并行线程执行的虚拟指令集),并让编译器能够将类似C的代码高效地编译成这些指令,直接调度这些单元执行。

这个认知极大地推动了工作。团队开始围绕这个核心理念构建整个技术栈。PTX被设计为一种与具体GPU指令集隔离的中间层,允许同一个CUDA程序在不同代的GPU上运行,硬件差异由驱动程序中的后端编译器处理。内存模型被明确划分为多个层次:每个线程私有的寄存器、由线程块共享的快速共享内存(Shared Memory)、以及容量巨大但延迟较高的全局设备内存(Global Memory)。程序员必须显式管理数据在这些层次间的移动,这在当时被视为一种复杂性,但后来被证明是实现极致性能的关键控制点。

在开发工具链的过程中,团队还从极客们遇到的挫折中汲取了“负经验”。他们看到,开发者最痛恨的就是代码在一次驱动更新后莫名崩溃。因此,CUDA工具链的一个早期设计目标就是“向后兼容”和“稳定性承诺”。即便底层硬件指令集演进,PTX层和编译器会保证旧代码依然能运行。这需要在驱动内部构建一个极其复杂的、多层编译和优化的流水线,初期带来了巨大的工程挑战,但为开发者提供了图形API从未有过的可预测性和代码资产保护。

当这些技术细节逐渐清晰,另一个问题凸显出来:用户如何开始?总不能直接把一本厚厚的《CUDA编程指南》丢给外部开发者,然后祈祷他们能自己摸索出来。团队意识到,他们需要一个“灯塔”项目,一个足够有影响力、能清晰展示CUDA威力的“Hello World”。经过内部讨论,他们将目光投向了一个在科学计算领域极为经典且计算密集的问题:大规模矩阵乘法,或者更进一步的,线性代数库。他们决定投入资源,开发一个基于CUDA的BLAS(基础线性代数子程序)库,命名为CUBLAS。

这是一个战略性决策。CUBLAS不仅仅是一个示例,它直接对标科学计算和工业界的核心需求。通过将这个库开源(或低门槛提供),并展示其相比CPU BLAS(如Intel MKL)或当时GPU的图形化方案数倍乃至数十倍的性能提升,英伟达可以直接向目标开发者群体——工程师、科学家、研究人员——证明CUDA的价值不是理论上的,而是实实在在、可以立刻用来解决他们核心问题的。这个决策,标志着CUDA项目从纯内部的技术架构开发,开始转向构建一个可触达、可使用的外部生态系统。

于是,在极客们仍在黑暗中摸索“着色器游戏”的岁月里,在英伟达总部一间间灯火通明的会议室和实验室里,一套旨在终结所有“伪装”和“破解”的完整计算体系正在悄然成型。它包含了新的硬件思考、新的虚拟指令集、新的编程语言扩展、新的内存模型、新的编译器,以及一个即将到来的、作为开路先锋的数学库。这条路依然漫长且充满风险,内部的资源争夺和外部的市场质疑从未停止。但方向已定,工程的齿轮开始沉重而坚定地转动。那些在汽车旅馆里发出的呐喊,经过技术内部的共振、转化与再创造,正在凝聚成一套有形的、复杂的、准备推向世界的语言和工具。通用计算的“通行证”——CUDA,正在被精心设计和铸造之中。