11

试图了解 cuda 的虚拟和真实架构之间的差异,以及不同的配置将如何影响程序的性能,例如

-gencode arch=compute_20,code=sm_20
-gencode arch=compute_20,code=sm_21
-gencode arch=compute_21,code=sm_21
...

NVCC手册中给出了以下解释,

GPU 编译是通过中间表示 PTX ([...]) 执行的,它可以被视为虚拟 GPU 架构的组装。与实际的图形处理器相反,这样的虚拟 GPU 完全由它提供给应用程序的一组能力或特性来定义。特别是,虚拟 GPU 架构提供(大部分)通用指令集,并且二进制指令编码不是问题,因为 PTX 程序总是以文本格式表示。因此,一个 nvcc 编译命令总是使用两种架构:一个计算架构来指定虚拟中间架构,以及一个真正的 GPU 架构来指定要在其上执行的预期处理器。要使这样的 nvcc 命令有效,真正的架构必须是虚拟架构的实现(以某种方式)。这将在下面进一步解释。选择的虚拟架构更多地是对应用程序所需的 GPU 功能的说明:使用最小的虚拟架构仍然允许第二个 nvcc 阶段使用最广泛的实际架构。相反,指定一个提供应用程序未使用的功能的虚拟架构会不必要地限制可以在第二个 nvcc 阶段指定的可能 GPU 集。使用最小的虚拟架构仍然允许第二个 nvcc 阶段使用最广泛的实际架构。相反,指定一个提供应用程序未使用的功能的虚拟架构会不必要地限制可以在第二个 nvcc 阶段指定的可能 GPU 集。使用最小的虚拟架构仍然允许第二个 nvcc 阶段使用最广泛的实际架构。相反,指定一个提供应用程序未使用的功能的虚拟架构会不必要地限制可以在第二个 nvcc 阶段指定的可能 GPU 集。

但仍然不太了解不同配置对性能的影响(或者,可能只影响物理 GPU 设备的选择?)。特别是,这句话让我最困惑:

特别是,虚拟 GPU 架构提供(大部分)通用指令集,并且二进制指令编码不是问题,因为 PTX 程序总是以文本格式表示。

4

4 回答 4

7

NVIDIA CUDA 编译器驱动程序 NVCC用户指南部分关于GPU 编译提供了对虚拟和物理架构以及如何在构建过程中使用这些概念的非常全面的描述。

虚拟架构指定代码所针对的功能集。下表显示了虚拟架构的一些演变。编译时,您应该指定具有足够功能集的最低虚拟架构,以使程序能够在最广泛的物理架构上执行。

虚拟架构功能列表(来自用户指南)

compute_10   Basic features
compute_11   + atomic memory operations on global memory
compute_12   + atomic memory operations on shared memory
             + vote instructions
compute_13   + double precision floating point support
compute_20   + Fermi support
compute_30   + Kepler support

物理架构指定了 GPU 的实现。这为编译器提供了指令集、指令延迟、指令吞吐量、资源大小等,以便编译器可以优化地将虚拟架构转换为二进制代码。

可以为编译器指定多个虚拟和物理架构对,并让编译器将最终的 PTX 和二进制文件返回到单个二进制文件中。在运行时,CUDA 驱动程序将为已安装的物理设备选择最佳表示。如果fatbinary文件中未提供二进制代码,则驱动程序可以使用 JIT 运行时实现最佳 PTX 实现。

于 2013-02-09T02:40:17.253 回答
3

“虚拟架构”代码将由即时编译器编译,然后再加载到设备上。AFAIK,它与 NVCC 在离线构建“物理架构”代码时调用的编译器是同一个编译器 - 所以我不知道最终的应用程序性能是否会有任何差异。

基本上,每一代 CUDA 硬件都与上一代二进制不兼容——想象一下下一代英特尔处理器采用 ARM 指令集。通过这种方式,虚拟架构提供了可以为兼容硬件编译的 CUDA 应用程序的中间表示。每一代硬件都引入了需要新指令的新特性(例如原子、CUDA 动态并行)——这就是您需要新虚拟架构的原因。

基本上,如果你想使用 CDP,你应该为 SM 3.5 编译。您可以将其编译为设备二进制文件,该二进制文件将具有用于特定 CUDA 设备生成的汇编代码,或者您可以将其编译为 PTX 代码,该代码可以编译为任何提供这些功能的设备生成的设备汇编。

于 2013-02-08T21:24:01.510 回答
1

虚拟架构指定了 GPU 具有哪些功能,而真实架构指定了它是如何做到的。

我想不出任何具体的例子。一个(可能不正确的)示例可能是一个虚拟 GPU,它指定了卡的核心数量,因此生成的代码针对该核心数量,而真正的卡可能有更多的冗余(或者由于制造而减少了一些)错误)和一些映射到实际使用的内核的方法,这些方法可以放在第一步生成的更通用的代码之上。

您可以认为 PTX 代码有点像汇编代码,它以特定架构为目标,然后可以编译为特定处理器的机器代码。一般来说,针对正确类型的处理器的汇编代码将生成更好的机器代码。

于 2013-02-08T19:14:07.390 回答
-1

通常情况下,nvidia 写的文档会导致人们(包括我自己)变得更加困惑!(也许只有我!)

你关心性能,基本上这说的是不要(可能)但你应该。基本上GPU架构就像大自然。他们在上面运行了一些东西,然后发生了一些事情。然后他们试图解释它。然后他们把它喂给你。

最后可能应该运行一些测试,看看什么配置给出了最好的结果。

虚拟架构旨在让您自由思考。您应该遵守这一点,尽可能多地使用线程,您几乎可以将所有内容分配为线程和块的数量,没关系,它将被转换为 PTX 并且设备将运行它。

唯一的问题是,如果您为每个块分配超过 1024 个线程,您将得到 0 作为结果,因为设备(真正的架构)不支持它。

或者例如您的设备支持 CUDA 1.2,您可以在代码中定义双指针变量,但同样会得到 0 作为结果,因为设备无法运行它。

性能方面,您必须知道每 32 个线程(例如 warp)必须访问内存中的一个位置,否则您的访问将被序列化等等。

所以我希望你现在已经明白了,这是一门相对较新的科学,而 GPU 是一个非常复杂的硬件架构,每个人都在努力充分利用它,但这是一个测试游戏,对实际情况有一点了解CUDA 背后的架构。我建议搜索 GPU 架构,看看虚拟线程和线程块是如何实际实现的。

于 2013-02-08T19:24:02.123 回答