虽然前面的答案在一般意义上是正确的,但在 ODE 的上下文中向量化意味着更具体的东西。简而言之,一个函数f(t,y)
是向量化的,当且仅当f(t,[y1 y2 ...])
返回[f(t,y1) f(t,y2) ...]
, 对于y1,y2
列向量。根据文档 [1],“这允许求解器减少计算雅可比矩阵的所有列所需的函数评估次数。”
在 ODE 意义上,函数fun3
及fun4
以下函数已正确矢量化:
function re=rabdab()
x=linspace(0,20000,20000)';
opts=odeset('Vectorized','on');
tic;
[T,Y] = ode45(@fun,[x],[0 1 1]);
[T,Y] = ode45(@fun,[x],[0 1 1]);
[T,Y] = ode45(@fun,[x],[0 1 1]);
toc;
tic;
[A,B] = ode45(@fun2,[x],[0 1 1]);
[A,B] = ode45(@fun2,[x],[0 1 1]);
[A,B] = ode45(@fun2,[x],[0 1 1]);
toc;
tic;
[A,B] = ode45(@fun3,[x],[0 1 1],opts);
[A,B] = ode45(@fun3,[x],[0 1 1],opts);
[A,B] = ode45(@fun3,[x],[0 1 1],opts);
toc;
tic;
[A,B] = ode45(@fun4,[x],[0 1 1],opts);
[A,B] = ode45(@fun4,[x],[0 1 1],opts);
[A,B] = ode45(@fun4,[x],[0 1 1],opts);
toc;
function dy = fun(t,y)
dy = zeros(3,1); % a column vector
dy = [y(2) * y(3);...
-y(1) * y(3);...
-0.51 * y(1) * y(2);];
function dy = fun2(t,y)
dy = zeros(3,1); % a column vector
dy(1) = y(2) * y(3);
dy(2) = -y(1) * y(3);
dy(3) = -0.51 * y(1) * y(2);
function dy = fun3(t,y)
dy = zeros(size(y)); % a matrix with arbitrarily many columns, rather than a column vector
dy = [y(2,:) .* y(3,:);...
-y(1,:) .* y(3,:);...
-0.51 .* y(1,:) .* y(2,:);];
function dy = fun4(t,y)
dy = [y(2,:) .* y(3,:);... % same as fun3()
-y(1,:) .* y(3,:);...
-0.51 .* y(1,:) .* y(2,:);];
(作为旁注:省略不必要的内存分配,zeros
让fun4
运行速度略快于fun3
.)
- 问:关于第一个参数的向量化怎么样?
- 答:对于 ODE 求解器,ODE 函数仅针对第二个参数进行矢量化。然而,边值问题求解器
bvp4c
确实需要对第一个和第二个参数进行矢量化。[1]
官方文档 [1] 提供了有关 ODE 特定矢量化的更多详细信息(请参阅“雅可比属性描述”部分)。
[1] https://www.mathworks.com/help/releases/R2015b/matlab/ref/odeset.html