生成コードのパフォーマンスと可読性を微調整するためのインライン化の制御
インライン化は、関数呼び出しをその関数の内容 (本文) と置き換える最適化手法です。インライン化によって関数呼び出しのオーバーヘッドが排除されるため、速度が向上します。
アプリケーションによっては、コードのインライン化が多すぎると次のような特定の欠点が生じる可能性もあります。
インライン化によって、生成される C/C++ コードが長くなり、コードの可読性が低下する可能性があります。たとえば、ソース MATLAB® コードで特定の関数
foo
を何度も呼び出すとします。コード ジェネレーターがfoo
を常にインライン化する場合、foo
は呼び出されるたびにインライン化されるため、生成コードのサイズは増加します。ただし、これが生じるには、呼び出しサイトが異なっていなければなりません。たとえば、foo
がループ内で何度呼び出されても、インライン化によってコード サイズが大きくなることはありません。ライン外の関数の場合、関数のローカル変数のスタック領域は、関数が返ったときに解放されます。インライン関数では、関数が返されても、ローカル変数によってスタック領域は占有されたままになります。したがって、RAM またはスタック領域が制限されている場合は、関数のインライン化を制限することをお勧めします。
コード ジェネレーターは、内部のヒューリスティックな方法を使用して、生成コードで関数をインライン化するかどうかを判定します。このヘルプ トピックでは、このようなヒューリスティックな方法を微調整し、アプリケーションの速度、可読性およびスタック領域の要件を満たすコードを生成する方法について説明します。
特定の MATLAB 関数のインライン化の制御
特定の MATLAB 関数を常にインライン化する、または決してインライン化しないようにコード ジェネレーターに指示するには、その関数の本体内で coder.inline('always')
命令と coder.inline('never')
命令を使用します。これらの命令の詳細については、coder.inline
を参照してください。
コード生成設定を使用したインライン化の制御
記述した関数用に生成されるコードと MathWorks® 関数用に生成されるコードでは速度および可読性の要件が異なる場合があります。特定のコード生成設定を使用すると、生成コード ベースのこれら 2 つの部分に関するインライン化の動作を、それらの間の境界で個別に制御できます。このような設定は、MEX コードとスタンドアロン コードの両方の生成に適用されます。
コード構成パラメーター | 説明 | オプション |
---|---|---|
コード構成オブジェクトの場合: MATLAB Coder™ アプリの場合: [すべての設定] タブの [ユーザー関数間のインライン] | 記述した関数が別の記述した関数を呼び出すすべての呼び出しサイトにおけるインライン化の動作を制御します。 | 'Always' | 'Speed' (既定値) | 'Readability' | 'Never' |
コード構成オブジェクトの場合: MATLAB Coder アプリの場合: [すべての設定] タブの [MathWorks 関数間のインライン] | MathWorks 関数が別の MathWorks 関数を呼び出すすべての呼び出しサイトにおけるインライン化の動作を制御します。 | 'Always' | 'Speed' (既定値) | 'Readability' | 'Never' |
コード構成オブジェクトの場合: MATLAB Coder アプリの場合: [すべての設定] タブの [ユーザー関数と MathWorks 関数の間のインライン] | 記述した関数が MathWorks 関数を呼び出すか、MathWorks 関数が記述した関数を呼び出すすべての呼び出しサイトにおけるインライン化の動作を制御します。 | 'Always' | 'Speed' (既定値) | 'Readability' | 'Never' |
オプションの説明:
'Always'
:呼び出しサイトでインライン化を常に実行します。'Speed'
:内部のヒューリスティックな方法を使用して、呼び出しサイトでインライン化を実行するかどうかを判定します。通常、この設定を使用すると高度に最適化されたコードが生成されます。この設定が既定の設定です。'Readability'
:非常に小さい関数の呼び出しを除き、関数呼び出しのインライン化をほぼ実行しません。可能な限り、速度を大幅に低下させることなくコードのモジュール性を維持します。非常に読みやすいコードが生成されます。'Never'
:関数呼び出しのインライン化を実行しません。最大限の可読性が得られます。この設定では、生成コードのパフォーマンスが大幅に低下する可能性があります。
メモ
インライン パラメーターで選択したオプションにコード ジェネレーターが厳密に従わない場合があります。たとえば、MathWorks 関数の本体に coder.inline('never')
命令が含まれている場合に InlineBetweenMathWorksFunctions
を 'Always'
に設定すると、コード ジェネレーターは coder.inline
命令を優先し、その関数をインライン化しません。詳細については、異なるインライン化制御間の相互作用を参照してください。
インライン化戦略の例
これは、生成コードの速度と可読性のバランスを取るインライン化戦略の例です。次のアクションを同時に実行するようにコード ジェネレーターに指示します。
可読性を高めるため、生成コードの速度が低下するとしても、記述したコードのモジュール性を維持します。この動作のためには、
InlineBetweenUserFunctions
を'Readability'
に設定します。コードの可読性が低下するとしても、MathWorks 関数の高度に最適化されたコードを生成します。コード ベースのこの部分を検査する可能性は低いためです。この動作のためには、
InlineBetweenMathWorksFunctions
を'Speed'
に設定します。生成コードで、記述した関数と MathWorks 関数を分離して、生成コードの外観が MATLAB コードとあまり異ならないようにします。この動作のためには、
InlineBetweenUserAndMathWorksFunctions
を'Readability'
に設定します。
異なるインライン化制御間の相互作用
MATLAB 関数の本体内に配置された
coder.inline('always')
命令またはcoder.inline('never')
命令は、codegen
オプションやコード構成設定などのグローバルなインライン化制御の効果をオーバーライドします。coder.inline
を参照してください。特定の MathWorks 関数には、これらの関数がグローバルなインライン化設定とどのように相互作用するかに影響する
coder.inline
命令の呼び出しが含まれます。たとえば、MathWorks 関数の本体にcoder.inline('never')
命令が含まれている場合にInlineBetweenMathWorksFunctions
を'Always'
に設定すると、コード ジェネレーターはcoder.inline
命令を優先し、その関数をインライン化しません。codegen
コマンドの-O disable:inline
オプションと-O enable:inline
オプションは、3 つのコード構成パラメーターInlineBetweenUserFunctions
、InlineBetweenMathWorksFunctions
およびInlineBetweenUserAndMathWorksFunctions
の各値をオーバーライドします。
例: 記述した関数と MathWorks® 関数の間の境界におけるインライン化の制御
この例では、記述した関数が MathWorks 関数を呼び出すか、MathWorks 関数が記述した関数を呼び出すすべての呼び出しサイトにおけるインライン化の動作を制御する方法を示します。
MathWorks 関数を呼び出す関数の定義
double の配列 x
を入力として受け入れ、関数bessely
を使用して入力配列を処理し、x
と同じ型およびサイズをもつ配列を返す MATLAB 関数 useBessely
を定義します。
type useBessely.m
function out = useBessely(x) out = x + bessely(3,x); end
既定のインライン化設定を使用したコードの生成
関数 useBessely
の C++ スタティック ライブラリを生成します。入力を 1
行 100
列の double
型に指定します。インライン化設定に既定値を使用します。これらの既定値によって生成コードの速度が最適化されます。ソース コードの生成のみを行い、ソース コードをビルドしないようにコード ジェネレーターに指示する -c
フラグを使用します。
codegen -c -lang:c++ -config:lib useBessely -args {zeros(1,100)} -report
Code generation successful: To view the report, open('codegen/lib/useBessely/html/report.mldatx')
コード生成レポートを開き、生成されたコードを検査します。MathWorks 関数 bessely
に対して個別の C++ 関数が生成されていないことを確認します。コード ジェネレーターにより、関数 bessely
のコードが、ファイル useBessely.cpp
に含まれている C++ 関数 useBessely
にインライン化されています。
変更されたインライン化設定を使用したコードの生成
C++ スタティック ライブラリを生成するためのコード構成オブジェクト cfg
を定義します。InlineBetweenUserAndMathWorksFunctions
プロパティを 'Never'
に設定します。この設定は、コード ジェネレーターに対して、記述した関数と MathWorks 関数を生成コードで分離するように指示します。その結果、生成された C++ コードは効率が低下しますが、インライン化されたコードよりも読みやすくなります。
cfg = coder.config('lib'); cfg.TargetLang = 'C++'; cfg.InlineBetweenUserAndMathWorksFunctions = 'Never';
cfg
をコード構成オブジェクトとして使用してコードを生成します。入力を 1
行 100
列の double
型に指定します。ソース コードの生成のみを行い、ソース コードをビルドしないようにコード ジェネレーターに指示する -c
フラグを使用します。
codegen -c -config cfg useBessely -args {zeros(1,100)} -report
Code generation successful: To view the report, open('codegen/lib/useBessely/html/report.mldatx')
コード生成レポートを開き、生成されたコードを検査します。C++ 関数 useBessely
は、MathWorks 関数 bessely
に対して生成されたコードを含む別の C++ 関数 coder::bessely
を呼び出します。その結果、生成された C++ 関数 useBessely
は、記述した MATLAB 関数 useBessely
と同様の外観になります。
type codegen/lib/useBessely/useBessely.cpp
// // Prerelease License - for engineering feedback and testing purposes // only. Not for sale. // File: useBessely.cpp // // MATLAB Coder version : 5.6 // C/C++ source code generated on : 30-Jan-2023 12:53:04 // // Include Files #include "useBessely.h" #include "bessely.h" #include "rt_nonfinite.h" // Function Definitions // // Arguments : const double x[100] // creal_T out[100] // Return Type : void // void useBessely(const double x[100], creal_T out[100]) { coder::bessely(x, out); for (int i{0}; i < 100; i++) { out[i].re += x[i]; } } // // File trailer for useBessely.cpp // // [EOF] //
参考
coder.inline
| codegen
| coder.CodeConfig
| coder.EmbeddedCodeConfig
| coder.MexCodeConfig