c++ - cuda 数学函数 norm3df 是否溢出?

标签 c++ cuda floating-point

我正在用 cuda 开发 nbody 模拟器。我想使用 float 类型来提高速度,但这让我的任务变得困难。我担心的是说我有一个 vector <10^20, 10^20, 10^20> 并且我想使用勾股定理计算它的大小。我必须对每个 10^40 的分量进行平方,而在 32 位中,这将是无穷大。因此,即使我对总和求平方根时的最终结果在范围内,中间步骤也会溢出。我在 cuda 数学 API 中遇到了以下函数。 norm3df(x, y, z)。这会阻止我正在谈论的中间步骤溢出吗?此外,我可能需要在主机和设备上使用此功能。行为是否相同?

最佳答案

标准 C++ 数学库包含一个函数 hypot() 用于计算二维范数同时避免中间计算中的过早下溢和上溢。由于 3D 范数也很常见,因此 CUDA 数学库还提供了一个类似的函数 norm3d()。 CUDA中的描述math API documentation阅读:

Calculate the length of three dimensional vector p in euclidean space without undue overflow or underflow

此外,CUDA 数学库提供倒数范数函数 rhypot()rnorm3d(),它们在规范化 2D 和 3D vector 时很有用,因为它们允许替换昂贵的用更便宜的乘法除法。

由于 norm3d()rhypot()rnorm3d() 不是标准的 C++ 数学库函数,因此它们不能用于CUDA 程序的主机部分,因为主机代码由主机工具链处理。 NVIDIA 为设备提供数学库支持。您可能希望向主机工具链供应商提交增强请求,以将这些有用的功能添加为专有扩展,和/或游说 ISO C/C++ 委员会将它们添加到标准的 future 版本中。

我之前注意到,目前发布的 CUDA 头文件似乎错误地将 normd3d() 和其他一些 CUDA 特定函数标记为 __host__ __device__,尽管实际上没有主机实现。这似乎是一个错误,可能是由于这些属性在原型(prototype)中的剪切和过去应用造成的。

范数和倒数范数函数在其内部计算中不需要更高的中间精度,这意味着对具有低吞吐量 double 的 GPU 没有负面性能影响。相反,他们使用巧妙的数学重新排列、操作数的重新缩放以及使用 FMA 来实现他们的目标。它们不仅可以防止不当的上溢和下溢,它们还应该比等效的朴素计算更准确。

直到并包括 CUDA 6.5 版,CUDA 数学库的实现细节在 CUDA 头文件 math_functions.hmath_functions_dbl_ptx3.h 中可见,所以任何人想要更好地了解规范函数的内部细节可能需要查看那里。

关于c++ - cuda 数学函数 norm3df 是否溢出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35457690/

相关文章:

c++ - cudaDeviceSynchronize() 错误代码 77 : cudaErrorIllegalAddress

c++ - cuda 中是否有模板化的数学函数?

c - 有没有办法用 i387 fsqrt 指令获得正确的舍入?

c# - Base 52 到 decimal 反之亦然转换

c++ - SndVol 如何改变给定 Audio Session 的音量级别?

c++ - 模板化单例类 - 如何处理私有(private)构造函数

c++ - Launch Bounds 没有发挥作用?

c++ - 大 float 的C++库

go - 为什么 Go 中的浮点乘法与文字和变量之间存在差异?

c++ - 如何正确删除ncurses中的菜单?