我正在尝试解决GPU(CUDA)上的一些不受约束的非线性优化问题。
目标函数是一个平滑的非线性函数,其梯度在分析上相对便宜,因此我无需理会数值逼近。
我想通过大多数fp32数学运算来解决此问题(由于各种原因),那么哪种非线性优化方法对舍入误差更鲁棒,同时又具有良好的性能?(例如共轭梯度/准牛顿/信任区域),有人在GPU上尝试过BFGS并获得良好结果吗?
顺便说一句,如果需要的话,Hessian相对较小(通常小于64x64),但是我需要同时解决数千个此类小规模优化问题。
我正在尝试解决GPU(CUDA)上的一些不受约束的非线性优化问题。
目标函数是一个平滑的非线性函数,其梯度在分析上相对便宜,因此我无需理会数值逼近。
我想通过大多数fp32数学运算来解决此问题(由于各种原因),那么哪种非线性优化方法对舍入误差更鲁棒,同时又具有良好的性能?(例如共轭梯度/准牛顿/信任区域),有人在GPU上尝试过BFGS并获得良好结果吗?
顺便说一句,如果需要的话,Hessian相对较小(通常小于64x64),但是我需要同时解决数千个此类小规模优化问题。
Answers:
我已经在GPU上实现了多种非线性求解器,包括LBFGS,Barzilai Borwein梯度下降和非线性共轭梯度。
为此,Dai&Yuan的非线性共轭梯度是最有效的。通常,非线性共轭梯度的其他版本可能更有效(例如CG-DESCENT),但实现起来也比较棘手。
通常,LBBFG是一个非常可靠的选择,除非您真的有足够的存储空间,否则它可能是最好的起点。
共轭梯度和BFGS都需要线搜索,这是fp32成为问题的地方。我建议不要使用标准的Wolfe条件进行行搜索,而建议使用此处建议的近似Wolfe条件。本文涉及的内容很少,但重要的是公式4.1。从本质上讲,它们明确介绍了可以用来计算函数的精度。
GPU注意事项:
您有很多小问题,与我的一个大问题的用例略有不同。如果您可以并行化函数和梯度求值以使用一个块中的所有线程,请考虑在每个GPU块(或者说是扭曲)上运行1个问题。这样,如果不同的问题需要不同数量的迭代,这不是问题。
如果这不是一个选择,我将使用LBFGS求解器。如果您的函数运行良好,则可以简单地使用步长为1(避免行搜索),并以固定的迭代次数运行所有问题。
我建议您使用Levenberg Marquardt(信任区域变体),因为它已在许多实际应用中使用,并表现出非常好的速度与精度性能。此外,对于GPU,有一些库(例如cuLM https://github.com/zitmen/cuLM),您可以尝试一下。如果他们做不到这一点,则有大量资源可供您实施。实施LM一点也不难。您只应注意尽量减少GPU通信。简要说明一下: