矢量化/并行化 GEKKO 方程
Vectorising / Paralellising GEKKO equations
使用 Phython 的 GEKKO 库并按照示例求解波动方程
their original paper,需要创建一大堆方程式。
m.Equations([u[i].dt() == v[i]for i in range(npx)])
m.Equations([v[i].dt() == c**2*(u[mod(i+1,npx)]-2.0*u[mod(i,npx)]+u[mod(i-1,npx)])/dx**2 for i in arange(0,npx,1)])
(我已经通过 mod
将其减少为两行,结合边界条件并让 i 运行 从 0 到 99,但它基本上仍然与示例中的相同。)
它仍在使用 for
循环,即 v[i]for i in range(npx)]
。是否可以避免这种情况,从而使代码更具可读性或通过像使用 numpy 数组一样对其进行并行化/矢量化来使模拟更快?
当然对于这个问题在我的笔记本电脑上计算只需要<18s,但更大的问题可能会很慢。
文档中有一些关于数组的内容,但我不明白,我什至不知道这是否是我正在寻找的内容。
我附加了一个MWE,使用上面的代码here。
如果您想提高速度,请尝试使用 m.options.IMODE=7
的顺序解决方案。对于仿真来说,一般比IMODE=4
快很多(同时求解)。
from gekko import GEKKO
import numpy as np
import time
start = time.time()
pi = np.pi
#Initialise model
m = GEKKO(remote = False)
#Discretisations(time and space)
npt = 200; npx = 100
m.time = np.linspace(0, 1, npt)
xpos = np.linspace(0, 2*pi, npx)
dx = xpos[1]-xpos[0]
#Define Variables
c = m.Const(value = 10)
u = [m.Var(value = np.cos(xpos[i])) for i in range(npx)]
v = [m.Var(value = np.sin(2*xpos[i])) for i in range(npx)]
#Automatic discretisation in time and manual discretisation in space
m.Equations([u[i].dt() == v[i] for i in range(npx)])
m.Equations([v[i].dt() == c**2*(u[np.mod(i+1,npx)]-2.0*u[np.mod(i,npx)]\
+u[np.mod(i-1,npx)])/dx**2 \
for i in np.arange(0,npx,1)])
#Set options
m.options.imode = 7
m.options.solver = 1
m.options.nodes = 3
m.solve(disp = False, GUI = False)
print('Solve Time: ' + str(m.options.SOLVETIME))
print('Total Time: ' + str(time.time()-start))
使用 IMODE=4
设置问题需要更多时间,但解决问题所需时间更少。
Solve Time: 2.7666
Total Time: 25.547
使用 IMODE=7
设置问题所需的时间更少,但解决问题的时间更多。
Solve Time: 8.2271
Total Time: 11.819
当您遇到更大的问题时,IMODE=7
将比 IMODE=4
花费更少的时间进行模拟。
对于并行选项,您可以并行构建模型,但该模型的解决方案除了 IMODE=7
之外没有太多选项可以提供更快的解决方案。您可以通过以下方式创建并行 Gekko 应用程序:
在 IPOPT 中与 ma77、ma97 等一起使用并行线性求解器。从我对大规模问题所做的一些测试来看,这通常只会提高 20-60% 的速度。这些选项在公开发布的 IPOPT 版本中不可用,因为求解器需要许可证。线性求解器 MUMPS 与 Gekko 一起分发,但不包括并行支持(尽管这可能会在稍后提供)。问题是求解器只是解的一部分,即使求解器无限快,自动微分、objective 评估和方程评估仍然需要大约 50% 的 CPU 时间。
运行独立。这通常称为 "massively parallel",因为可以将进程拆分为单独的线程,然后在所有子进程完成时再次组合代码。 instructional material on multi-threading and How to do parallel Python Gekko? 展示了如何并行计算。你的问题不是为多线程设置的,因为方程是一起求解的。
使用 Phython 的 GEKKO 库并按照示例求解波动方程 their original paper,需要创建一大堆方程式。
m.Equations([u[i].dt() == v[i]for i in range(npx)])
m.Equations([v[i].dt() == c**2*(u[mod(i+1,npx)]-2.0*u[mod(i,npx)]+u[mod(i-1,npx)])/dx**2 for i in arange(0,npx,1)])
(我已经通过 mod
将其减少为两行,结合边界条件并让 i 运行 从 0 到 99,但它基本上仍然与示例中的相同。)
它仍在使用 for
循环,即 v[i]for i in range(npx)]
。是否可以避免这种情况,从而使代码更具可读性或通过像使用 numpy 数组一样对其进行并行化/矢量化来使模拟更快?
当然对于这个问题在我的笔记本电脑上计算只需要<18s,但更大的问题可能会很慢。
文档中有一些关于数组的内容,但我不明白,我什至不知道这是否是我正在寻找的内容。
我附加了一个MWE,使用上面的代码here。
如果您想提高速度,请尝试使用 m.options.IMODE=7
的顺序解决方案。对于仿真来说,一般比IMODE=4
快很多(同时求解)。
from gekko import GEKKO
import numpy as np
import time
start = time.time()
pi = np.pi
#Initialise model
m = GEKKO(remote = False)
#Discretisations(time and space)
npt = 200; npx = 100
m.time = np.linspace(0, 1, npt)
xpos = np.linspace(0, 2*pi, npx)
dx = xpos[1]-xpos[0]
#Define Variables
c = m.Const(value = 10)
u = [m.Var(value = np.cos(xpos[i])) for i in range(npx)]
v = [m.Var(value = np.sin(2*xpos[i])) for i in range(npx)]
#Automatic discretisation in time and manual discretisation in space
m.Equations([u[i].dt() == v[i] for i in range(npx)])
m.Equations([v[i].dt() == c**2*(u[np.mod(i+1,npx)]-2.0*u[np.mod(i,npx)]\
+u[np.mod(i-1,npx)])/dx**2 \
for i in np.arange(0,npx,1)])
#Set options
m.options.imode = 7
m.options.solver = 1
m.options.nodes = 3
m.solve(disp = False, GUI = False)
print('Solve Time: ' + str(m.options.SOLVETIME))
print('Total Time: ' + str(time.time()-start))
使用 IMODE=4
设置问题需要更多时间,但解决问题所需时间更少。
Solve Time: 2.7666
Total Time: 25.547
使用 IMODE=7
设置问题所需的时间更少,但解决问题的时间更多。
Solve Time: 8.2271
Total Time: 11.819
当您遇到更大的问题时,IMODE=7
将比 IMODE=4
花费更少的时间进行模拟。
对于并行选项,您可以并行构建模型,但该模型的解决方案除了 IMODE=7
之外没有太多选项可以提供更快的解决方案。您可以通过以下方式创建并行 Gekko 应用程序:
在 IPOPT 中与 ma77、ma97 等一起使用并行线性求解器。从我对大规模问题所做的一些测试来看,这通常只会提高 20-60% 的速度。这些选项在公开发布的 IPOPT 版本中不可用,因为求解器需要许可证。线性求解器 MUMPS 与 Gekko 一起分发,但不包括并行支持(尽管这可能会在稍后提供)。问题是求解器只是解的一部分,即使求解器无限快,自动微分、objective 评估和方程评估仍然需要大约 50% 的 CPU 时间。
运行独立。这通常称为 "massively parallel",因为可以将进程拆分为单独的线程,然后在所有子进程完成时再次组合代码。 instructional material on multi-threading and How to do parallel Python Gekko? 展示了如何并行计算。你的问题不是为多线程设置的,因为方程是一起求解的。