摘要:2025 年伊始,显卡领域就热闹非凡。英特尔的 Arc B580 表明,制造一款显存(VRAM)超过 8GB 的中端显卡仍是可行的。AMD 的 RDNA 4 延续了 AMD 长期以来的一种做法,即在追求高端产品之后,又觉得终究不太值得。英伟达在 2025 年也
本文由半导体产业纵横(ID:ICVIEWS)编译自Chips and Cheese
是时候来聊聊英伟达GeForce 6系列显卡了。
2025 年伊始,显卡领域就热闹非凡。英特尔的 Arc B580 表明,制造一款显存(VRAM)超过 8GB 的中端显卡仍是可行的。AMD 的 RDNA 4 延续了 AMD 长期以来的一种做法,即在追求高端产品之后,又觉得终究不太值得。英伟达在 2025 年也推出了新一代产品,他们的 5000 系列显卡已经发布,但市面上却一直没有现货。不过,数字越大越好,所以现在是时候来聊聊英伟达 GeForce 6 系列显卡了。
每一代游戏玩家都对更高质量的图形效果有所需求。没有人比英伟达更清楚这一点,因此英伟达 GeForce 6000 系列显卡旨在以足够高的帧率提供接近电影级的画质,以支持交互式游戏体验。GeForce 6000 显卡,简称 GeForce 6 系列,在设计时考虑到了图形渲染的高度并行性。与此同时,它们在可编程性方面实现了巨大飞跃,为实现复杂的游戏内特效开辟了令人兴奋的新可能。
图形渲染涉及在计算最终像素颜色之前,将顶点坐标从三维空间转换到二维屏幕空间,这一过程被称为光栅化。这两个阶段本质上都是并行任务,并且能很好地适配拥有大量执行单元阵列的硬件。因此,英伟达GeForce 6 系列是一种大规模并行处理的设备。它拥有大量的固定功能图形硬件,但该显卡的真正实力在于其一系列顶点着色器核心和像素着色器核心。这些可编程组件执行由游戏提供的着色器程序,而不是执行预设功能。它们还充当基本的构建模块,使英伟达能够针对不同的功耗、价格和性能目标进行扩展。英伟达 GeForce 6000 系列中最高端的芯片 NV40 配备了 6 个顶点着色器核心和 16 个像素着色器核心。
摘自英伟达发表于电气与电子工程师协会(IEEE)的论文
一台高度并行的机器需要一个高带宽的内存子系统来为其提供数据支持。英伟达 GeForce 6 系列产品最高可配备 256 位的 GDDR3 动态随机存取存储器,这使得它的内存总线宽度比典型的台式机中央处理器要宽得多。该显卡具有一个可被所有像素着色器核心和顶点着色器核心共享的二级纹理缓存,这使得获取到的纹理数据能够在短期内被重复使用。英伟达当时并未披露缓存的大小,但他们的目标是在有许多未命中情况同时发生时达到 90% 的命中率,而不是像中央处理器缓存那样常常追求 99% 的命中率。该显卡通过流行的加速图形接口(AGP)与主机系统进行通信,但也能支持即将推出的外设部件互连高速标准。
顶点着色器程序将坐标从三维空间转换到二维屏幕空间。这听起来可能是一项简单的任务,无非就是进行相机矩阵乘法和透视除法运算。但可编程的顶点着色器带来了新的技巧。例如,一个顶点着色器可以对纹理进行采样,并将其用作置换贴图。除了支持纹理访问之外,英伟达 GeForce 6000 的顶点着色器核心还支持分支、循环和函数调用。在真正的中央处理器之外,以前在其他设备上,这些功能中的大部分都是难以想象的,这展示了显卡发展的令人兴奋之处。
顶点着色器的执行从一个拥有 512 个条目的指令随机存取存储器中提取指令开始。英伟达使用来自驱动程序格式的 128 位顶点指令,这些指令会被转换为 123 位的内部格式。因此,该指令随机存取存储器的容量大约为 8 千字节。DirectX 9 的顶点着色器 3.0 标准规定至少要有 512 个指令插槽,并且英伟达的顶点着色器核心指令集架构与 DirectX 9 的高级着色器语言指令紧密契合。由于存在指令限制,着色器程序不会像中央处理器程序那样常常因指令缓存未命中而导致性能损失。此外,访问指令随机存取存储器不像缓存那样需要进行标签比较,从而节省了功耗。
从梅萨(Mesa)代码中推断出的英伟达 GeForce 6000 顶点着色器指令布局
DirectX 9顶点着色器的高级着色器语言指令大致可分为标量指令和矢量指令两类。标量指令包括诸如求平方根倒数之类的特殊运算。矢量指令通常涉及像乘加这样的基本运算,并且对由四个32位值组成的128位矢量进行操作。英伟达GeForce 6000的顶点着色器流水线针对这种设置进行了高度优化,并且具有独立的矢量流水线和标量流水线。每条指令集架构指令都同时指定了一个标量运算和一个矢量运算,使得顶点着色器核心能够在一个指令流中从两个维度利用并行性。DirectX 9着色器程序指定的矢量提供了矢量级别的并行性。英伟达的编译器发现的任何标量+矢量双指令发射机会都能提供额外的并行性。
并行性的第三个来源是多线程,它起到了隐藏延迟的作用。矢量运算插槽可以接受纹理采样指令。顶点着色器对内存的访问相对来说仍不常见,所以顶点着色器核心并没有一个与其纹理获取单元绑定的一级纹理缓存。英伟达预计,一个着色器程序需要20到30条指令来隐藏纹理获取延迟,而仅靠单个线程很难实现这一点。因此,每个顶点着色器核心最多可以跟踪三个线程,并在它们之间进行切换以隐藏延迟。
指令输入可来自寄存器或常量随机存取存储器。两者都由 128 位矢量条目组成,以匹配矢量执行宽度。寄存器文件分为输入寄存器、输出寄存器和临时寄存器。输入寄存器和输出寄存器各有 16 个条目,从着色器程序的角度来看,它们分别为只读和只写。临时寄存器文件支持读写操作,有 32 个条目。DirectX 9 的顶点着色器 3.0 规范允许一个着色器程序最多可寻址 32 个寄存器,但英伟达可能会在多个线程之间共享寄存器文件。如果是这样,一个顶点着色器程序应使用不超过 10 个临时寄存器,以实现最大占用率。
像素着色器,或称为片段着色器,承担了大量繁重的工作,因为渲染一个场景通常涉及处理的像素数量远多于顶点数量。相应地,英伟达 GeForce 6000 显卡最多可拥有 16 个像素着色器核心。像素着色器核心本身和顶点着色器核心一样具有高度可编程性,具备分支支持等诸多特性。然而,像素着色器核心的构建方式大不相同,以利用像素层面通常存在的更高并行性。
英伟达 GeForce 6000 的像素着色器使用 128 位指令,不过由于硬件差异,其编码与顶点着色器所使用的编码有很大区别。英伟达选择支持多达 65536 条像素着色器指令,远远超过了 DirectX 9 规定的最低 512 个指令插槽的规范。使用所有指令插槽将消耗 1 兆字节的存储空间,因此像素着色器核心可能会使用指令缓存。
“片段处理器每条流水线有两个 32 位浮点数着色器单元,片段会先经过这两个着色器单元和分支处理器,然后再循环返回整个流水线以执行下一组指令。”——《英伟达 GeForce 6 系列 GPU 架构》,作者埃米特・基尔加里夫(Emmet Kilgariff)和拉姆迪马・费尔南多(Ramdima Fernando)
英伟达的顶点着色器核心的运行方式很像带有三向同步多线程功能来隐藏延迟的中央处理器,而像素着色器核心则在多个线程间采用单指令多数据执行模型。这种并行性,通常被称为单指令多线程,是在通过使用多分量矢量在单个线程内实现的单指令多数据的基础上应用的。英伟达并非跟踪三个独立的线程,而是将许多像素着色器调用分组为一个矢量,并在硬件中有效地循环处理这些 “线程”。这种方法使英伟达能够以低成本同时处理数千个 “线程”,因为同一矢量中的线程必须执行相同的指令,且不能采取与其他线程不同的独立执行路径。只有正在处理的数据是不同的。
对于这种单指令多线程线程模型,程序员必须留意指令分歧带来的性能损耗。如果一个矢量内的不同线程在条件分支上选择了不同的方向,像素着色器核心将执行分支的两个方向,同时屏蔽掉非活动线程。这与顶点着色器核心的多指令多数据执行模型形成了鲜明对比,顶点着色器核心的执行模型即使在同一核心中运行的线程分支方向不同时,也允许无损耗的分支操作。英伟达建议在超过 1000 个像素的区域内保持分支的一致性,或者大约 256 个 2x2 像素的四边形区域,这暗示着矢量长度会非常长。
同时处理如此多的任务对于隐藏延迟至关重要,但这也给芯片内部存储带来了压力。DirectX 9 允许像素着色器寻址 32 个临时寄存器,这些寄存器的宽度依然为 128 位。要同时处理 256 个线程,每个像素着色器核心将需要 128 千字节的寄存器文件容量,而这在未来几年内的GPU中都难以实现。英伟达 GeForce 6000 使用的是较小的寄存器文件,其大小未知。英伟达表示,如果像素着色器程序使用四个或更少的 128 位寄存器,就可以让同时处理的线程数量达到最大值。大致估算一下,256 个线程,每个线程使用四个寄存器,将需要 16 千字节的寄存器文件容量。
像素着色器核心的两个 128 位矢量单元在不同的流水线阶段依次排列。每个周期,这两个单元都可以执行四次 32 位浮点数运算,不过只有位于下方的那个单元可以进行乘加运算。位于上方的单元能够处理特殊函数运算以及纹理地址计算。纹理运算在这两个执行单元阶段之间发出。32 位浮点数运算的峰值吞吐量为每个周期 12 次运算。例如,通过在上方阶段发出一次矢量 32 位浮点数乘法运算,在下方阶段发出一次 32 位浮点数乘加运算,就可以达到这一吞吐量。
从着色器程序的角度来看,上方和下方的矢量单元合起来每个周期可以完成两次矢量运算。与顶点着色器核心相比,像素着色器的顺序 “双指令发射” 布局使得上方的单元能够将其运算结果传递给下方的单元。因此,两条相互依赖的指令可以实现 “双指令发射”。除了对两个矢量单元的指令进行交叉编排外,英伟达的编译器还可以将作用于矢量元素不同子集的运算打包到一条指令中,这提高了单个线程内矢量单元的利用率。半精度浮点数运算甚至可以进一步提高吞吐量。对于图形渲染而言,完整的 32 位精度往往并非必需,尤其是在处理像素颜色的时候。像素着色器核心中的两个矢量执行单元都能以双倍速率执行半精度浮点数运算。使用半精度浮点数还能使这些数值对寄存器文件的占用减少一半,这反过来也可以提高占用率,进而更好地隐藏延迟。
输入寄存器未绘制出来,但所有的着色器程序都会使用输入寄存器,并将其计算结果写入输出寄存器。纹理采样是像素着色的一个重要部分,因此与顶点着色器核心相比,像素着色器核心有一条经过优化的纹理采样路径:每个核心都有一个一级纹理缓存,由芯片级的二级纹理缓存提供支持。
超越像素着色像素着色器程序通常输出像素颜色,但颜色实际上只是一些数值。英伟达 GeForce 6000 强大的大规模并行计算能力大部分集中在其像素着色器阵列中,而且其拥有的高浮点运算能力(每秒十亿次浮点运算,GFLOPs)对于非像素相关的任务来说也非常出色。此外,像素处理流水线的灵活性使得富有创造力的程序员几乎可以利用它完成任何事情。
例如,光线追踪是一种与光栅化在本质上截然不同的图形渲染方法,它涉及到在场景中追踪光线的路径。由于对计算能力的要求,光线追踪在很大程度上局限于离线应用。然而,英伟达GeForce 6系列的可编程像素着色器能够胜任实时渲染的任务,至少对于简单场景来说是如此。
来自斯坦福大学关于布鲁克(Brook)应用程序编程接口(API)的展示内容
其可能性不仅限于不同的图形渲染技术。可编程着色器的强大功能推动了一些新应用程序编程接口的发展,这些接口并非直接面向图形领域。斯坦福大学的布鲁克(Brook)应用程序编程接口针对 GPU 上的通用计算。它的编程模型与 GPU 针对并行任务进行优化的方式紧密相连。要熟悉这样一种模型可能需要一些时间来适应,尤其是因为大多数程序员一直以来学习的都是串行执行模型。但从事高度并行和高度规则的数据处理的研究人员和其他开发人员应该关注这些应用程序编程接口。
困难仍然存在在 GPU 上运行任何并行任务仍然存在重大障碍:着色器程序通过绑定的纹理来访问内存;与 CPU 端的内存分配相比,纹理的大小有限;与完整规格的 IEEE 754 标准实现相比,浮点精度往往不足;着色器在不使显示停顿的情况下只能执行很短的时间;在着色器执行期间无法修改纹理等等。
开发人员还必须在 CPU 和 GPU 的内存空间之间传输数据,以便为 GPU 提供数据并获取结果。后者可能会出现问题,因为 GPU 经过优化,是为了将像素着色器的输出作为一帧图像呈现在屏幕上,然后迅速用后续的一帧覆盖它。从 GPU 将数据复制回 CPU 可能会遇到主机接口的限制。
英伟达无疑意识到了这些局限性,并且正在努力解决这些问题。GeForce 6 系列除了支持 AGP 接口外,还将支持即将推出的 PCI Express 标准。PCI Express 增加的带宽使 GPU 更接近成为一个易于使用的并行加速器。
结语GeForce 6 系列的像素和顶点着色器流水线比以往任何时候都更加灵活,这表明英伟达正认真对待可编程着色器。对于当前的游戏工作负载而言,GeForce 6 系列引入的许多功能可能看起来有些过剩。很难想象有人会编写一个包含循环、函数调用和分支,且长度达数百条指令的着色器程序。GeForce 6 系列的功能表明,英伟达在基本图形渲染之外的特性方面展开竞争。这是摆脱固定功能硬件这一更大趋势的一部分,并且对 GPU 的发展有着令人兴奋的意义。也许很快,我们就不会再称这些显卡为 GPU 了,因为它们能做的远不止渲染图形。
尽管英伟达 GeForce 6000 系列显卡具有可编程性,但其仍然非常注重图形处理能力。英伟达的着色器指令集架构依旧与 DirectX 9 规范紧密相关,这确保了游戏中的着色器程序能在该硬件上良好运行。而且这款硬件相当强大;高端的 GeForce 6000 芯片拥有超过 2 亿个晶体管。这得益于国际商业机器公司先进的 130 纳米制程工艺才得以实现。要提供如此强大的处理能力,也需要可靠的供电支持,因此高端显卡使用了一对莫仕(Molex)连接器。莫仕连接器是经过时间考验的标准连接器,其粗针脚和电线能够可靠地为各种外围设备供电而不会熔化。
总之,GPU正以惊人的速度发展。2005 年是令人兴奋的一年。图形渲染技术正与国家经济齐头并进,向着 2008 年迈进,毫无疑问,每个人都在期待着那个光明的未来。
*声明:本文系原作者创作。文章内容系其个人观点,我方转载仅为分享与讨论,不代表我方赞成或认同,如有异议,请联系后台。
想要获取半导体产业的前沿洞见、技术速递、趋势解析,关注我们!
来源:半导体产业纵横一点号