最新消息: USBMI致力于为网友们分享Windows、安卓、IOS等主流手机系统相关的资讯以及评测、同时提供相关教程、应用、软件下载等服务。

Nvidia_GT200详解并行处理器

IT圈 admin 23浏览 0评论

2024年10月11日发(作者:员天成)

注:本文是Nvidia's GT200:into the parallel processor的中文译文,原文

作者为David Kanter博士

翻译本文的目的旨在明CUDA是如何在硬件上实现的,帮助编程人员编写和优化

CUDA程序

感谢Call of duty的指导

简介

过去十年中,计算领域出现了一个新的发展趋势:GPU通用计算。

由Intel,IBM,SUN,AMD和富士通生产的通用CPU虽然有了很大发展,但性能提高

速度却已经不能与与上世纪八十年代末九十年代初相比。单线程 处理的性能在

很大程度上受到了限制。这些限制一方面来自于通用计算程序中过低的指令级并

行;另一方面来自于“功率墙(Power Wall)”--集成电路的功率消耗的物理限

制。摩尔定律能够为处理器提供数以亿计的晶体管,但在为了运行单线程程序而

设计的处理器中,这些晶体管绝大多 数都被用于制造高速缓存(Cache)。这样做

虽然能把处理器功耗控制在合理的范围内,却阻碍了性能的进一步提高。

与此同时,GPU(图形处理单元)却有效的利用了数量巨大的晶体管资源。由于

图形渲染过程的高度并行性,GPU的性能按时间呈几何级数增长。同时,随着 GPU

计算能力的不断增长,一场GPU革命的时机也成熟了。GPU已经从由若干专用的

固定功能单元(Fixed Function Unit)组成的专用并行处理器,进化为了以通用

计算资源为主,固定功能单元为辅的架构。

这一进化过程的最初征兆出现在以ATI R300和Nvidia NV30位代表的DirectX 9

时代的GPU上。与前代的DirectX 8时代GPU相比,这一代的显卡拥有可编程的

像素和顶点渲染器,具有了一定的浮点计算能力。AMD收购ATI也是一个微妙的

转折点—大多数人当时还在关注 AMD与Intel在市场上的竞争,却没有意识到

AMD的收购行为有着更加复杂的动机。

支持DirectX 10的显卡的首次出现是一个分水岭:过去只能处理像素或者只能

处理顶点的专门功能处理单元被通用的统一着色器架构(Unified Shader

Architecture)取代了。以ATI R600和Nvidia G80为代表的DirectX10时代GPU

能够提供了超越以往任何GPU的能力:它们拥有数百个功能单元,能够处理一部

份过去只能在CPU上运行的数据 并行问题。需要强调的是,这些第一代的

DirectX 10 GPU只能处理“一部分”数据并行问题;它们只适合处理使用类似

阵列的数据结构,并且高度并行的问题。这些处理器的双精度浮点的计算能力十

分有限;它们虽 然基本符合IEEE规范对32位单精度浮点的大多数规定,但同

时也缺少对异常的处理,并省略了一些舍入模式。

这场革命的结果使计算领域的局势突然变得复杂了许多。现在不仅有各种各样的

CPU,也有了能够处理并行计算任务的GPU。这些产品的计算能力、可编程性和 适

合进行的计算任务各有不同。GPU、Cell和Niagara这一类的产品优缺点都十分

突出:在处理需要复杂分支的单线程任务时,它们的表现简直无药可 救;而在

处理充分并行的任务时,它们的性能比CPU能够强上数十甚至数百倍。在可编程

性上,Niagara和通用CPU的编程较为灵活,GPU很难处理复 杂的数据结构,而

Cell简直和程序员有仇。

讽刺的是,虽然ATI与CPU厂商AMD合并了,但另一家GPU厂商Nvidia却在通

用计算方面有更加全面而坚实的基础。本文主要介绍Nvidia GPU在通用计算领

域方面的应用,尤其是CUDA和最新一代GT200 GPU。GT200架构被使用在了面向

娱乐市场的GeForce,用于高性能计算的Tesla和用于专业渲染领域的Quadro

产品线上。本文并不深究 DirectX 10和OpenGL2.1中错综复杂的现代3D流水

线,只有在与CUDA的编程模型进行类比时才会提到。

CUDA 执行模型

Nvidia的并行编程模型被命名为CUDA(Computing Unified Device

Architecture,统一计算架构模型)。CUDA的基本思想是尽量使得开发线程级

并行(Thread Level Parallel),这些线程能够在硬件中被动态的调度和执行。

CUDA编程模型的重点是将CPU做为终端(Host),而GPU做为服务器 (Server)或

协处理器(Coprocessor),或者设备(Device),从而让GPU来运行一些能够被

高度线程化的程序。所以,GPU只有在 计算高度数据并行任务时才能发挥作用。

在这类任务中,需要处理大量的数据,数据的储存形式类似于规则的网格,而对

这些数据的进行的处理则基本相同。这类数 据并行问题的经典例子有:图像处

理,物理模型模拟(如计算流体力学),工程和金融模拟与分析,搜索,排序。

而需要复杂数据结构的计算如树,相关矩阵,链 表,空间细分结构等,则不适

用于使用GPU进行计算。找到程序中的计算并行度后,就能将一部分程序移植到

GPU上。运行在GPU上的程序被称为 Kernel(核)。核并不是完整的程序,而是

整个程序中的若干基本的关键数据并行计算步骤。

图1 CPU与GPU 串行程序,核,网格和线程块

除了数据并行的核以外,程序中也有标准的串行程序。如表一所示,在两个核之

间运行的就是串行 代码(如果两个核函数之间没有串行代码,它们就可以被合

并为一个)。理论上,串行代码的作用只是清理上个核,启动下一个核。但由于

目前的GPU的功能仍然 十分有限,串行部分的工作仍然十分可观。

核以网格(Grid)的形式执行,每个网格由若干个线程块(block)组成,每一个

线程块 又由最多512个线程(thread)组成。属于同一线程块的线程拥有相同的

指令地址,能够并行执行,并且能够通过共享存储器(Shared memory)和同步栅

(barrier)进行线程块内通信。同一线block中的thread开始于相同的指令地

址,理论上能够以不同的分支执行。但实 际上,在block内的分支因为性能方

面的原因被大大限制了。

核实质上是以block的形式执行的。CUDA引入了grid这个概念来表示一系列能

够(并 不一定)完全并行执行的线程块的集合。线程块的执行没有顺序,完全

并行。这是CUDA的一个很杰出的特性:无论是在一次只能处理一个线程块的GPU

上,还 是在一次能处理数十乃至上百个线程块的GPU上,这一模型都能很好的适

用。

目前,一个核函数只对应一个网格,但是未来这一限制极有可能会被解除。实际

使用中在一个网格 访问数据的同时,如果能够进行另一个网格的计算,则可以

有效的提高设备的利用率。但现在网格以串行代码划分了边界,不能很好的隐藏

访存延迟(Memory Access Latency)。

因为同一线程块中的线程需要共享数据,因此它们必须在同一个处理器(Nvidia

称之为 Streaming Mulitporcessor,缩写SM)中发射。线程块中的每一个线程

被发射到一个执行单元(Nvidia称之为Streaming Processor,缩写SP)。这

里涉及到了Nvidia GPU的内部架构,我们将在下一节进行详细说明。

CUDA存储器模型

除了执行模型以外,CUDA也规定了存储器模型(如图2所示)和一系列用于主

控CPU与GPU间通信的不同地址空间。图中红色的区域表示GPU片内的高速存储

器,橙色区域表示DRAM中的的地址空间。

图2 CUDA存储器模型

首先,是最底层的寄存器(register,REG)。对每个线程来说,寄存器都是私有的

--这与CPU中一样。如果寄 存器被消耗完,数据将被存储在本地存储器(local

memory)。本地存储器对每个线程也是私有的,但是数据是被保存在帧缓冲区

DRAM中,而不是片内的寄存器或者缓存中。线程的输入和中间输出变量将被 保

存在寄存器或者本地存储器中。

然后是用于线程间通信的共享存储器。共享存储器是一块可以被同一block中的

所有thread(上节提到过,一个block最多可以有512个 thread)访问的可读

写存储器。访问共享存储器几乎和访问寄存器一样快,是实现线程间通信的延迟

最小的方法。共享存储器可以实现许多不同的功能,如用 于保存共用的计数器

(例如计算循环迭代次数)或者block的公用结果(例如计算512个数的平均值,

并用于以后的计算)。

除此以外,还有两种只读的地址空间—常数存储器和纹理存储器(constant

memory and texture memory),它们是利用GPU用于图形计算的专用单元发展

而来的。常数存储器空间较小(只有64k),支持随机访问。纹理存储器尺寸则大

得多,并且支 持二维寻址(传统的缓存只支持一维寻址)。

这两种存储器实际存在于帧缓冲区DRAM中,但由于它们的只读性质,在GPU片

内可以进行缓存,从而加快访问速度。这两种存储器并不要求缓存一致性—它们

是只读的。但这也意味着如果CPU或者GPU要更改常数存储器或者纹理存储器的

值,缓存中的值在更新完成之前也无法使用。CUDA程序中,常数存储器用于 存

储需要经常访问的只读参数,而用插值或者滤波的纹理存储器访问对大尺寸的二

维或者三维图象或者采样序列进行高带宽的流式访问。

最后是全局存储器(global memory),使用的是普通的显存。整个网格中的任

意线程都能读写全局存储器的任意位置,并且既可以从CPU访问,也可以从CPU

访问。由于全局存储器是可写的,GPU片内没有对其进行缓存。

2024年10月11日发(作者:员天成)

注:本文是Nvidia's GT200:into the parallel processor的中文译文,原文

作者为David Kanter博士

翻译本文的目的旨在明CUDA是如何在硬件上实现的,帮助编程人员编写和优化

CUDA程序

感谢Call of duty的指导

简介

过去十年中,计算领域出现了一个新的发展趋势:GPU通用计算。

由Intel,IBM,SUN,AMD和富士通生产的通用CPU虽然有了很大发展,但性能提高

速度却已经不能与与上世纪八十年代末九十年代初相比。单线程 处理的性能在

很大程度上受到了限制。这些限制一方面来自于通用计算程序中过低的指令级并

行;另一方面来自于“功率墙(Power Wall)”--集成电路的功率消耗的物理限

制。摩尔定律能够为处理器提供数以亿计的晶体管,但在为了运行单线程程序而

设计的处理器中,这些晶体管绝大多 数都被用于制造高速缓存(Cache)。这样做

虽然能把处理器功耗控制在合理的范围内,却阻碍了性能的进一步提高。

与此同时,GPU(图形处理单元)却有效的利用了数量巨大的晶体管资源。由于

图形渲染过程的高度并行性,GPU的性能按时间呈几何级数增长。同时,随着 GPU

计算能力的不断增长,一场GPU革命的时机也成熟了。GPU已经从由若干专用的

固定功能单元(Fixed Function Unit)组成的专用并行处理器,进化为了以通用

计算资源为主,固定功能单元为辅的架构。

这一进化过程的最初征兆出现在以ATI R300和Nvidia NV30位代表的DirectX 9

时代的GPU上。与前代的DirectX 8时代GPU相比,这一代的显卡拥有可编程的

像素和顶点渲染器,具有了一定的浮点计算能力。AMD收购ATI也是一个微妙的

转折点—大多数人当时还在关注 AMD与Intel在市场上的竞争,却没有意识到

AMD的收购行为有着更加复杂的动机。

支持DirectX 10的显卡的首次出现是一个分水岭:过去只能处理像素或者只能

处理顶点的专门功能处理单元被通用的统一着色器架构(Unified Shader

Architecture)取代了。以ATI R600和Nvidia G80为代表的DirectX10时代GPU

能够提供了超越以往任何GPU的能力:它们拥有数百个功能单元,能够处理一部

份过去只能在CPU上运行的数据 并行问题。需要强调的是,这些第一代的

DirectX 10 GPU只能处理“一部分”数据并行问题;它们只适合处理使用类似

阵列的数据结构,并且高度并行的问题。这些处理器的双精度浮点的计算能力十

分有限;它们虽 然基本符合IEEE规范对32位单精度浮点的大多数规定,但同

时也缺少对异常的处理,并省略了一些舍入模式。

这场革命的结果使计算领域的局势突然变得复杂了许多。现在不仅有各种各样的

CPU,也有了能够处理并行计算任务的GPU。这些产品的计算能力、可编程性和 适

合进行的计算任务各有不同。GPU、Cell和Niagara这一类的产品优缺点都十分

突出:在处理需要复杂分支的单线程任务时,它们的表现简直无药可 救;而在

处理充分并行的任务时,它们的性能比CPU能够强上数十甚至数百倍。在可编程

性上,Niagara和通用CPU的编程较为灵活,GPU很难处理复 杂的数据结构,而

Cell简直和程序员有仇。

讽刺的是,虽然ATI与CPU厂商AMD合并了,但另一家GPU厂商Nvidia却在通

用计算方面有更加全面而坚实的基础。本文主要介绍Nvidia GPU在通用计算领

域方面的应用,尤其是CUDA和最新一代GT200 GPU。GT200架构被使用在了面向

娱乐市场的GeForce,用于高性能计算的Tesla和用于专业渲染领域的Quadro

产品线上。本文并不深究 DirectX 10和OpenGL2.1中错综复杂的现代3D流水

线,只有在与CUDA的编程模型进行类比时才会提到。

CUDA 执行模型

Nvidia的并行编程模型被命名为CUDA(Computing Unified Device

Architecture,统一计算架构模型)。CUDA的基本思想是尽量使得开发线程级

并行(Thread Level Parallel),这些线程能够在硬件中被动态的调度和执行。

CUDA编程模型的重点是将CPU做为终端(Host),而GPU做为服务器 (Server)或

协处理器(Coprocessor),或者设备(Device),从而让GPU来运行一些能够被

高度线程化的程序。所以,GPU只有在 计算高度数据并行任务时才能发挥作用。

在这类任务中,需要处理大量的数据,数据的储存形式类似于规则的网格,而对

这些数据的进行的处理则基本相同。这类数 据并行问题的经典例子有:图像处

理,物理模型模拟(如计算流体力学),工程和金融模拟与分析,搜索,排序。

而需要复杂数据结构的计算如树,相关矩阵,链 表,空间细分结构等,则不适

用于使用GPU进行计算。找到程序中的计算并行度后,就能将一部分程序移植到

GPU上。运行在GPU上的程序被称为 Kernel(核)。核并不是完整的程序,而是

整个程序中的若干基本的关键数据并行计算步骤。

图1 CPU与GPU 串行程序,核,网格和线程块

除了数据并行的核以外,程序中也有标准的串行程序。如表一所示,在两个核之

间运行的就是串行 代码(如果两个核函数之间没有串行代码,它们就可以被合

并为一个)。理论上,串行代码的作用只是清理上个核,启动下一个核。但由于

目前的GPU的功能仍然 十分有限,串行部分的工作仍然十分可观。

核以网格(Grid)的形式执行,每个网格由若干个线程块(block)组成,每一个

线程块 又由最多512个线程(thread)组成。属于同一线程块的线程拥有相同的

指令地址,能够并行执行,并且能够通过共享存储器(Shared memory)和同步栅

(barrier)进行线程块内通信。同一线block中的thread开始于相同的指令地

址,理论上能够以不同的分支执行。但实 际上,在block内的分支因为性能方

面的原因被大大限制了。

核实质上是以block的形式执行的。CUDA引入了grid这个概念来表示一系列能

够(并 不一定)完全并行执行的线程块的集合。线程块的执行没有顺序,完全

并行。这是CUDA的一个很杰出的特性:无论是在一次只能处理一个线程块的GPU

上,还 是在一次能处理数十乃至上百个线程块的GPU上,这一模型都能很好的适

用。

目前,一个核函数只对应一个网格,但是未来这一限制极有可能会被解除。实际

使用中在一个网格 访问数据的同时,如果能够进行另一个网格的计算,则可以

有效的提高设备的利用率。但现在网格以串行代码划分了边界,不能很好的隐藏

访存延迟(Memory Access Latency)。

因为同一线程块中的线程需要共享数据,因此它们必须在同一个处理器(Nvidia

称之为 Streaming Mulitporcessor,缩写SM)中发射。线程块中的每一个线程

被发射到一个执行单元(Nvidia称之为Streaming Processor,缩写SP)。这

里涉及到了Nvidia GPU的内部架构,我们将在下一节进行详细说明。

CUDA存储器模型

除了执行模型以外,CUDA也规定了存储器模型(如图2所示)和一系列用于主

控CPU与GPU间通信的不同地址空间。图中红色的区域表示GPU片内的高速存储

器,橙色区域表示DRAM中的的地址空间。

图2 CUDA存储器模型

首先,是最底层的寄存器(register,REG)。对每个线程来说,寄存器都是私有的

--这与CPU中一样。如果寄 存器被消耗完,数据将被存储在本地存储器(local

memory)。本地存储器对每个线程也是私有的,但是数据是被保存在帧缓冲区

DRAM中,而不是片内的寄存器或者缓存中。线程的输入和中间输出变量将被 保

存在寄存器或者本地存储器中。

然后是用于线程间通信的共享存储器。共享存储器是一块可以被同一block中的

所有thread(上节提到过,一个block最多可以有512个 thread)访问的可读

写存储器。访问共享存储器几乎和访问寄存器一样快,是实现线程间通信的延迟

最小的方法。共享存储器可以实现许多不同的功能,如用 于保存共用的计数器

(例如计算循环迭代次数)或者block的公用结果(例如计算512个数的平均值,

并用于以后的计算)。

除此以外,还有两种只读的地址空间—常数存储器和纹理存储器(constant

memory and texture memory),它们是利用GPU用于图形计算的专用单元发展

而来的。常数存储器空间较小(只有64k),支持随机访问。纹理存储器尺寸则大

得多,并且支 持二维寻址(传统的缓存只支持一维寻址)。

这两种存储器实际存在于帧缓冲区DRAM中,但由于它们的只读性质,在GPU片

内可以进行缓存,从而加快访问速度。这两种存储器并不要求缓存一致性—它们

是只读的。但这也意味着如果CPU或者GPU要更改常数存储器或者纹理存储器的

值,缓存中的值在更新完成之前也无法使用。CUDA程序中,常数存储器用于 存

储需要经常访问的只读参数,而用插值或者滤波的纹理存储器访问对大尺寸的二

维或者三维图象或者采样序列进行高带宽的流式访问。

最后是全局存储器(global memory),使用的是普通的显存。整个网格中的任

意线程都能读写全局存储器的任意位置,并且既可以从CPU访问,也可以从CPU

访问。由于全局存储器是可写的,GPU片内没有对其进行缓存。

发布评论

评论列表 (0)

  1. 暂无评论