找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 89|回复: 4

DAY82:阅读Compute Capabilities

[复制链接]
发表于 2018-10-10 15:22:39 | 显示全部楼层 |阅读模式
GTC
H. Compute Capabilities
The general specifications and features of a compute device depend on its compute capability (see Compute Capability).
Table 13 gives the features and technical specifications associated to each compute capability.
Floating-Point Standard reviews the compliance with the IEEE floating-point standard.
Sections Compute Capability 3.x, Compute Capability 5.x, Compute Capability 6.x, and Compute Capability 7.x give more details on the architecture of devices of compute capability 3.x, 5.x, 6.x, and 7.x respectively.

H.1. Features and Technical SpecificationsTable 13. Feature Support per Compute Capability
Feature Support
Compute Capability

(Unlisted features are supported for all compute capabilities)
3.0
3.2
3.5, 3.7, 5.0, 5.2
5.3
6.x
7.x

Atomic functions operating on 32-bit integer values in global memory (Atomic Functions)
Yes

atomicExch() operating on 32-bit floating point values in global memory (atomicExch())
Yes

Atomic functions operating on 32-bit integer values in shared memory (Atomic Functions)
Yes

atomicExch() operating on 32-bit floating point values in shared memory (atomicExch())
Yes

Atomic functions operating on 64-bit integer values in global memory (Atomic Functions)
Yes

Atomic functions operating on 64-bit integer values in shared memory (Atomic Functions)
Yes

Atomic addition operating on 32-bit floating point values in global and shared memory (atomicAdd())
Yes

Atomic addition operating on 64-bit floating point values in global memory and shared memory (atomicAdd())
No
Yes

Warp vote and ballot functions (Warp Vote Functions)
Yes

__threadfence_system() (Memory Fence Functions)

__syncthreads_count(),
__syncthreads_and(),
__syncthreads_or() (Synchronization Functions)

Surface functions (Surface Functions)

3D grid of thread blocks

Unified Memory Programming

Funnel shift (see reference manual)
No
Yes

Dynamic Parallelism
No
Yes

Half-precision floating-point operations: addition, subtraction, multiplication, comparison, warp shuffle functions, conversion
No
Yes

Tensor Core
No
Yes

Table 14. Technical Specifications per Compute Capability
Compute Capability

Technical Specifications
3.0
3.2
3.5
3.7
5.0
5.2
5.3
6.0
6.1
6.2
7.0
7.5

Maximum number of resident grids per device (Concurrent Kernel Execution)
16
4
32
16
128
32
16
128

Maximum dimensionality of grid of thread blocks
3

Maximum x-dimension of a grid of thread blocks
231-1

Maximum y- or z-dimension of a grid of thread blocks
65535

Maximum dimensionality of thread block
3

Maximum x- or y-dimension of a block
1024

Maximum z-dimension of a block
64

Maximum number of threads per block
1024

Warp size
32

Maximum number of resident blocks per multiprocessor
16
32
16

Maximum number of resident warps per multiprocessor
64
32

Maximum number of resident threads per multiprocessor
2048
1024

Number of 32-bit registers per multiprocessor
64 K
128 K
64 K

Maximum number of 32-bit registers per thread block
64 K
32 K
64 K
32 K
64 K
32 K
64 K

Maximum number of 32-bit registers per thread
63
255

Maximum amount of shared memory per multiprocessor
48 KB
112 KB
64 KB
96 KB
64 KB
96 KB
64 KB
96 KB
64 KB

Maximum amount of shared memory per thread block 27
48 KB
96 KB
64 KB

Number of shared memory banks
32

Amount of local memory per thread
512 KB

Constant memory size
64 KB

Cache working set per multiprocessor for constant memory
8 KB
4 KB
8 KB

Cache working set per multiprocessor for texture memory
Between 12 KB and 48 KB
Between 24 KB and 48 KB
32 ~ 128 KB
32 or 64 KB

Maximum width for a 1D texture reference bound to a CUDA array
65536

Maximum width for a 1D texture reference bound to linear memory
227

Maximum width and number of layers for a 1D layered texture reference
16384 x 2048

Maximum width and height for a 2D texture reference bound to a CUDA array
65536 x 65535

Maximum width and height for a 2D texture reference bound to linear memory
65000 x 65000

Maximum width and height for a 2D texture reference bound to a CUDA array supporting texture gather
16384 x 16384

Maximum width, height, and number of layers for a 2D layered texture reference
16384 x 16384 x 2048

Maximum width, height, and depth for a 3D texture reference bound to a CUDA array
4096 x 4096 x 4096

Maximum width (and height) for a cubemap texture reference
16384

Maximum width (and height) and number of layers for a cubemap layered texture reference
16384 x 2046

Maximum number of textures that can be bound to a kernel
256

Maximum width for a 1D surface reference bound to a CUDA array
65536

Maximum width and number of layers for a 1D layered surface reference
65536 x 2048

Maximum width and height for a 2D surface reference bound to a CUDA array
65536 x 32768

Maximum width, height, and number of layers for a 2D layered surface reference
65536 x 32768 x 2048

Maximum width, height, and depth for a 3D surface reference bound to a CUDA array
65536 x 32768 x 2048

Maximum width (and height) for a cubemap surface reference bound to a CUDA array
32768

Maximum width (and height) and number of layers for a cubemap layered surface reference
32768 x 2046

Maximum number of surfaces that can be bound to a kernel
16

Maximum number of instructions per kernel
512 million



H.2. Floating-Point Standard
All compute devices follow the IEEE 754-2008 standard for binary floating-point arithmetic with the following deviations:
  • There is no dynamically configurable rounding mode; however, most of the operations support multiple IEEE rounding modes, exposed via device intrinsics;
  • There is no mechanism for detecting that a floating-point exception has occurred and all operations behave as if the IEEE-754 exceptions are always masked, and deliver the masked response as defined by IEEE-754 if there is an exceptional event; for the same reason, while SNaN encodings are supported, they are not signaling and are handled as quiet;
  • The result of a single-precision floating-point operation involving one or more input NaNs is the quiet NaN of bit pattern 0x7fffffff;
  • Double-precision floating-point absolute value and negation are not compliant with IEEE-754 with respect to NaNs; these are passed through unchanged;
Code must be compiled with -ftz=false, -prec-div=true, and -prec-sqrt=true to ensure IEEE compliance (this is the default setting; see the nvcc user manual for description of these compilation flags).
Regardless of the setting of the compiler flag -ftz,
  • Atomic single-precision floating-point adds on global memory always operate in flush-to-zero mode, i.e., behave equivalent to FADD.F32.FTZ.RN,
  • Atomic single-precision floating-point adds on shared memory always operate with denormal support, i.e., behave equivalent to FADD.F32.RN.
In accordance to the IEEE-754R standard, if one of the input parameters to fminf(), fmin(), fmaxf(), or fmax() is NaN, but not the other, the result is the non-NaN parameter.
The conversion of a floating-point value to an integer value in the case where the floating-point value falls outside the range of the integer format is left undefined by IEEE-754. For compute devices, the behavior is to clamp to the end of the supported range. This is unlike the x86 architecture behavior.
The behavior of integer division by zero and integer overflow is left undefined by IEEE-754. For compute devices, there is no mechanism for detecting that such integer operation exceptions have occurred. Integer division by zero yields an unspecified, machine-specific value.
http://developer.nvidia.com/content/precision-performance-floating-point-and-ieee-754-compliance-nvidia-gpus includes more information on the floating point accuracy and compliance of NVIDIA GPUs.


回复

使用道具 举报

 楼主| 发表于 2018-10-10 15:38:36 | 显示全部楼层
嗯嗯. 本章表格主要说明了各种计算能力了下的卡的"特性"的异同。请注意该表格列出了目前所有支持的计算能力的卡的对比情况.而计算能力也往往是一般用户口中的"代", 某代某代的卡如何如何。
它决定了用户在编写代码的时候, 所能用到的特性; 有些特性是如此重要, 也往往决定了用户购买的选择.例如说, 用户的代码需要动态的细分处理, 需要使用动态并行(DP)的能力, 那么根据此表格, 显然就不能上3.0的一代Kepler.例如说, 前几天我们论坛有个帖子, 有一个很奇特的需求, 要对一张图片的所有像素的值进行求和. 我们当时在论坛提醒用户, 需要注意整数类型的累加后的溢出情况(例如使用16-bit, 32-bit等等的整数类型), 则该用户基于精度考虑, 可能会选择使用浮点类型,特别的, 他可能会选择double来进行简单的原子累加(block内部进行无原子操作的规约累加, 然后就地在global memory可选的进行double累加原子操作, 规避二次kernel启动),
则这个特性需要他至少购买计算能力6.0, 也就是Pascal这一代或者更高的卡,才能完成他的设计目标.
但是需要说明的是, 往往越新的一代卡, 折算到单位计算性能下的单价越贵.例如很多人现在已经拿到了2080(例如我们的七月, 括号里的请删除),它主打的是新的Tensor Core的特色(不用考虑RT Core, 用CUDA的人暂时用不到它), 而单精度的单位GFlops下的性能却没有显著提升, 价格却高了不少,则用户实际上可以考虑购买上一代的1080之类的卡, 甚至同样的预算能上1080Ti, 从而取得更好的性价比.
这样根据实际项目对计算能力的主要特性的取舍不同, 用户可以作出一定预算下的正确采购要求.

回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-10 16:12:10 | 显示全部楼层
sisiy 发表于 2018-10-10 15:38
嗯嗯. 本章表格主要说明了各种计算能力了下的卡的"特性"的异同。请注意该表格列出了目前所有支持的计算能力 ...

本表格需要特别注意的是两个地方,  一个是半精度的支持, 一个是Tensor Core, 本章节的表格只作出了支持, 或者不支持的说明, 但实际上这两点在支持的情况下, 外加计算能力5.3的特例(TX1)

但这只是支持情况, 在支持的卡上, 至少保证了200%速率(相比该卡上的单精度速率)的半精度通用性能,但是在支持Tensor Core的卡上(主要是7.0和7.5, 后者也就目前我们说的图灵, 包括你用的2080), 具有非常显著的专用半精度性能, 也就是在矩阵乘法的情况下, 具有800%的半精度性能提升(同样和该卡的单精度性能相比), 我们都知道, 特别的, 在深度学习的情况下, 主要就用两个操作,一个是矩阵乘法, 一个是卷积,
而前者又可能占用了大头, 所以哪怕在通用的支持FP16半精度的情况下, 用户也应该尽量考虑使用7.0+, 虽然本表格将5.3/6.x/7.x都简单的划成了支持半精度, 但用户从实用的角度, 应当考虑购买新卡(或者新的嵌入式计算设备,例如还没有出来的Xavier? 而不是5.X/6.X的TX1/TX2)。

类似的, 该表格还对7.X的Tensor Core支持统一划成了支持, 但实际上这两代的Tensor Core差别非常大,后一代的Tensor Core还支持INT8和INT4计算, 具有非常显著的性能提升(例如INT8是1600%), 用户在特定的需求的情况下, 例如密集的INT8计算, 应当只能考虑7.5的图灵卡,(也包括一些挖矿用户, 但好在现在挖矿不景气, BTM之类的币种正在被人忽视中, 否则Turing又会暴涨一段时间, 万幸)

此外, 考虑到现在的需要用的卡只有6.X+了, 该表格还没有给出6.X+的主要特性:

(1)支持深度学习指令(INT8), 至少具有400%的性能(例如__dp4a()函数, 手册没说), 该函数在Pascal(6.1)+上被支持, 而且比较通用(相比Tensor Core 2代的1600%极度专用化的INT8加速), 很多图像处理的用户应当考虑这点.

(2)增强的Unified Memory, Pascal+的Unified Memory得到了极大增强, 但是这里也只是简单的和3.X/5.X等等一起, 简单的标注了支持.

实际上Unified memory也可以划成至少两代, 3.X/5.X上的是初级的第一代, 6.X起具有非常显著的特性提升. 这个等我们到了后面的Unified Memory再详细说.

所以用户对这个计算能力导致的特性异同的表格, 应当注意这种粗略的说法, 从而在选购和应用的时候作出更恰当的判断.(实际上, 6.1的家用Pascal(不包含GP100), 这两个特性是最主要的特性了. 去掉这两个特性的Pascal等于只是Maxwell---但制程作出了优化而已(从28nm))

第二个表格, 则说明了在CUDA使用的情况下, 一些硬件本身的限制情况.主要的大部分都是相同的(以前的计算能力还有复杂的启动block形状的限制不同, grid内部的blocks数量的限制不同, 这些现在如今都被取消了)
你可以看到, 标准的1024个线程的最大block大小, 最多(2^31 - 1)的X方向的Blocks数量,这些都减轻了用户的记忆负担, 和提高了程序的设计时候的思考量.
我说一下这个表格对普通的CUDA用户所主要造成的影响:
(1)Shared Memory / L1大小,
根据我们之前的章节, Shared Memory等于一种随机访问性能好(不同Banks的不同深度可以同时对用户提供数据服务), 用户可控的L1 Cache,而L1是全自动的.

所以不同的计算能力的情况下的不同的Shared Memory大小往往影响性能(一般情况下, 越大越好),但是这里需要指出几个例外,一个是计算能力3.7, 它具有超常的非常巨大的Shared Memory(112KB/SM), 而目前已知的3.7的卡只有K80,

K80是NV对失败的Kepler一代所作出的最后努力, 它将2个SM的资源累加到了一个SM上,所以你会看到在K80上具有惊人的Shared Memory大小.同理你会看到所有的寄存器大小都是256KB(也就是本表格的64K个),但只有K80是512KB的惊人大小, 这同样是因为它将2个SM的资源合成了1个SM.
所以说, 如果Kepler一代到现在还有价值的卡, 只有K80了.


然后同样的你会看到7.X的Shared Memory似乎比较小.但是这里需要指出的是, 7.X的SM里面(Volta/Turing), SP数量只有减半的, 它们的大小实际上等同于乘以2,也就是相当于192KB和128KB的等价效果(而不是96KB和64KB), 这点需要特别注意.

类似的, 专业卡的6.0(GP100), 看上去Shared Memory还不如6.1的家用卡大,但实际上它的SM里面的SP也是减半的, 同样的SP规模折算下, 它具有双倍的资源,实际上6.0和6.1对比, 等价于128KB vs 96KB, 而不是64KB vs 96KB. 这点用户也需要知道.

此外, 部分嵌入式的设备, 具有较少的寄存器数量, (例如5.3和6.2的TX1/TX2,只有标准的每个block能用的寄存器数量的一半),这导致你至少需要在这些设备上, 每个SM能上2个block, 才能有效的利用资源. 这点也需要注意一下.

注意最后该表格给出了一个最大512M条指令, 每个kernel的限制.这个实际上是很搞笑的,
哪怕在每条指令8B大小的情况下(例如6.X, 实际上稍微大一点), 512M条指令的Kernel, 编译出来也有4GB大了,如果是7.X, 16B每条指令, 则有8GB那么大,
我从来没有见过如此巨大的kernel.但是考虑到总是有人喜欢问:"我的kernel能写的多大" "我的kernel写了这么长没事吗"这样的问题,该表格给出这种指标, 也很搞笑和无奈的.所以也挺好的.


此外, 关于本表格的能绑定的surface数量是16这个问题,  实际上是一个历史问题, 具体可以参考我们之前章节的bindless, 无需绑定的那种surface, texture之类的, 后者没有这种限制.也没有每个绑定的纹理在启动每个kernel所带来的固定额外开销.






回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-10 16:27:51 | 显示全部楼层
sisiy 发表于 2018-10-10 16:12
本表格需要特别注意的是两个地方,  一个是半精度的支持, 一个是Tensor Core, 本章节的表格只作出了支持,  ...

关于第三部分, N卡所遵循的浮点标准(IEEE-754)
这里主要说明了几点:
没有全局可以配置的动态的圆整(取整)模式,很多处理器上(例如X87?), 具有用户可调的浮点取整模式,
但是N卡作为GPU,没有这种全局的模式, 而是每条指令都可以自行设定.回到具体的CUDA C用户, 用户可以注意到有些intrinsic functions具有_rz()之类的结尾, 就是起到这种作用的
(欢迎参考我们之前的章节中说的4大圆整模式)

此外, 本章节说的NaN的问题,
部分处理器带有多种NaN处理模式,
很多人以前在我们的群里, 三天两头的发, 我计算出错了,出现了一些奇特的值(数值printf的时候带有一些字母)
这里需要注意Quiet NaN和Signaling NaN的区别,
后者还是NaN(异常值), 只是带有额外的描述信息.(例如你0/0时候的结果,就属于NaN)
本章节说明了, 如果单精度的运算过程中, 输入运算数据有异常值NaN的, 结果都将只是Quiet NaN,具体的细节可以自行搜索一下.实际上wikipedia上有很详细的描述, 如果我没记错的话.
然后还说了双精度运算的时候, NaN数据会被Passthrough, 直接传递异常值的负载信息.这点也需要注意.但无论如何, 出现了NaN, 并导致NaN在程序的多次迭代计算中传播开来,最后导致整体结果面目全非, 一般是用户的锅,
需要详细检查中间过程的结果数据, 和/或输入值的数据, 做好它们的异常值处理.此外, 关于C++ Exception, 我们的GPU目前并不支持计算过程中的exception报告, 而是会产生Inf/Nan/0这种数据,这也是很正常的选择, 因为同时在GPU上执行的数据执行是海量的, 如果像常规的CPU那样, 中途暂停一个或者多个kernel的计算, 报告CPU, 然后CPU单独处理, 将会是灾难性的, GPU啥都不用干了.你会得到海量的并发异常的.

此外, 本段落还说了, 可以全局的用某些参数来控制精度信息(你可以选择更高性能的, 但精度较低的; 和较慢的, 但精度较高的代码生成,这点在之前说过, 请参考我们之前的相关章节. 注意该章节提到的SFU部分)
然后这里强调的是,  原子操作有时具有较低的精度:

在global memory上的原子累加, 总是直接将denormals(或者叫subnormal number), 当成0来处理.

而在Shared memory上的同样的累加, 支持这种接近0的subnormal number, 并不将它们当成0来处理.

(将很接近0的subnormal值当成0来处理会损失精度),

忘记了subnormal numbers是什么了? 之前我们的章节提到过:当浮点数小到非常接近0的时候, 已经无法用原始的浮点格式(指数浮动)表示了, 此时为了尽量保存有效数字, 将转换成使用固定指数的定点数表示, 此时float之类的都将不再能保持23-bit这种有效数字位数, 但同时不将这些非常小的数值当成0处理, 而是尽量保存为定点位数, 有一位算一位, 从而尽量能够为用户保存精度。
当使用或者出现subnormal number的时候, 往往代表你需要转换到下一级更高精度的数值方式了, 例如half可以考虑改用float, float可以考虑改用double
而double可以考虑改用float128(目前N卡并不能直接支持它), 但是可以用整数模拟,Turing的并发INT/FP整数单元, 可以在你同时使用常规FP单元硬件直接计算Float之类的同时,还能上INT单元模拟double和float128计算, 显著提升性能, 并有效保护精度。

关于本段落里面的FADD.F32.FTZ.RN和.RN,实际上是PTX的内容, 有兴趣的用户可以看一下PTX手册(这本是CUDA C编程指南, PTX有非常详细的, 类似本书的另外一本)




回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-10-10 16:29:56 | 显示全部楼层
sisiy 发表于 2018-10-10 16:27
关于第三部分, N卡所遵循的浮点标准(IEEE-754)
这里主要说明了几点:
没有全局可以配置的动态的圆整(取 ...


(1)CPU可选的支持, 但如果你要求了支持(CPU上设定了不将subnormal numbers当成0), 则CPU支持它们, 但同时性能会有1到2个数量级的下降


(2)GPU的A卡中, 并不支持它们, 总是直接当成0处理(损失精度), 但没有性能损失.

(3)N卡没有直接的资料, 但根据各种GTC或者可用公开文档看(我并没有单独测试过它们),


N卡是支持它们, 能够带来精度提升, 同时并没有性能下降.


因此这样说, 需要非到了使用subnormal数不可的地方, 还是得上N卡.


N卡在精度方面, 还是靠得住的.
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

快速回复 返回顶部 返回列表