CUDA虚拟架构与真实架构的区别

13

尝试理解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集合。
以上内容解释了虚拟GPU体系结构的概念以及为什么需要使用两个体系结构,但不太清楚不同配置如何影响性能(或者只影响物理GPU设备的选择?)。尤其是以下声明最令人困惑:
特别地,虚拟GPU架构提供了一个(在很大程度上)通用的指令集,因为PTX程序始终以文本格式表示,所以二进制指令编码不是问题。
4个回答

9
The NVIDIA CUDA Compiler Driver 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实现。

只是为了那些好奇的人:NVIDIA现在在他们的文档中使用的术语是“真实架构”,而不是“物理架构”。 - leopold.talirz

3
"虚拟架构"代码将在装载到设备之前由即时编译器编译。据我所知,这个编译器与NVCC在离线构建"物理架构"代码时使用的编译器相同——因此我不知道应用程序性能是否会有任何差异。
基本上,每一代CUDA硬件都与上一代二进制不兼容——想象一下Intel处理器的下一代采用ARM指令集。这样,虚拟架构提供了一个中间表示CUDA应用程序的方式,可以为兼容的硬件进行编译。每一代硬件都会引入新特性(例如原子操作、CUDA动态并行),需要新的指令集——这就是为什么需要新的虚拟架构。
基本上,如果您想使用CDP,则应该编译为SM 3.5。您可以将其编译为设备二进制代码,其中包含特定CUDA设备生成的汇编代码,或者您可以将其编译为PTX代码,然后可以编译成任何提供这些功能的设备生成的设备汇编。

1
虚拟架构规定了GPU的能力,而真实架构则规定了它如何实现这些能力。例如,虚拟GPU可能规定了显卡的核心数目,因此生成的代码会针对该核心数目进行编写,而实际显卡可能会有更多的核心用于冗余(或因制造误差而少一些),并且还有一些映射到实际使用的核心的方法,这可以在第一步生成的更通用的代码之上进行放置。
您可以将PTX代码视为汇编代码,其针对特定的架构,可以编译成特定处理器的机器代码。针对正确类型的处理器的汇编代码,通常会生成更好的机器代码。

-1
通常情况下,NVIDIA的文件会让人们变得更加困惑(包括我自己)!(或许只有我这样!)
你关注的是性能,基本上就是说不要(可能)被迷惑,但是应该去研究。基本上,GPU架构就像自然一样。他们在上面运行某些东西,然后尝试解释它。然后再传递给你。
最后,应该运行一些测试,看看哪种配置可以得到最佳结果。
虚拟架构是为了让你自由思考而设计的。你应该遵循这个原则,使用尽可能多的线程,你可以将几乎所有东西都分配为线程和块数,无论如何,它都将被转换为PTX并在设备上运行。
唯一的问题是,如果你将超过1024个线程分配给一个块,你将会得到0秒的结果,因为设备(真正的架构)不支持它。
例如,如果您的设备支持CUDA 1.2,您可以在代码中定义双精度变量,但是您仍将得到0秒的结果,因为设备根本无法运行它。

关于性能问题,你必须知道每32个线程(例如批次)必须访问内存中的单个位置,否则你的访问将被串行化等。

所以我希望你现在已经理解了重点,这是一个相对较新的科学,GPU是一种非常复杂的硬件架构,每个人都在努力发挥它的最大潜力,但这需要不断测试和对CUDA实际架构的一些了解。我建议搜索GPU架构,并查看虚拟线程和线程块如何实际实现。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接