MATLAB プロファイラーを使用した MEX 関数のプロファイリング
MATLAB® Coder™ によって生成された MEX 関数の実行時間を MATLAB プロファイラーを使用してプロファイリングできます。生成コードのプロファイルには、呼び出し回数および対応する MATLAB 関数の各行に要した時間が表示されます。最も時間がかかる生成コードを生み出した MATLAB コードの行を特定するには、プロファイラーを使用します。この情報は、開発サイクルの初期段階でパフォーマンスの問題を特定して修正するのに役立ちます。MATLAB プロファイラーの詳細については、profile
とパフォーマンス向上のためのコードのプロファイリングを参照してください。
プロファイラーへのグラフィカルなインターフェイスは MATLAB Online™ ではサポートされていません。
MEX プロファイルの生成
生成された MEX 関数で MATLAB プロファイラーを使用することができます。あるいは、MATLAB 関数を呼び出すテスト ファイルがある場合は、MEX 関数の生成とプロファイリングを 1 ステップで実行できます。これらの操作は、コマンド ラインまたは MATLAB Coder アプリで実行できます。
生成された MEX 関数でプロファイラーを使用するには、以下を実行します。
構成オブジェクト プロパティ
EnableMexProfiling
をtrue
に設定することで、MEX プロファイリングを有効にします。代わりに、
-profile
オプションを指定してcodegen
を使用することもできます。MATLAB Coder アプリでの同等の設定は、[生成] ステップの [実行プロファイリングを有効にする] です。
MEX ファイル
MyFunction_mex
を生成します。MATLAB プロファイラーを実行し、別のウィンドウで開くプロファイル概要レポートを表示します。
profile on; MyFunction_mex; profile viewer;
元の MATLAB ファイル
MyFunction.m
を変更または移動させていないことを確認します。変更または移動させていた場合、プロファイラーはプロファイリングでMyFunction_mex
を考慮しません。
MATLAB 関数を呼び出すテスト ファイル MyFunctionTest.m
がある場合は、以下を実行できます。
-test
オプションと-profile
オプションを指定したcodegen
を使用して、MEX 関数の生成とプロファイリングを 1 ステップで実行できます。以前に MATLAB プロファイラーをオンにしていた場合は、これら 2 つのオプションを一緒に使用する前にオフにします。codegen MyFunction -test MyFunctionTest -profile
アプリの [検証] ステップの [実行プロファイリングを有効にする] を選択することで、MEX 関数をプロファイリングします。以前に MATLAB プロファイラーをオンにしていた場合は、この操作を実行する前にオフにします。
例
プロファイラーを使用して、最も時間がかかる生成コードを生み出す関数または MATLAB コードの行を特定します。入力行列 A
および B
の表現を行優先から列優先のレイアウトに 1 行で変換する MATLAB 関数の例を以下に示します。大規模な行列の場合は、こうした変換の実行に長い時間を要します。特定の行を変更して変換を回避することで、関数の効率性が向上します。
以下の MATLAB 関数について考えます。
function [y] = MyFunction(A,B) %#codegen % Generated code uses row-major representation of matrices A and B coder.rowMajor; length = size(A,1); % Summing absolute values of all elements of A and B by traversing over the % matrices row by row sum_abs = 0; for row = 1:length for col = 1:length sum_abs = sum_abs + abs(A(row,col)) + abs(B(row,col)); end end % Calling external C function 'foo.c' that returns the sum of all elements % of A and B sum = 0; sum = coder.ceval('foo',coder.ref(A),coder.ref(B),length); % Returning the difference of sum_abs and sum y = sum_abs - sum; end
この関数の生成コードでは、正方行列 A
および B
の行優先の表現を使用します。コードでは最初に、行列を行ごとに移動することで sum_abs
(A
と B
のすべての要素の絶対値の合計) を計算します。このアルゴリズムは、行優先のレイアウトで表現される行列向けに最適化されています。次に、コードでは coder.ceval
を使用して外部の C 関数 foo.c
を呼び出します。
#include <stdio.h> #include <stdlib.h> #include "foo.h" double foo(double *A, double *B, double length) { int i,j,s; double sum = 0; s = (int)length; /*Summing all the elements of A and B*/ for(i=0;i<s*s;i++) { sum += A[i] + B[i]; } return(sum); }
対応する C ヘッダー ファイル foo.h
は以下の通りです。
#include "rtwtypes.h" double foo(double *A, double *B, double length);
foo.c
は変数 sum
を返します。この変数は、A
と B
のすべての要素の合計です。関数 foo.c
のパフォーマンスは、行列 A
と B
が行優先のレイアウトまたは列優先のレイアウトで表現されるかどうかに影響されません。MyFunction
は sum_abs
と sum
の差を返します。
大規模な入力行列 A
と B
の MyFunction
のパフォーマンスを測定してから、それをさらに最適化できます。
MEX プロファイリングを有効にして、
MyFunction
の MEX コードを生成します。2 つの大規模な乱数行列A
とB
に対してMyFunction_mex
を実行します。プロファイル概要レポートを確認します。A = rand(20000); B = rand(20000); codegen MyFunction -args {A,B} foo.c foo.h -profile profile on; MyFunction_mex(A,B); profile viewer;
別のウィンドウが開き、プロファイル概要レポートが表示されます。
プロファイル概要レポートには MEX ファイルとその子 (元の MATLAB 関数の生成コード) の合計時間と自己時間が表示されます。
[関数名] で最初のリンクをクリックし、
MyFunction
の生成コードのプロファイル詳細レポートを表示します。最も時間がかかった行を確認できます。coder.ceval
を呼び出す行に時間がかかっています (16.914 秒)。この行の実行にかなりの時間を要したのは、外部の C 関数に渡す前に、coder.ceval
が行列A
とB
の表現を行優先のレイアウトから列優先のレイアウトに変換するためです。coder.ceval
で追加の引数-layout:rowMajor
を使用することで、この変換を回避することができます。sum = coder.ceval('-layout:rowMajor','foo',coder.ref(A),coder.ref(B),length);
変更した
MyFunction
を使用して、MEX 関数とプロファイルを再度生成します。A = rand(20000); B = rand(20000); codegen MyFunction -args {A,B} foo.c foo.h -profile profile on; MyFunction_mex(A,B); profile viewer;
MyFunction
のプロファイル詳細レポートは、coder.ceval
を呼び出す行にかかる時間がわずか 0.653 秒になったことを示しています。
MEX コード カバレッジに対する式の畳み込みの効果
coder.const
を使用して式を定数に畳み込むとき、MATLAB 関数と MEX 関数の間のコード カバレッジに差異が生じます。たとえば、以下の関数について考えます。
function y = MyFoldFunction %#codegen a = 1; b = 2; c = a + b; y = 5 + coder.const(c); end
MATLAB 関数 MyFoldFunction
をプロファイリングすると、プロファイル詳細レポートにこのコード カバレッジが表示されます。
しかし、MEX 関数 MyFoldFunction_mex
をプロファイリングすると異なるコード カバレッジが表示されます。
コード生成では式 c = a + b
を定数に畳み込んでいるため、行 2、3 および 4 は生成コードでは実行されません。
この例では、ユーザー定義の式の畳み込みを使用します。コード ジェネレーターは、生成コードのパフォーマンスを最適化するために、特定の式を自動的に畳み込む場合があります。こうした最適化も、MEX 関数のカバレッジが MATLAB 関数と異なるものになる要因です。
参考
profile
| codegen
| coder.MexCodeConfig
| coder.rowMajor
| coder.ceval
| coder.const