编译速度过慢
若 set_*
函数运行时间很长,则遇到了编译速度过慢的问题(是的,确实很慢)。这是因为 set_*
会调用 Numba 编译所需函数,以加速后续问题的求解。Pockit 已经尽可能地优化了整个过程,但对于复杂的问题,编译时间仍然会很长(可能需要几分钟)。
若编译时间过长,可以尝试以下方法:
检查问题设定
- 不要设置
simplify=True
或parallel=True
,因为这会使编译时间更长。(默认值为False
,因此若未手动设置,则可忽略此项。) - 输入的表达式应尽量适宜整个编译过程。例如 \(x^2\) 应输入为
x * x
或x ** 2
,而不是pow(x, 2.0)
,从而使得符号微分过程能更好地处理这一表达式。
优化求解过程
为了避免重复编译,pockit 中 set_*
函数被设计为解耦的。即设定新的动力学方程、约束方程、目标函数、边界条件、离散化参数等时,不需要重新编译其它函数。例如,若需要对相同系统、不同边界条件进行求解,则更改边界条件时只需要调用 set_boundary_condition
函数,而不需要重新调用 set_dynamics
函数,从而避免重复编译。
注意:若在 System.set_phase
之后又调用了 Phase 的 set_*
函数,则在完成后需要调用一次 System.update
函数,以更新问题信息。(System.update
函数不需要编译任何函数,速度很快。)
缓存编译结果
对于反复研究同一问题的用户,可以将编译结果缓存到本地,以避免重复编译。这样可以显著减少编译时间。方法为
- 创建一个缓存文件夹,用于存放编译结果。
- 在
set_*
函数中设置cache
参数为缓存目录的路径。以set_dynamics
为例:
支持的函数有P.set_dynamics(..., cache='./path/to/cache')
Phase.set_dynamics
、Phase.set_integral
、Phase.set_phase_constraint
、Phase.set_boundary_condition
、System.set_objective
、System.set_system_constraint
这样,编译结果会被保存到缓存文件夹中,下次运行时会直接加载编译结果。
使用预先手动编译的函数
若以上方法仍无法满足需求,可以完全放弃 Pockit 的符号微分、编译功能,而直接使用预先编译的函数。参见略过符号微分。