繁体   English   中英

准确计算修改后的贝塞尔函数 - 在CUDA中使用netlib Fortran例程?

[英]Accurate computation of modified Bessel functions - Using netlib Fortran routines in CUDA?

我正在处理在CUDA中精确计算零阶I0的修正贝塞尔函数的问题。

很长一段时间,根据论文,我一直在使用理性的切比雪夫近似

JM Blair,“修正贝塞尔函数I_0(x)和I_1(x)的理性切比雪夫近似”,数学。 Comput。,vol。 28,n。 126,pp.581-583,1974年4月。

与Matlab提供的结果相比,它给出了1e-29的平均误差。 不幸的是,这个看似很高的精度对于我正在研究的新应用来说已经不够了。

Matlab使用DE Amos开发的Fortran例程

Amos,DE,“用于复杂论证和非负序的贝塞尔函数的子程序包”,桑迪亚国家实验室报告,SAND85-1018,1985年5月。

Amos,DE,“用于复杂论证和非负序的贝塞尔函数的便携式包”,Trans。 数学。 软件,1986年。

可以从netlib / amos网站下载。

有一些方法可以在C / C ++代码中使用这些Fortran例程,方法是在库文件中编译它们,然后使用C / C ++包装器(参见netlib_wrapping )。 我想知道是否有任何方法可以使那些Fortran例程中的设备功能被CUDA内核调用。

关于问题的更多细节

我有两个代码,一个用Matlab编写,另一个用CUDA编写。 两者都按三个步骤操作:

1) 通过修改的贝塞尔函数I0进行缩放和数据的零填充 ;

2) FFT ;

3) 插值

我将两者都与“精确”结果进行比较:作为步骤3)的输出,Matlab给出的相对均方根误差为1e-10%,而CUDA为1e-2%,因此我开始研究原因。

两个代码的第一步之间的均方差,即100*sqrt(sum(abs(U_Matlab_step_1-U_CUDA_step_1).^2))/sqrt(sum(abs(U_Matlab_step_1).^2)) ,为0%mean(mean(abs(U_Matlab-U_CUDA)))=6e-29代替)所以我会说它很好。 不幸的是,当我转到第2步时,错误会增加到2e-4% 最后,如果我用Matlab的步骤1)的输出提供CUDA的步骤2),那么步骤2)的rms误差变为1e-14% ,这使我认为不准确的来源是由于第一步,即,修改贝塞尔函数的计算。

有兴趣发展本次讨论

看看NVIDIA开发者专区论坛

我想知道这是否可归因于浮点运算之间的精度差异。

有几件事要检查

  1. Cuda 5添加了一些新的trig函数,可以更好地匹配您的计算格式。 此外,我认为自版本4以来的CUDA数学库有一些bessel函数,虽然我不确定这是真的还是它们对你的问题有多么相关。
  2. 你能写一个串行CPU版本进行测试吗? 这将告诉您精度问题是否归因于优化,例如使用64位与80位表示的数字。 关闭优化后,您的计算机将主要处理80位表示(也许matlab会这样做),而启用数学优化后,您的编译器可能会处理不太准确的64位表示。 这相当于x87和SSE之间的差异。
  3. 不同的计算能力硬件的精度略有不同。 例如,compute 2.0的FMA更准确,更接近于优化的x86。
  4. 是否有物理上的理由认为Matlab是正确的? 当Matlab超调时,你的算法可能会低于结果。 如果CUDA在Matlab没有进行操作时会发生这种情况。
  5. 如果必须,必须重新创建Matlab结果,您可以尝试通过将输出与不同的舍入技巧相匹配来调整代码的每个步骤。 见表。

圆桌会议

addition       | x + y        | __dadd_[rn|rz|ru|rd](x, y)
multiplication | x * y        | __dmul_[rn|rz|ru|rd](x, y)
Fused-Mult-Add | fma(x, y, z) | __fma_[rn|rz|ru|rd](x, y, z)
reciprocal     | 1.0 / x      | __drcp_[rn|rz|ru|rd](x)
division       | x / y        | __ddiv_[rn|rz|ru|rd](x, y)
square root    | sqrt(x)      | __dsqrt_[rn|rz|ru|rd](x)

mode | interpretation
rn   | round to nearest, ties to even
rz   | round towards zero
ru   | round towards +∞
rd   | round towards -∞

来自http://developer.download.nvidia.com/assets/cuda/files/NVIDIA-CUDA-Floating-Point.pdf

我找到了一个介绍性的技术讲座来回答你的问题。 这是PDF的链接。 所以是的,这是可能的,但是我无法通过前面提到的脚本将遗留的fortran代码转换为CUDA C,也许直接联系开发人员。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM