Cuda 数学与 C++ 数学

Posted

技术标签:

【中文标题】Cuda 数学与 C++ 数学【英文标题】:Cuda math vs C++ math 【发布时间】:2016-12-15 22:29:02 【问题描述】:

我在 CPU 上使用 C++ 和在 GPU 上使用 CUDA 实现了相同的算法。在这个算法中,我必须以数值方式求解一个积分,因为它没有解析答案。我必须积分的函数是一个奇怪的曲线多项式,最后有一个 exp 函数。

在 C++ 中

for(int l = 0; l < 200; l++)

    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step;
    r_int = r_int + step;

在 CUDA 中

for(int l = 0; l < 200; l++)

    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*__expf(-a6*r_int)*step;
    r_int = r_int + step;

    

输出:

CPU:dose_output=0.00165546

GPU:dose_output=0.00142779

我认为 math.h 的 exp 函数和 CUDA 的 __expf 函数计算的不是同一件事。我试图删除 --use_fast_math 编译器标志,认为这是原因,但似乎两种实现都相差 20% 左右。

我正在使用 CUDA 来加速医学物理算法,但这些差异并不是很好,因为我必须证明其中一个输出比另一个输出“更真实”,这显然对患者来说是灾难性的。

差异来自函数本身吗?否则,我认为它可能来自a_i 因素的内存副本或我获取它们的方式。

编辑:“完成”代码

float a0 = 5.9991e-04;
float a1 = -1.4694e-02;
float a2 = 1.1588;
float a3 = 4.5675e-01;
float a4 = -3.8617e-03;
float a5 = 3.2066e-03;
float a6 = 4.7050e-01;

float integral = 0.0;

float r_int = 5.0;
float step = 0.1/200;

for(int l = 0; l < 200; l++)

    integral = integral + (a0*(1/(r_int*r_int)) + a1*(1/r_int) + a2 + a3*r_int + a4*r_int*r_int + a5*r_int*r_int*r_int)*exp(-a6*r_int)*step;
    r_int = r_int + step;


cout << "Integral=" << integral << endl; 

我建议在 gpu 和 cpu 上运行这部分。 来自Carleton's seed database的值

【问题讨论】:

评论不用于扩展讨论;这个对话是moved to chat。 我知道这已经很老了,但是无论多么奇怪,多项式的解析反导数都可以通过 Risch 算法与指数相乘。 【参考方案1】:

您正在使用 CUDA API 中不太准确的 exp() 实现。

基本上你可以在设备上使用三个版本的 exp() :

exp(),更准确的一个 expf(),这是一个单精度的“等价物” __expf(),是前一个的内在版本,准确度较低

您可以在 CUDA 文档的Mathematical Functions Appendix 中阅读有关数学函数的不同实现的更多信息,包括双精度、单精度和内在版本:

D.2。内在函数

本节中的函数只能在设备代码中使用。

在这些函数中,精度较低但速度较快的版本 标准函数的一些函数。它们具有相同的名称 以 __ 为前缀(例如 __sinf(x))。它们映射到的速度更快 更少的本地指令。

在同一页面中,您将看到您删除的编译器选项只是防止每个函数被其内在版本替换。当您明确使用 exp() 的内在版本时,删除此标志对您没有任何改变:

编译器有一个选项(-use_fast_math)强制每个函数 在表 8 中编译成它的内在对应物。

【讨论】:

以上是关于Cuda 数学与 C++ 数学的主要内容,如果未能解决你的问题,请参考以下文章

C++数学与算法系列之排列和组合

C++ 数学与算法系列之认识格雷码

Linux 桌面玩家指南:16. 使用 CUDA 发挥显卡的计算性能

开源 C++ 游戏引擎数学库?

C++ 数学与算法系列之牛顿二分迭代法求解非线性方程

C++ 数学与算法系列之高斯消元法求解线性方程组