简体   繁体   English

在 Octave / Matlab 中矢量化 ODE

[英]Vectorizing ODE in Octave / Matlab

If I have an ode and wrote it in two ways, like here:如果我有一首颂歌并以两种方式写它,比如这里:

function re=rabdab()
x=linspace(0,2000,2000)';
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;



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);

There is almost no difference in time.时间上几乎没有区别。 One takes just as long as the other.一个和另一个一样长。 But I thought that fun is the vectorized version of fun2 .但我认为funfun2的矢量化版本。 Or am I mistaken here?还是我在这里弄错了? The purpose is to speed up my code a little.目的是稍微加快我的代码速度。 The example is taken from the matlab webpage.该示例取自 matlab 网页。 I think I haven't really understood what "vectorized" means.我想我还没有真正理解“矢量化”是什么意思。 If this is already vectorized, what would a non-vectorized code look like?如果这已经是矢量化的,那么非矢量化的代码会是什么样子?

Vectorization is a concept which is closely related to functional programming . 向量化是一个与函数式编程密切相关的概念。 In MATLAB it means performing operations on arrays (vectors or matrices) without implicitly writing a loop.在 MATLAB 中,它意味着在不隐式编写循环的情况下对数组(向量或矩阵)执行操作。

For example, if you were to compute the function f(x) = 2x for every integer x between 1 and 100, you could write:例如,如果您要为 1 到 100 之间的每个整数x计算函数f(x) = 2x ,您可以编写:

for x = 1:100
    f(x) = 2 * x;
end

which is not vectorized code.这不是矢量化代码。 The vectorized version is:矢量化版本是:

x = 1:100; %// Declare a vector of integer values from 1 to 100
f = 2 * x; %// Vectorized operation "*"

or even shorter:甚至更短:

f = 2 * (1:100);

MATLAB is an interpreted language, so obviously the interpreter translates this into some kind of loop "under the hood", but it's optimized and is usually much faster than actually interpreting a loop (read this question for reference). MATLAB 是一种解释型语言,因此显然解释器将其翻译为某种“幕后”循环,但它经过优化,通常比实际解释循环快得多(阅读此问题以供参考)。 Well, sort of -- it's been like that until the recent releases of MATLAB, where JIT acceleration has been integrated (read here ).嗯,有点 - 在最近的 MATLAB 版本之前一直是这样,其中集成了JIT 加速(阅读此处)。

Now getting back to your code: what you have here is two vectorized versions of your code: one that concatenates vertically three values and one that directly assigns these values into a column vector.现在回到您的代码:这里有两个向量化版本的代码:一个垂直连接三个值,一个直接将这些值分配到列向量中。 That's basically the same thing.这基本上是一样的。 Should you have done it with an explicit for loop, this would not have been "vectorized".如果您使用显式 for 循环完成它,则不会“矢量化”。 Regarding the actual performance gain from "vectorizing" a loop (that is, converting a for loop into a vectorized operation), this depends on the how fast the for loop actually was due to JIT acceleration in the first place.关于“向量化”循环(即将 for 循环转换为向量化操作)的实际性能增益,这首先取决于由于 JIT 加速而导致的 for 循环实际上有多快。

It doesn't seem that there's much to be done to speed up your code.似乎没有多少工作要做来加速您的代码。 Your functions are pretty basic, so it boils down to the internal implementation of ode45 , which you cannot modify.您的函数非常基础,因此归结为ode45的内部实现,您无法修改。

If you're interested in further reading about vectorization and writing faster MATLAB code in general, here's an interesting article: Loren on the Art of MATLAB: " Speeding Up MATLAB Applications " .如果您有兴趣进一步阅读有关矢量化的内容和编写更快的 MATLAB 代码,这里有一篇有趣的文章: Loren on the Art of MATLAB:“加速MATLAB 应用程序

Happy coding!快乐编码!

While the previous answer is correct in general terms, vectorized in the context of ODEs means something more specific.虽然前面的答案在一般意义上是正确的,但在 ODE 上下文中矢量化意味着更具体的东西。 In short, a function f(t,y) is vectorized iff f(t,[y1 y2 ...]) returns [f(t,y1) f(t,y2) ...] , for y1,y2 column vectors.简而言之,函数f(t,y)被向量化,如果f(t,[y1 y2 ...])返回[f(t,y1) f(t,y2) ...] ,对于y1,y2列向量。 As per the documentation [1], "this allows the solver to reduce the number of function evaluations required to compute all the columns of the Jacobian matrix."根据文档 [1],“这允许求解器减少计算雅可比矩阵的所有列所需的函数评估次数。”

Functions fun3 and fun4 below are properly vectorized in the ODE sense:下面的函数fun3fun4在 ODE 意义上被正确矢量化:

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,:);];

(As a side remark: omitting the unnecessary memory allocation with zeros lets fun4 run slightly faster than fun3 .) fun4说一句:用zeros省略不必要的内存分配让fun4运行速度略快于fun3 。)

  • Q: What about vectorizing with respect to the first argument?问:关于第一个参数的矢量化怎么样?
  • A: For the ODE solvers, the ODE function is vectorized only with respect to the second argument.答:对于 ODE 求解器,ODE 函数仅针对第二个参数进行矢量化。 The boundary value problem solver bvp4c , however, does require vectorization with respect to the first and second arguments.然而,边界值问题求解器bvp4c确实需要对第一个和第二个参数进行矢量化。 [1] [1]

The official documentation [1] provides further details on ODE-specific vectorization (see section "Description of Jacobian Properties").官方文档 [1] 提供了有关 ODE 特定矢量化的更多详细信息(请参阅“雅可比属性说明”一节)。

[1] https://www.mathworks.com/help/releases/R2015b/matlab/ref/odeset.html [1] https://www.mathworks.com/help/releases/R2015b/matlab/ref/odeset.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM