Matlabユザコミュニティ

MATLAB & 金宝appSimulinkユ,ザ,コミュニティ,向け日本語ブログ

MATLAB R2023aアップデ,ト:関数ハンドルの高速化

※この投稿は2023年3月16日にMATLAB博客(迈克裘槎)に投稿されたものの抄訳です。


MathWorksがMATLABの処理速度を上げる方法は大きく分けて2あります。個々の関数に潜り込んでオーバーヘッドを除去したり,アルゴリズムを改善したりする方法と,MATLAB言語自体のパフォーマンスを向上させて高速化する方法です。
今日は,R2023aリリ,スで関数ハンドルの高速化が行われた,後者の例を見てみましょう。

関数ハンドルって何?

ドキュメントからそのまま引用すると··”関数ハンドルは,関数を表すmatlab®デ,タ型です。一般に,関数ハンドルは関数を別の関数に渡すために使用します。たとえば,関数ハンドルは,所定の値の範囲に対して数式を評価する関数の入力引数として使用できます。」
例えば,こんな関数があったとします。
函数y = computeSquare(x)
Y = x.^2;
结束
この関数にたいして関数ハンドルを作って,
f = @computeSquare
値をもf =function_handle:
@computeSquare
4の二乗をこんな感じで計算できます。
B = f(4)
B = 16
この”それがどうした・・”的に見える機能は非常に便利で,MATLABコードのいたるところで使われているのを見かけると思います。

関数ハンドルの速度チェック

関数ハンドルを使って,結果を保存せずに1億個の数字の二乗を計算してみましょう。特に意味のない計算ですが,R2023aで関数ハンドルのオーバーヘッドが大幅に削減されていることがわかります。
N = 1e8;
抽搐
I = 1:n
Out = f(i);
结束
T = toc
T = 0.7665
私のPCではこんな結果でした。
  • R2022b: 33秒
  • R2023a: 0.77秒
R2023aで40倍強の高速化となっています。パスやロ,カル関数への関数ハンドルは直接の関数呼び出しと同じくらいに高速化されています。
もう少し現実的な例を見てみましょう。

関数ハンドルの高速化= odeソルバ,の高速化

この例は,板凳上コマンド内で評価される関数から取ってきています。vanderpol関数は板凳上の最後に定義されており,ここでは@vanderpolというハンドル名で呼び出しています。計算を5回繰り返し,一番良い結果を取っています。
%的颂歌。范德波尔方程,= 1
Y0 = [2;0);
Tspan = [0 20000];
numRepeats = 5;%重复计算的次数。我以后只报告最好的一个。
t = 0 (1,numRepeats);存储计时结果
数= 1:numRepeats
抽搐
[s,y] = ode45(@vanderpol,tspan,y0);
T (count) = toc;
结束
流(ode45最好的时间是%。2 f秒\ n”最小值(t))
Ode45最佳时间为0.21秒
  • R2022b: 0.4秒
  • R2023a: 0.21秒
ほぼ2倍のスピ,ドアップです。これは,先に見た40倍のスピ,ドアップには程遠いですが,数值では関数呼び出し以外にもいろいろなことが行われているからですね。

最適化ソルバはどうだろう?

他にも,関数ハンドルを何度も使うようなものはある程度高速化されるはずです。Odeの次に考えたのは最適化。最適化処理でも目的関数が何度も呼ばれています。ここでは,シミュレ,テッドアニ,リングを使った全局优化工具箱の簡単な例を紹介します。
numRepeats = 5;%重复计算的次数。我以后只报告最好的一个。
t = 0 (1,numRepeats);存储计时结果
数= 1:numRepeats
rng默认的
X0 = [0.5 0.5];
[x,fval,exitFlag,output] = simulannealbnd(@objective,x0);
T (count) = toc;
结束
优化终止:最佳函数值的更改小于options.FunctionTolerance。
优化终止:最佳函数值的更改小于options.FunctionTolerance。
优化终止:最佳函数值的更改小于options.FunctionTolerance。
优化终止:最佳函数值的更改小于options.FunctionTolerance。
优化终止:最佳函数值的更改小于options.FunctionTolerance。
5回実行した中で一番速かったものは··
流(模拟退火的最佳时间为%。2 f秒\ n”最小值(t))
模拟退火的最佳时间为0.16秒
で何回関数が呼ばれているかというと··
流("优化器调用了%d个函数\n ", output.funccount);
优化器进行了2971次函数调用

R2022bとR2023aでの結果はこら。

  • R2022b: 0.19秒
  • R2023a: 0.16秒
残念ながらあまり速くなっていませんね。関数ハンドルの高速化では違いがでない例でした。30.00回の目的関数評価で節約できる関数ハンドルのオーバーヘッドは、私の PC では0.01 秒にも満たないと予想してますが、速くなってることは確かですね。

フィドバックお待しています

関数ハンドルを多用するコードで高速化を実感しているものがあれば,コメント欄やツイッターで是非教えてください。
函数y = computeSquare(x)
用于显示函数句柄开销
Y = x.^2;
结束
函数Dydt = vanderpol(~,y)
计算mu = 1时的范德波尔ode
%用于ode45演示
Dydt = [y(2);(1 y (1) ^ 2) * y (2) - y (1)];
结束
函数Y =目标(x)
%用于模拟退火演示
y = x (4 - 2.1 . * (1) ^ 2 + x(1)。^ 4. / 3)。* x (1) ^ 2 + x(1) *(2) +(4 + 4。* x(2) ^ 2)。* x (2) ^ 2;
结束
|

コメント

コメントを残すには,ここをクリックしてMathWorksアカウントにサインインするか新しいMathWorksアカウントを作成します。