我正在处理在CUDA中准确计算零阶I0的修正贝塞尔函数的问题。
很长一段时间以来,我一直根据论文使用理性的切比雪夫近似
J.M。布莱尔,“修正的贝塞尔函数I_0(x)和I_1(x)的理性切比雪夫近似”,数学。 Comput。,vol。 28,n。 126,pp.581-583,1974年4月。
,与Matlab提供的结果相比,给出了1e-29的平均误差。不幸的是,这个看似很高的精度对于我正在研究的新应用来说已经不够了。
Matlab使用D.E开发的Fortran例程。摩
可从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%
,这使我认为不准确的来源是由于第一步,即修改贝塞尔函数的计算。
对本次讨论的有趣发展
答案 0 :(得分:3)
我想知道这是否可归因于浮点运算之间的精度差异。
有几件事需要检查
圆桌会议
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
答案 1 :(得分:0)
我找到了一个介绍性的技术讲座来回答你的问题。这是PDF的链接。 所以是的,这是可能的,但是我无法通过前面提到的脚本将遗留的fortran代码转换为CUDA C,也许直接联系开发人员。