3

私が頌歌を持っていて、それを次のように 2 つの方法で書いたとします。

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

時間的にはほとんど差がありません。一方は他方と同じくらい時間がかかります。funしかし、それは のベクトル化されたバージョンだと思いましたfun2。それとも私はここで間違っていますか?目的は、コードを少し高速化することです。この例は、matlab Web ページから取得されます。「ベクトル化」の意味をよく理解していないと思います。これが既にベクトル化されている場合、ベクトル化されていないコードはどのようになりますか?

4

2 に答える 2

1

前の回答は一般的には正しいですが、ODE のコンテキストでベクトル化すると、より具体的な意味になります。つまり、関数f(t,y)は、列ベクトルに対してf(t,[y1 y2 ...])が返される場合にベクトル化されます。ドキュメント[1]によると、「これにより、ソルバーはヤコビ行列のすべての列を計算するために必要な関数評価の数を減らすことができます。」[f(t,y1) f(t,y2) ...]y1,y2

以下の関数はfun3fun4ODE の意味で適切にベクトル化されます。

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できます。)fun4fun3

  • Q: 最初の引数に関するベクトル化についてはどうですか?
  • A: ODE ソルバーの場合、ODE 関数は 2 番目の引数に関してのみベクトル化されます。ただし、境界値問題ソルバーbvp4cは、1 番目と 2 番目の引数に関してベクトル化を必要とします。[1]

公式ドキュメント [1] には、ODE 固有のベクトル化に関する詳細が記載されています (セクション「ヤコビ プロパティの説明」を参照)。

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

于 2021-01-31T06:53:44.513 に答える