处理OpenCL粒子系统中缺乏浮点精度

时间:2012-01-24 22:12:38

标签: floating-point opencl precision

我正在编写一个基于OpenCL的粒子系统来加速大规模网络的可视化。本质上,这是一个两阶段问题,其中第一阶段对每个粒子施加负重力(典型的n体问题),因此它们都排斥并且第二阶段然后基于粒子之间的边缘(或弹簧)吸引粒子。

在重力算法的每次迭代过程中,每个粒子的位置(表示为一对浮点数)受到彼此距离的影响(经典物理模型,没有阻力,保持简单)。

在一个具有完美间隔的方形阵列粒子的情况下,重力的应用应该导致X轴和Y轴的对称性。在重力应用开始时就是如此,但随着时间的推移,将大量浮点数加在一起所固有的精度不足会导致小的不均匀偏差。这反过来又传播通过整个n体系统,并且发生对称性的损失。

避免这种情况的一种简单方法是使用双精度数字,但MacBook Pro上的GeForce 9600M GT不支持双精度数字。那么,在OpenCL中处理这些问题的好方法是什么?我已经考虑过截断我添加到几个小数的浮点数来避免这个问题,但这看起来有点笨拙。

2 个答案:

答案 0 :(得分:14)

你已经遇到了大多数对数值分析领域至关重要的问题;你应该准备好解读一下这些问题通常是如何处理的。

首先,如果您的问题具有对称性,您可以利用它来减少所需的计算量,并且还可以消除由于数值错误导致的任何自发对称性破坏。

其次,要意识到即使在处理相同的有限精度时,并非所有算法都相同:某些算法比其他算法更numerically stable。使用更高精度的算法并不能消除数值不稳定性,只需要花费更长的时间才能显现出来。您的重力模拟当前可能实现的等效于Euler's Method。如果不切换到双精度,您可以使用更高阶的方法(例如Runge-Kutta)使模拟更加稳定/准确。

最后,听起来你正在做force-directed graph layout。简单地向前运行物理模拟很容易找到局部最优,高度依赖于起始位置,并且(正如您所发现的)通常非常不稳定。链接的维基页面提到了其他几种可以更好地解决问题的方法。

答案 1 :(得分:7)

这是一个非常常见的问题;即使在CPU上,有时您也希望避免使用双精度来避免内存开销/带宽因素为2。

为GPU编写的许多分子动力学和n体代码使用"混合精度"算术;它们将粒子位置和速度存储为单个精度,但是它们使用双精度进行一些关键操作 - 通常用于存储位置差异,并累积加速度。 (谷歌搜索"mixed precision" "molecular dynamics""n-body"会产生大量的结果。

这样可以减少双精度计算的次数,但不会减少到零。要实现比硬件原生支持的更高精度算术,您可以进行软件仿真,使用两个浮点模拟双精度。有一个古老的fortran库dsfun90实现了这个,this NVidia forum中有人在CUDA中实现了类似的东西(基于NVIDIA的Mandelbrot示例中的操作)。我不知道OpenCL实现,但是从CUDA复制它应该非常简单。显然它没有本机双打那么快,但如果只是为了几个关键操作,它就不那么糟糕。