找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 63|回复: 3

DAY80:阅读Intrinsic Functions

[复制链接]
发表于 2018-8-28 15:45:01 | 显示全部楼层 |阅读模式
E.2. Intrinsic Functions
The functions from this section can only be used in device code.
Among these functions are the less accurate, but faster versions of some of the functions of Standard Functions .They have the same name prefixed with __ (such as __sinf(x)). They are faster as they map to fewer native instructions. The compiler has an option (-use_fast_math) that forces each function in Table 8 to compile to its intrinsic counterpart. In addition to reducing the accuracy of the affected functions, it may also cause some differences in special case handling. A more robust approach is to selectively replace mathematical function calls by calls to intrinsic functions only where it is merited by the performance gains and where changed properties such as reduced accuracy and different special case handling can be tolerated.
Table 8. Functions Affected by -use_fast_math


Operator/FunctionDevice Function
x/y
__fdividef(x,y)
sinf(x)
__sinf(x)
cosf(x)
__cosf(x)
tanf(x)__tanf(x)
sincosf(x,sptr,cptr)__sincosf(x,sptr,cptr)
logf(x)
__logf(x)
log2f(x)__log2f(x)
log10f(x)__log10f(x)
expf(x)__expf(x)
exp10f(x)__exp10f(x)
powf(x,y)__powf(x,y)

Functions suffixed with _rn operate using the round to nearest even rounding mode.
Functions suffixed with _rz operate using the round towards zero rounding mode.
Functions suffixed with _ru operate using the round up (to positive infinity) rounding mode.
Functions suffixed with _rd operate using the round down (to negative infinity) rounding mode.
Single-Precision Floating-Point Functions
__fadd_[rn,rz,ru,rd]() and __fmul_[rn,rz,ru,rd]() map to addition and multiplication operations that the compiler never merges into FMADs. By contrast, additions and multiplications generated from the '*' and '+' operators will frequently be combined into FMADs.
The accuracy of floating-point division varies depending on whether the code is compiled with -prec-div=false or -prec-div=true. When the code is compiled with -prec-div=false, both the regular division / operator and __fdividef(x,y) have the same accuracy, but for 2126 < y < 2128, __fdividef(x,y) delivers a result of zero, whereas the / operator delivers the correct result to within the accuracy stated in Table 9. Also, for 2126 < y < 2128, if x is infinity, __fdividef(x,y) delivers a NaN (as a result of multiplying infinity by zero), while the / operator returns infinity. On the other hand, the / operator is IEEE-compliant when the code is compiled with -prec-div=true or without any -prec-div option at all since its default value is true.
Table 9. Single-Precision Floating-Point Intrinsic Functions. (Supported by the CUDA Runtime Library with Respective Error Bounds

Double-Precision Floating-Point Functions
__dadd_rn() and __dmul_rn() map to addition and multiplication operations that the compiler never merges into FMADs. By contrast, additions and multiplications generated from the '*' and '+' operators will frequently be combined into FMADs.
Table 10. Double-Precision Floating-Point Intrinsic Functions. (Supported by the CUDA Runtime Library with Respective Error Bounds





回复

使用道具 举报

 楼主| 发表于 2018-8-28 16:47:40 | 显示全部楼层
今天的主要内容是这些instrinsic functions. 用过CPU的人都知道, instrinsic函数往往是能直接映射到一条或者多条硬件指令的,也叫本征函数。
通过直接使用他们这些instrinsic函数的名字, 编译就地生成对应的硬件指令.例如CPU上的很多__mm开头的函数(直接编译成对应的SIMD指令)就是这种.而回到CUDA上, 情况稍微有些不同.不同于CPU的必须使用这些内置名字, 编译器才能产生对应的指令(注意, Intel的编译器除外, 它非常智能), CUDA的这些函数, 只是对应的上一章节的标准数学函数的快速版本而已.我们都知道, SM里含有SP和SFU, 其中的SP能进行通用计算,而SFU则功能稍微固定(你可以将它看成是一些数据函数的专用功能, 类似tensorcore, 只是用途不同)
通过使用本章节的这些内置函数, 你可以尽量要求一些计算通过内置的专用SFU功能部分来计算完成,而不是使用宝贵的SP.这样, 这些内置函数往往会比标准版本快速很多.但代价则是, 会损失一定的精度.很多时候用户需要权衡, 是否使用这些SFU计算出来的快速版本, 还是选择通用的SP计算出来的版本.这些快速版本在应用场合的误差要求满足的情况下, 还是能提速不少的.
那么如何使用他们, 本章节提供了两种方案:
一种是使用编译参数控制(例如-use_fast_math这些), 这样会将所有能替换成内置高速低精度版本的全自动替换掉.
另外一种则是用户手工使用这些带有2个下划线__开头的版本.
这两种各有利弊.
第一种只需要简单的右键点击一下VS里面的项目属性, 改称使用快速数学, 即可享受提速. 但坏处是所有的能改的函数都被改了. 很多时候精度可能无法满足要求.
另外一种则是用户不使用编译参数控制. 二是手工的自己的代码里的, 部分允许使用高速低精度的地方, 改称两个下划线开头的版本.
这种可以同时享受精度和速度, 但坏处是需要用户有可能较多的代价改动量.
用户可以自行决定是否需要更改.
(有人问深度学习用户不是对精度没啥要求么?深度学习用不了的, 深度学习用户需要tensor core加速. SFU能加速的这些内置函数是给数值计算的用户提供的,也就是CUDA最初流行时候的主力用途)
请用户注意的是, SFU能运算的内置版本的功能有限,主要是在于:

回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-28 17:01:30 | 显示全部楼层
sin, cos, ex2, lg2, 1/x, 1/x^0.5类似这些的.SFU在加速这些运算的时候, 能和SP同时计算(计算能力2.1到计算能力6.1,但是7.0什么情况我还不知道)
也就是说, SP可以继续干它的事情.在除了Turing和7.0的Volta(这卡我没用过)之外,能和SP同时利用的, 基本上只有SFU和LSU/Shared memory了.想在5.X和6.1的卡上, 达到峰值IPC(大约在6, 一般5.X就认为峰值了. 只用满SP是4. 卡在不能掩盖的各种延迟或者低速指令用的太多可能只有1-2)的唯一办法就是, 同时尽量利用这些单元.所以不仅仅是本章节一些数学计算可以用这些快速的内置版本, 想成功发挥SM的整体性能, 有的时候也需要考虑他们.
需要补充说明的是:
(1)这些快速内置版本的数学计算函数, 只适合单精度. 双精度不影响的.这是因为SFU只能运算这些特定的单精度函数版本(*这个说法不精确, 但是目前可以这样看. 否则本章节就说的太复杂了)
(2)标准函数往往有两种实现方式: 一种是纯SP. 一是SFU+SP混合, 即SFU先出来一个大致结果, 然后SP进行进一步的精度修正.
这两种标准函数(忘记标准的数学函数了? 看上一章节), 当被改写成快速的内置版本后,前者会变成从纯SP计算变成SFU计算.而后者则会从SFU+SP混合计算去掉后续的一步或者多步SP修正步骤.但无论那种, 往往都会有不少的提速.例如sincosf()可以从纯SP计算(一大堆的浮点和整数指令序列)变成4条SFU指令(MUFU.RRO/SIN/COS), 提速明显.例如sqrtf()会从SFU计算+SP后续的牛顿法插值, 变成只有SFU计算部分.
(3)第三点则是说, half(半精度, FP16), 和double一样, 也没有这些快速的内置版本数学函数.目前的编译器, 例如在6.0上(P100, 200%的FP16的卡), 会生成一系列的SP的指令序列的.同样不能享受到这个.但好在用FP16的人往往不在乎精度, 所以无所谓.而用FP64(double)的人往往非常在乎精度, 所以也无所谓.这样这些高速的低精度版本的内置函数只能对float生效.
需要说明的是, 刚才有2个表格用户需要看一下,这个表格是对比了一些标准数学函数的精度信息.同样的一些操作, 往往double版本的结果要比float版本的更加精确,这种更加精确不仅仅是说, double的有效数字更多, float的有效数字少导致的,而是说, 在他们各自的表达范围能,
(有人问:这个得用支持双精度的卡吧?都可以用. 只是普通卡用起来性能悲剧而已. 但是性能不等于精度. 精度还是和高端卡一样的)
double具有更低的ULP误差(一种有最低有效位表示的误差, 在常规数据(不是denormal/subnormal数值的时候), 可以一定程度的理解成特定的相对误差),所以很多时候还是需要上double的.毕竟单精度只有24-bit有效数字(*精确的说23-bit), 双精度的却有53-bit, 翻倍了还多.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-8-28 17:07:13 | 显示全部楼层
sisiy 发表于 2018-8-28 17:01
sin, cos, ex2, lg2, 1/x, 1/x^0.5类似这些的.SFU在加速这些运算的时候, 能和SP同时计算(计算能力2.1到计算 ...

这样实际上哪怕所有的float运算都是0误差的, 也实际结果比不上哪怕有20个ULP误差的double的.因为常规说的32-bit和64-bit的说法不对, 里面表示有效数字的只有24(23)和53(52)-bit.其他的bit干别的去了. 所以有需要高度精度要求的用户需要注意了,一定要上double的卡.双精度的提升不是一点半点的.
需要补充的是, SFU不仅仅能处理这些内置的高速低精度的一些数学函数.另外的一个主要用途还在于数值类型转换(例如从float到int, 从int8_t到int32_t)等等.这个时候这种转换是和SP并行的.代码写的好(例如这种转换别太多)而且编译器生成的较好.则这些数值转换操作同样可以被SFU免费加速, 掩盖在SP计算中. 等于0代价.所以用户看到手册之前有表格写到, 类型转换运算很多只有25%的速率,其实不用担心.因为到6.1为止的卡, SFU的这种类型转换计算, 和普通计算(浮点, 整数, 逻辑)同时进行, 无成本的.当然, 到了Turing开始, 现在谣传SP里面的整数和浮点运算也可以同时进行了,就想以前的SP+SFU一样.如果是这样的话, 下一代的N卡将会更加的无比强大(不过Turing还没出来实物).
回复 支持 反对

使用道具 举报

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

本版积分规则

关闭

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

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