在此 OpenCL 参考表(断开的链接)的第三页上,有两个具有相同参数的内置向量长度函数:length()
和half_length()
.
这些功能有什么区别?我从名字中收集到一个比另一个“更快”但在什么情况下?它是否会为了提高速度而牺牲准确性?如果不是,为什么要使用length()
over fast_length()
?
在此 OpenCL 参考表(断开的链接)的第三页上,有两个具有相同参数的内置向量长度函数:length()
和half_length()
.
这些功能有什么区别?我从名字中收集到一个比另一个“更快”但在什么情况下?它是否会为了提高速度而牺牲准确性?如果不是,为什么要使用length()
over fast_length()
?
根据 OpenCL 规范(1.1 版,第 215 页):
float length(floatn p)
: 返回向量的长度p
,即sqrt(p.x²+p.y²+...)
float fast_length(floatn p)
:返回向量的长度p
计算为half_sqrt(p.x²+p.y²+...)
所以fast_length
用half_sqrt
,而length
用sqrt
。正如您所猜测的那样sqrt
,对准确性有更好的保证,但可能会更慢。更重要的是:
最小精度sqrt
:3ulp(最小精度单位)
最小精度half_sqrt
:8192ulp
所以half_sqrt
可以降低大约 11 位的准确度sqrt
(实际上它可以降低 13 位的准确度,因为没有要求不比sqrt
严格必要的更好)。由于float
尾数为23bit
(加上一个隐式位)half_sqrt
,因此只能保证大约 10 位的精度(11 位包括隐式 1)。但是,如果硬件具有这样的功能,它可能会更快。在硬件中,指令仅提供少量位(如 10-14)并在指令后使用 Newton-Raphson 迭代以获得必要的精度并不sqrt
罕见rsqrt
。在这种情况下,使用half_sqrt
显然更快。