fiaccel を使用したコードの高速化
fiaccel による固定小数点実行の高速化
fiaccel
を使用すると、固定小数点 MATLAB® コードを MEX 関数に変換できます。生成される MEX 関数には、MATLAB で固定小数点アルゴリズムをコンパイル済み C/C++ コードのスピードに自動的に高速化するための最適化機能が含まれています。関数 fiaccel
によって、アルゴリズムの実行速度が大幅に向上されます。
fiaccel の実行
以下に基本のコマンドを示します。
fiaccel M_fcn
既定では、fiaccel
は次のアクションを実行します。
コンパイル パスの検索順序に指定されているように、ファイル
M_fcn
.m
に保存されている関数M_fcn
を検索します。M_fcn
を MEX コードにコンパイルします。エラーや警告がない場合は、ファイル命名規則に説明されている命名規則を使用して、現在のフォルダーにプラットフォーム固有の MEX ファイルを生成します。
エラーがある場合は MEX ファイルは生成しませんが、生成ファイルと場所に説明されているように、エラー レポートを既定の出力フォルダーに生成します。
警告がある場合でエラーがない場合は、現在のフォルダーにプラットフォーム固有の MEX ファイルを生成し、警告をレポートします。
この既定の動作は、fiaccel
で 1 つ以上のコンパイラ オプションを指定して変更できます (複数のオプションはコマンド ライン上で空白で区切ります)。
生成ファイルと場所
fiaccel
では次の場所にファイルが生成されます。
生成物 | In: |
---|---|
プラットフォーム固有の MEX ファイル | 現在のフォルダー |
コード生成レポート (コンパイル中にエラーや警告が発生した場合) | 既定の出力フォルダー: fiaccel/mex/M_fcn_name/html |
生成ファイルの名前と場所を変更するには、fiaccel
を実行する際にオプション -o
と -d
を使用します。
この例では、関数 fiaccel
を使用し、簡単なアルゴリズムの異なる部分をコンパイルします。この 2 つのケースの実行時間を比較すれば、関数 fiaccel
の利点と最適な使用方法を理解できます。
アルゴリズムの異なる部分を高速化する場合の実行時間の比較
この例では、関数 fiaccel を使用して簡単なアルゴリズムの異なる部分をコンパイルする方法を示します。
この例で使用するアルゴリズムは MATLAB 関数 sum
の機能を複製したもので、行列の列の和を計算します。
type fi_matrix_column_sum.m
function B = fi_matrix_column_sum(A) % Sum the columns of matrix A. % Copyright 2008-2023 The MathWorks, Inc. %#codegen [m,n] = size(A); w = get(A,'WordLength') + ceil(log2(m)); f = get(A,'FractionLength'); B = fi(zeros(1,n),true,w,f,fimath(A)); for j = 1:n for i = 1:m B(j) = B(j) + A(i,j); end end
試行 1: 最良のパフォーマンス
アルゴリズムの実行速度を上げる最良の方法は、関数 fiaccel
を使用してアルゴリズム全体をコンパイルすることです。アルゴリズム全体をコンパイルする場合に、関数 fiaccel
によって実現されるパフォーマンスの向上を評価するには、次のコードを実行します。
コードの最初の部分は、MATLAB 関数だけを使用してアルゴリズムを実行します。
fipref('NumericTypeDisplay','short'); A = fi(randn(1000,10)); tic B = fi_matrix_column_sum(A); t_matrix_column_sum_m = toc
t_matrix_column_sum_m = 3.8430
コードの 2 番目の部分は、関数 fiaccel を使用してアルゴリズム全体をコンパイルします。MATLAB 関数 tic
と toc
は、それぞれの方法による実行時間を記録します。
fiaccel fi_matrix_column_sum -args {A} tic B = fi_matrix_column_sum_mex(A); t_matrix_column_sum_mex = toc
t_matrix_column_sum_mex = 0.1714
試行 2: 最悪のパフォーマンス
関数 fiaccel
を使用して計算の最小ユニットだけをコンパイルすると、実行速度が大幅に低下します。入れ子になっているループ内で関数 mex
を呼び出すことで生じるオーバーヘッドのため、MATLAB 関数のみを使用する場合よりも実行速度が低下することもあります。計算の最小ユニットだけをコンパイルする場合の mex
関数のパフォーマンスを評価するには、次のコードを実行します。
コードの最初の部分は、MATLAB 関数だけを使用してアルゴリズムを実行します。
tic [m,n] = size(A); w = get(A,'WordLength') + ceil(log2(m)); f = get(A,'FractionLength'); B = fi(zeros(1,n),true,w,f); for j = 1:n for i = 1:m B(j) = fi_scalar_sum(B(j),A(i,j)); % B(j) = B(j) + A(i,j); end end t_scalar_sum_m = toc
t_scalar_sum_m = 11.0941
コードの 2 番目の部分は関数 fiaccel
で計算の最小ユニットをコンパイルし、計算の残りの部分は MATLAB で行います。
fiaccel fi_scalar_sum -args {B(1),A(1,1)} tic [m,n] = size(A); w = get(A,'WordLength') + ceil(log2(m)); f = get(A,'FractionLength'); B = fi(zeros(1,n),true,w,f); for j = 1:n for i = 1:m B(j) = fi_scalar_sum_mex(B(j),A(i,j)); % B(j) = B(j) + A(i,j); end end t_scalar_sum_mex = toc
t_scalar_sum_mex = 5.4848
実行時間の比率
試行 1 と試行 2 の結果を比較します。使用するコンピューターにより異なる実行時間が記録される場合もありますが、比率はほぼ同じになります。fiaccel
を使用してアルゴリズム全体をコンパイルした試行 (t_matrix_column_sum_mex.m
) と、スカラーの加算だけをコンパイルした試行 (t_scalar_sum_mex.m
) との間では比率に有意差があります。fiaccel
でコンパイルしていないファイル (t_matrix_column_sum_m
) の方が、fiaccel
を使用して計算の最小ユニットだけをコンパイルした場合 (t_scalar_sum_mex
) よりもまだ良い結果になっています。
t_scalar_sum_mex/t_matrix_column_sum_mex
ans = 32.0024
t_scalar_sum_mex/t_matrix_column_sum_m
ans = 1.4272
t_matrix_column_sum_m/t_matrix_column_sum_mex
ans = 22.4230
t_scalar_sum_m/t_scalar_sum_mex
ans = 2.0227
試行 1: 最良のパフォーマンス
アルゴリズムの実行速度を上げる最良の方法は、関数 fiaccel
を使用してアルゴリズム全体をコンパイルすることです。アルゴリズム全体をコンパイルする場合に、関数 fiaccel
によって実現されるパフォーマンスの向上を評価するには、次のコードを実行します。
コードの最初の部分は、MATLAB 関数だけを使用してアルゴリズムを実行します。コードの 2 番目の部分は、関数 fiaccel
を使用してアルゴリズム全体をコンパイルします。MATLAB の関数 tic
と toc
は、それぞれの方法による実行時間を記録します。
% MATLAB fipref('NumericTypeDisplay','short'); A = fi(randn(1000,10)); tic B = fi_matrix_column_sum(A) t_matrix_column_sum_m = toc % fiaccel fiaccel fi_matrix_column_sum -args {A} tic B = fi_matrix_column_sum_mex(A); t_matrix_column_sum_mex = toc
試行 2: 最悪のパフォーマンス
関数 fiaccel
を使用して計算の最小ユニットだけをコンパイルすると、実行速度が大幅に低下します。入れ子になっているループ内で関数 mex
を呼び出すことで生じるオーバーヘッドのため、MATLAB 関数のみを使用する場合よりも実行速度が低下することもあります。計算の最小ユニットだけをコンパイルする場合の mex
関数のパフォーマンスを評価するには、次のコードを実行します。
コードの最初の部分は、MATLAB 関数だけを使用してアルゴリズムを実行します。コードの 2 番目の部分は関数 fiaccel
で計算の最小ユニットをコンパイルし、計算の残りの部分は MATLAB 関数で行います。
% MATLAB tic [m,n] = size(A); w = get(A,'WordLength') + ceil(log2(m)); f = get(A,'FractionLength'); B = fi(zeros(1,n),true,w,f); for j = 1:n for i = 1:m B(j) = fi_scalar_sum(B(j),A(i,j)); % B(j) = B(j) + A(i,j); end end t_scalar_sum_m = toc % fiaccel fiaccel fi_scalar_sum -args {B(1),A(1,1)} tic [m,n] = size(A); w = get(A,'WordLength') + ceil(log2(m)); f = get(A,'FractionLength'); B = fi(zeros(1,n),true,w,f); for j = 1:n for i = 1:m B(j) = fi_scalar_sum_mex(B(j),A(i,j)); % B(j) = B(j) + A(i,j); end end t_scalar_sum_mex = toc
実行時間の比率
試行 1 と試行 2 の比較を次の表に示します。使用するコンピューターにより実行時間が表の値と異なる場合もありますが、比率はほぼ同じになります。fiaccel
を使用してアルゴリズム全体をコンパイルした試行 (t_matrix_column_sum_mex.m
) と、スカラーの加算だけをコンパイルした試行 (t_scalar_sum_mex.m
) との間では比率に極端な差があります。fiaccel
でコンパイルしていないファイル (t_matrix_column_sum_m
) の方が、fiaccel
を使用して計算の最小ユニットだけをコンパイルした場合 (t_scalar_sum_mex
) よりもまだ良い結果になっています。
X (全体のパフォーマンス ランク) | 時間 | X/最良 | X_m/X_mex |
---|---|---|---|
試行 1: 最良のパフォーマンス | |||
t_matrix_column_sum_m (2) | 1.99759 | 84.4917 | 84.4917 |
t_matrix_column_sum_mex (1) | 0.0236424 | 1 | |
試行 2: 最悪のパフォーマンス | |||
t_scalar_sum_m (4) | 10.2067 | 431.71 | 2.08017 |
t_scalar_sum_mex (3) | 4.90664 | 207.536 |
fiaccel を使用したデータ型オーバーライド
データ型オーバーライドを有効にするには、reset(fipref)
コマンドを実行した後、MATLAB プロンプトで次のコマンドを入力します。
fipref('DataTypeOverride','TrueDoubles')
このコマンドは Fixed-Point Designer™ ソフトウェアにすべての fi
オブジェクトを fi
double
型で作成するよう指示します。fiaccel
コマンドを使用してコードをコンパイルすると、その結果作成される MEX 関数は浮動小数点データを使用します。
MEX 関数に対する既定の fimath
値の指定
fiaccel
で生成された MEX 関数では、MATLAB の既定のグローバル fimath
が使用されます。MATLAB 出荷時の既定のグローバル fimath
には以下のプロパティがあります。
RoundingMethod: Nearest OverflowAction: Saturate ProductMode: FullPrecision SumMode: FullPrecision
MATLAB の既定の fimath
値に依存する MEX 関数を実行しているときは、MATLAB セッション中にこの値を変更しないでください。変更すると、コンパイル時と実行時の fimath
の値が一致していないという警告が MATLAB によって生成されます。たとえば、次の MATLAB 関数を作成します。
function y = test %#codegen y = fi(0);
test
は、fimath
オブジェクトを明示的に指定することなく fi
オブジェクトを構築します。したがって、test
は、実際にはコンパイル時に既定の fimath
オブジェクトに依存することになります。 MEX 関数 test_mex
を生成し、MATLAB の既定の fimath
の出荷時の設定を使用します。
resetglobalfimath;
fiaccel test
fiaccel
は現在のフォルダーに MEX 関数 test_mex
を生成します。test_mex
を実行します。
test_mex
ans = 0 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 15
MATLAB の既定の fimath
値を変更して、コンパイル時に使用される設定と一致しないようにします。
F = fimath('RoundingMethod','Floor'); globalfimath(F);
メモリから MEX 関数をクリアして、再度実行します。
clear test_mex
test_mex
testglobalfimath_mex Warning: This function was generated with a different default fimath than the current default. ans = 0 DataTypeMode: Fixed-point: binary point scaling Signedness: Signed WordLength: 16 FractionLength: 15
fimath
プロパティを分離します。詳細は、データ型定義のアルゴリズムからの分離を参照してください。