このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
固定小数点の関数近似
固定小数点ライブラリ関数が使用できない場合、固定小数点アプリケーションにはその関数の近似が必要です。多くの場合、内挿されたルックアップ テーブルを使用して指定範囲の関数近似を保存します。
この例では、ルックアップ テーブルを使用して、指定された入力範囲において関数 y = sin(2*pi*x)
を近似する方法を示しています。
この例では、入力は符号なしの 16 ビット データ型 fixdt(0,16,16)
、出力は符号付きの 16 ビット データ型 fixdt(1,16,14)
を使用します。
この例の目的は、2 進小数点の右側 8 ビットまで正確な近似を作成することです。これは、最悪誤差が 2^(-8)
未満になるようにするということを意味します。
この目標を満たすルックアップ テーブルのデータ点集合は多数あります。メモリ使用量や計算速度といった目標に応じて、異なる実装を選択できます。この例では、最小のデータ点数でこの精度目標を満たすソリューションを見つけます。
関数の近似
FunctionApproximation.Options
オブジェクトを使用して精度と語長の制約を指定します。
options = FunctionApproximation.Options();
options.AbsTol = 2^-8;
options.RelTol = 0;
options.WordLengths = [8 16 32];
options.MemoryUnits = 'bytes';
options.OnCurveTableValues = true;
近似する関数と入力範囲、データ型を FunctionApproximation.Problem
オブジェクトで指定します。
functionToApproximate = @(x) sin(2*pi*x);
problem = FunctionApproximation.Problem(functionToApproximate, 'Options', options);
problem.InputTypes = numerictype(0,16,16);
problem.InputLowerBounds = 0;
problem.InputUpperBounds = 0.25;
problem.OutputType = numerictype(1,16,14);
ルックアップ テーブルの解を作成します。
solution = solve(problem);
Searching for fixed-point solutions. | ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 0 | 4.0000e+00 | 0 | 2 | 8 | 8 | EvenSpacing | 3.906250e-03, 2.105137e-01 | | 1 | 1.9000e+01 | 0 | 17 | 8 | 8 | EvenSpacing | 3.906250e-03, 4.257483e-03 | | 2 | 3.5000e+01 | 1 | 33 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.848536e-03 | | 3 | 2.8000e+01 | 1 | 26 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.768435e-03 | | 4 | 2.4000e+01 | 1 | 22 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.596819e-03 | | 5 | 2.1000e+01 | 1 | 19 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.589720e-03 | | 6 | 1.5000e+01 | 0 | 13 | 8 | 8 | EvenSpacing | 3.906250e-03, 7.812500e-03 | | 7 | 1.7000e+01 | 1 | 15 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.824648e-03 | | 8 | 1.2000e+01 | 0 | 10 | 8 | 8 | EvenSpacing | 3.906250e-03, 4.677033e-03 | | 9 | 1.1000e+01 | 0 | 9 | 8 | 8 | EvenSpacing | 3.906250e-03, 6.957420e-03 | | 10 | 1.4000e+01 | 1 | 12 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.687388e-03 | | 11 | 1.3000e+01 | 0 | 11 | 8 | 8 | EvenSpacing | 3.906250e-03, 7.812500e-03 | | 12 | 9.0000e+00 | 0 | 7 | 8 | 8 | EvenSpacing | 3.906250e-03, 7.818172e-03 | | 13 | 6.0000e+00 | 0 | 2 | 16 | 8 | EvenSpacing | 3.906250e-03, 2.105137e-01 | | 14 | 1.3000e+01 | 0 | 9 | 16 | 8 | EvenSpacing | 3.906250e-03, 6.957420e-03 | | 15 | 6.0000e+00 | 0 | 2 | 8 | 16 | EvenSpacing | 3.906250e-03, 2.105137e-01 | | 16 | 4.0000e+00 | 0 | 2 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 17 | 1.1000e+01 | 0 | 9 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 6.957420e-03 | | 18 | 6.0000e+00 | 0 | 2 | 16 | 8 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 19 | 1.3000e+01 | 0 | 9 | 16 | 8 | EvenPow2Spacing | 3.906250e-03, 6.957420e-03 | | 20 | 6.0000e+00 | 0 | 2 | 8 | 16 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 21 | 8.0000e+00 | 0 | 2 | 16 | 16 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 22 | 1.4000e+01 | 1 | 7 | 8 | 8 | ExplicitValues | 3.906250e-03, 3.830054e-03 | | 23 | 3.5000e+01 | 1 | 33 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 3.848536e-03 | Best Solution | ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 10 | 1.4000e+01 | 1 | 12 | 8 | 8 | EvenSpacing | 3.906250e-03, 3.687388e-03 |
ブレークポイントの仕様を EvenPow2Spacing
に変更し、ルックアップ テーブルの解を再作成します。
problem.Options.BreakpointSpecification = 'EvenPow2Spacing';
bestEvenPow2SpacingSolution = solve(problem);
Searching for fixed-point solutions. | ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 0 | 4.0000e+00 | 0 | 2 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 1 | 1.9000e+01 | 0 | 17 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 4.257483e-03 | | 2 | 3.5000e+01 | 1 | 33 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 3.848536e-03 | | 3 | 1.1000e+01 | 0 | 9 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 6.957420e-03 | | 4 | 6.0000e+00 | 0 | 2 | 16 | 8 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 5 | 2.1000e+01 | 0 | 17 | 16 | 8 | EvenPow2Spacing | 3.906250e-03, 4.257483e-03 | | 6 | 1.3000e+01 | 0 | 9 | 16 | 8 | EvenPow2Spacing | 3.906250e-03, 6.957420e-03 | | 7 | 6.0000e+00 | 0 | 2 | 8 | 16 | EvenPow2Spacing | 3.906250e-03, 2.105137e-01 | | 8 | 2.0000e+01 | 0 | 9 | 8 | 16 | EvenPow2Spacing | 3.906250e-03, 4.856432e-03 | Best Solution | ID | Memory (bytes) | Feasible | Table Size | Breakpoints WLs | TableData WL | BreakpointSpecification | Error(Max,Current) | | 2 | 3.5000e+01 | 1 | 33 | 8 | 8 | EvenPow2Spacing | 3.906250e-03, 3.848536e-03 |
ソリューションの確認
ソフトウェアは、FunctionApproximation.Problem
および FunctionApproximation.Options
オブジェクトで指定された要件を満たすいくつかの実装を返します。これらのさまざまな実装を確認できます。
feasibleSolutions = solution.FeasibleSolutions; tableDataVec = [feasibleSolutions.TableData]; evenSpacingSolutions = find([tableDataVec.IsEvenSpacing]); unevenSpacingSolutions = find(~[tableDataVec.IsEvenSpacing]); evenSolutionsMemoryUsage = arrayfun(@(x) x.totalMemoryUsage(), feasibleSolutions(evenSpacingSolutions)); unevenSolutionsMemoryUsage = arrayfun(@(x) x.totalMemoryUsage(), feasibleSolutions(unevenSpacingSolutions)); bestEvenSpacingSolution = feasibleSolutions(evenSpacingSolutions(evenSolutionsMemoryUsage == min(evenSolutionsMemoryUsage))); bestUnevenSpacingSolution = feasibleSolutions(unevenSpacingSolutions(unevenSolutionsMemoryUsage == min(unevenSolutionsMemoryUsage))); xeven = bestEvenSpacingSolution.TableData.BreakpointValues{1}; yeven = bestEvenSpacingSolution.TableData.TableValues; xuneven = bestUnevenSpacingSolution.TableData.BreakpointValues{1}; yuneven = bestUnevenSpacingSolution.TableData.TableValues; xpow2 = bestEvenPow2SpacingSolution.TableData.BreakpointValues{1}; ypow2 = bestEvenPow2SpacingSolution.TableData.TableValues;
メモリ使用量の比較
ルックアップ テーブルで使用されるメモリを比較します。
memoryValues = [... totalMemoryUsage(bestEvenPow2SpacingSolution), ... totalMemoryUsage(bestEvenSpacingSolution), ... totalMemoryUsage(bestUnevenSpacingSolution)]; figure(); xTickLabels = {'Even pow2 spacing \newline(fastest)','Even spacing \newline(faster)','Uneven spacing \newline(fast)'}; hMemory = bar(memoryValues); title('Comparison of memory usage obtained by different \newline breakpoint specification options'); hMemory.Parent.XTickLabel = xTickLabels; hMemory.Parent.XTickLabelRotation = 45; hMemory.Parent.YLabel.String = 'Memory (bytes)'; hMemory.Parent.Box = 'on'; hMemory.Parent.YGrid = 'on';
等間隔を使用する場合と不等間隔を使用する場合でテーブルが使用するメモリの量は同じですが、ポイントの数は異なります。これは、等間隔を使用するテーブルのブレークポイントを保存するときには、最初のポイントと間隔のみが保存されるためです。対照的に、不等間隔を使用するテーブルでは、すべてのブレークポイントが保存されます。
EvenPow2Spacing
では、等間隔の場合に保存されるポイントの倍を超えるポイントが保存されます。メモリ使用量の観点では、EvenPow2Spacing
はこの関数にとっては最も不適当です。ただし、EvenPow2Spacing
での計算は乗算ではなく算術シフトを使用して実行され、それによってより速い実行時間につながります。
ソリューションと元の関数との比較
EvenPow2Spacing
を使用するソリューションを元の関数と比較します。
[~, hEvenPow2Spacing] = compare(bestEvenPow2SpacingSolution);
hEvenPow2Spacing.Children(4).Title.String = [hEvenPow2Spacing.Children(4).Title.String ' (Even pow2 spacing)'];
等間隔を使用するソリューションを元の関数と比較します。
[~, hEvenSpacing] = compare(bestEvenSpacingSolution);
hEvenSpacing.Children(4).Title.String = [hEvenSpacing.Children(4).Title.String ' (Even spacing)'];
不等間隔を使用するソリューションを元の関数と比較します。
[~, hUnevenSpacing] = compare(bestUnevenSpacingSolution);
hUnevenSpacing.Children(4).Title.String = [hUnevenSpacing.Children(4).Title.String ' (Uneven spacing)'];
Simulink モデルでの近似の使用
この近似を Simulink Lookup Table (n-D) ブロックで直接使用できます。fxpdemo_approx
モデルは、異なるブレークポイント間隔仕様を使用してルックアップ テーブルを比較します。LUT は関数 sin(2*pi*x)
を近似します。
modelName = 'fxpdemo_approx'; open_system(modelName) modelWorkspace = get_param(modelName, 'ModelWorkspace'); modelWorkspace.assignin('xevenFirstPoint' , xeven(1) ); modelWorkspace.assignin('xevenSpacing' , diff(xeven(1:2)) ); modelWorkspace.assignin('yeven' , yeven ); modelWorkspace.assignin('TableDTeven' , bestEvenSpacingSolution.TableData.TableDataType ); modelWorkspace.assignin('BreakpointDTeven' , bestEvenSpacingSolution.TableData.BreakpointDataTypes); modelWorkspace.assignin('xuneven' , xuneven); modelWorkspace.assignin('yuneven' , yuneven); modelWorkspace.assignin('TableDTuneven' , bestUnevenSpacingSolution.TableData.TableDataType ); modelWorkspace.assignin('BreakpointDTuneven' , bestUnevenSpacingSolution.TableData.BreakpointDataTypes); modelWorkspace.assignin('xpow2FirstPoint' , xpow2(1) ); modelWorkspace.assignin('xpow2Spacing' , diff(xpow2(1:2)) ); modelWorkspace.assignin('ypow2' , ypow2 ); modelWorkspace.assignin('TableDTpow2' , bestEvenPow2SpacingSolution.TableData.TableDataType ); modelWorkspace.assignin('BreakpointDTpow2' , bestEvenPow2SpacingSolution.TableData.BreakpointDataTypes); set_param(modelName, 'Dirty', 'off');
概要
モデル fxpdemo_approx
では、理想関数と 3 つの近似が使用されます。モデルをシミュレートします。
sim(modelName)
コードの生成
Simulink® Coder™ がインストールされている場合、モデルのコードを生成できます。インライン パラメーターが ON の場合、不均等な間隔、等間隔、および 2 のべき乗の間隔の実装において効率に大きな違いがあることが、生成されるコードに示されます。