前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DAY79:阅读 Compute Capabilities

DAY79:阅读 Compute Capabilities

作者头像
GPUS Lady
发布2018-10-23 11:05:22
8640
发布2018-10-23 11:05:22
举报
文章被收录于专栏:GPUS开发者GPUS开发者

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 Specifications

.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.

文备注/经验分享:

本章表格主要说明了各种计算能力了下的卡的"特性"的异同。请注意该表格列出了目前所有支持的计算能力的卡的对比情况.而计算能力也往往是一般用户口中的"代", 某代某代的卡如何如何。 它决定了用户在编写代码的时候, 所能用到的特性; 有些特性是如此重要, 也往往决定了用户购买的选择.例如说, 用户的代码需要动态的细分处理, 需要使用动态并行(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, 从而取得更好的性价比. 这样根据实际项目对计算能力的主要特性的取舍不同, 用户可以作出一定预算下的正确采购要求.

本表格需要特别注意的是两个地方, 一个是半精度的支持, 一个是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所带来的固定额外开销.

关于第三部分, 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有非常详细的, 类似本书的另外一本)

有不明白的地方,请在本文后留言

或者在我们的技术论坛bbs.gpuworld.cn上发帖

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-10-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 GPUS开发者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • H. Compute Capabilities
    • H.1. Features and Technical Specifications
      • .2. Floating-Point Standard
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档