梯度 Computation/Assembly 非常慢

Gradient Computation/Assembly Very Slow

我正在使用 OpenMDAO 在 Python 中实现现有的 MATLAB 优化代码。

openmdao summary 的基本问题结构是:

============== Problem Summary ============
Groups:              14
Components:          70
Max tree depth:       5

Design variables:            7   Total size:      121

Nonlinear Constraints:      12   Total size:      936
    equality:                0                      0
    inequality:             12                    936

Linear Constraints:          0   Total size:        0
    equality:                0                      0
    inequality:              0                      0

Objectives:                  1   Total size:        1

Input variables:           357   Total size:    41451
Output variables:          271   Total size:    31855

Total connections: 357   Total transfer data size: 41451

在顶层,有 5-10 个用于评估约束和目标的组件,其中一组是自由度变量 defined/parsed(SplineComp),还有一大组是正在完成大部分计算(包含一组有两个级别,一组有一个级别,以及一堆组件)。这与 MATLAB 代码的结构基本相同。在 MATLAB 方面,我正在计算问题级别的分析梯度,但为该部分的有限差分梯度调用大组 14 次。在 Python 中,我混合使用了手动计算的梯度和该大组及其子组中组件的自动微分工具。

我已经验证了 Python 和 MATLAB 对于规定的输入集的结果匹配,并且 check_partials/check_totals 在 Python 中给出了令人满意的结果,我我现在对基准测试中的速度比较感到困惑。

在 MATLAB 中,梯度计算比 objective/constraint 的独立评估花费 ~14x 长,这与所使用的有限差分方法的预期一致。

在 Python 中,compute_totals 比 run_model 花费 ~25-50x 的时间。这让我感到困惑,因为我期望更好的性能,因为这里涉及零有限差分。我并不期望 compute_totals 与 run_model 的速度相同,但它比我预期的慢了一个数量级以上。

我 运行 命令行分析 (iprof) 毫不奇怪,大部分时间花在 solve_linear 上,但在使用 python 分析工具后,它显示了将近一半时间花在 dictionary_jacobian.

我尝试研究使用着色功能来缩短计算时间,但它似乎并没有找到雅可比矩阵的实际稀疏性(报告为 ~64% 非零,而实际为 ~6%):

我已经通过 declare_partials 的 rows/cols 选项验证了我所有的自定义组件都在使用稀疏部分定义(某些内置组件是否不使用会导致这种情况的稀疏定义?我'我为了方便而在大组中使用了一些)我知道黑客马拉松的发现(https://github.com/OpenMDAO/RevHack2020/blob/master/solution_approaches/how_big.md)建议我应该有一个大组件而不是多个小组件,但这很难在这里实现而不失去一个好的我需要大量的灵活性来激活该组内的不同功能。

如果您需要灵活性,请保持组件的大小。

Dictionary Jacobian 意味着您没有利用 DirectSolver 的优势,而这是为您的尺寸模型获得真正良好性能所必需的。这包括使用组装的雅可比矩阵,这也是真正快速的导数所需要的。

尝试将 DirectSolver 设置为模型顶部的线性求解器,如下所示:

prob.model.linear_solver = om.DirectSolver()

为了一般性,我不应该做以下事情:

  • 您只能在串行组上使用 DirectSolver(但该串行组可以是更大的分布式模型的一部分)。
  • 您可以在模型的 sub-group 上使用 DirectSolver。根据模型结构,这可能会更快 (See section 5.3 of this paper)
  • DirectSolver 使用组装的 jacobian(与有问题的 DictionaryJacobian 相对)。这是杂草丛生,但在绝大多数情况下,您需要一个稀疏组装的雅可比矩阵作为直接求解器。偶尔密集的组装会更好。这是通过 system option assembled_jac_type 控制的,默认为 csc (稀疏格式)。您可以尝试使用 dense 作为测试——但同样,csc 很可能是最快的。