Main Content

生成されたコードを使用した MATLAB Compiler で展開されるアプリケーションの高速化

この例では、生成されたコードを使用して、MATLAB® Compiler™ で展開するアプリケーションを高速化する方法を示します。この例では、MATLAB® Coder™ を使用してアルゴリズムの MEX バージョンを生成することでアルゴリズムを高速化します。MATLAB Compiler を使用して、MEX 関数を呼び出すスタンドアロン アプリケーションを展開します。展開されるアプリケーションでは、MATLAB® Runtime を使用します。これにより、MATLAB® をもたないユーザーに使用料なしで展開できるようになります。

このワークフローは、次の場合に役立ちます。

  • MATLAB Runtime でサポートするプラットフォームにアプリケーションを展開する場合。

  • アプリケーションに、コード生成に適した計算量の多いアルゴリズムが含まれる場合。

  • アルゴリズムに対して生成された MEX が元の MATLAB アルゴリズムよりも高速な場合。

  • アプリケーションの読み取り可能な C/C++ ソース コードを展開する必要がない場合。

この例のアプリケーションでは、DSP System Toolbox™ を必要とする DSP アルゴリズムを使用しています。

MATLAB アプリケーションの作成

高速化するためのベスト プラクティスは、計算量の多いアルゴリズムを、そのアルゴリズムを呼び出すコードから分離することです。

この例では、myRLSFilterSystemIDSim でアルゴリズムが実装されます。myRLSFilterSystemIDAppmyRLSFilterSystemIDSim を呼び出すユーザー インターフェイスを提供します。

myRLSFilterSystemIDSim は、再帰的最小二乗 (RLS) 適応フィルター処理を使用してシステム同定をシミュレートします。アルゴリズムは dsp.VariableBandwidthFIRFilter を使用して未同定のシステムをモデル化し、dsp.RLSFilter を使用して FIR フィルターを識別します。

myRLSFilterSystemIDApp は、シミュレーション パラメーターを動的に調整するために使用するユーザー インターフェイスを提供します。指定した数のタイム ステップに対して、またはシミュレーションを停止するまでシミュレーションが実行されます。シミュレーションの結果はスコープにプロットされます。

このアプリケーションの詳細については、DSP System Toolbox のドキュメンテーションのRLS 適応フィルター処理を使用したシステム同定 (DSP System Toolbox)を参照してください。

書き込み可能なフォルダーに、myRLSFilterSystemIDSimmyRLSFilterSystemIDApp を作成します。あるいは、[Open Script] をクリックしてこれらのファイルにアクセスします。

myRLSFilterSystemIDSim

function [tfe,err,cutoffFreq,ff] = ...
    myRLSFilterSystemIDSim(tuningUIStruct)
% myRLSFilterSystemIDSim implements the algorithm used in
% myRLSFilterSystemIDApp.
% This function instantiates, initializes, and steps through the System
% objects used in the algorithm.
%
% You can tune the cutoff frequency of the desired system and the
% forgetting factor of the RLS filter through the GUI that appears when
% myRLSFilterSystemIDApp is executed.

%   Copyright 2013-2017 The MathWorks, Inc.

%#codegen

% Instantiate and initialize System objects. The objects are declared
% persistent so that they are not recreated every time the function is
% called inside the simulation loop.
persistent rlsFilt sine unknownSys transferFunctionEstimator
if isempty(rlsFilt)
    % FIR filter models the unidentified system
    unknownSys = dsp.VariableBandwidthFIRFilter('SampleRate',1e4,...
        'FilterOrder',30,...
        'CutoffFrequency',.48 * 1e4/2);
    % RLS filter is used to identify the FIR filter
    rlsFilt = dsp.RLSFilter('ForgettingFactor',.99,...
        'Length',28);
    % Sine wave used to generate input signal
    sine = dsp.SineWave('SamplesPerFrame',1024,...
        'SampleRate',1e4,...
        'Frequency',50);
    % Transfer function estimator used to estimate frequency responses of
    % FIR and RLS filters.
    transferFunctionEstimator = dsp.TransferFunctionEstimator(...
        'FrequencyRange','centered',...
        'SpectralAverages',10,...
        'FFTLengthSource','Property',...
        'FFTLength',1024,...
        'Window','Kaiser');
end

if tuningUIStruct.Reset
    % reset System objects
    reset(rlsFilt);
    reset(unknownSys);
    reset(transferFunctionEstimator);
    reset(sine);
end

% Tune FIR cutoff frequency and RLS forgetting factor
if  tuningUIStruct.ValuesChanged
    param = tuningUIStruct.TuningValues;
    unknownSys.CutoffFrequency  = param(1);
    rlsFilt.ForgettingFactor = param(2);
end
    
% Generate input signal - sine wave plus Gaussian noise
inputSignal = sine() +  .1 * randn(1024,1);

% Filter input though FIR filter
desiredOutput = unknownSys(inputSignal);

% Pass original and desired signals through the RLS Filter
[rlsOutput , err] = rlsFilt(inputSignal,desiredOutput);

% Prepare system input and output for transfer function estimator
inChans = repmat(inputSignal,1,2);
outChans = [desiredOutput,rlsOutput];

% Estimate transfer function
tfe = transferFunctionEstimator(inChans,outChans);

% Save the cutoff frequency and forgetting factor
cutoffFreq = unknownSys.CutoffFrequency;
ff = rlsFilt.ForgettingFactor;

end

myRLSFilterSystemIDApp

function scopeHandles = myRLSFilterSystemIDApp(numTSteps)
% myRLSFilterSystemIDApp initialize and execute RLS Filter
% system identification example. Then, display results using
% scopes. The function returns the handles to the scope and UI objects.
%
% Input:
%   numTSteps - number of time steps
% Outputs:
%   scopeHandles    - Handle to the visualization scopes

% Copyright 2013-2017 The MathWorks, Inc.


if nargin == 0
    numTSteps = Inf; % Run until user stops simulation.
end

% Create scopes
tfescope = dsp.ArrayPlot('PlotType','Line',...
    'Position',[8 696 520 420],...
    'YLimits',[-80 30],...
    'SampleIncrement',1e4/1024,...
    'YLabel','Amplitude (dB)',...
    'XLabel','Frequency (Hz)',...
    'Title','Desired and Estimated Transfer Functions',...
    'ShowLegend',true,...
    'XOffset',-5000);

msescope = timescope('SampleRate',1e4,...
    'Position',[8 184 520 420],...
    'TimeSpanSource','property','TimeSpan',0.01,...
    'YLimits',[-300 10],'ShowGrid',true,...
    'YLabel','Mean-Square Error (dB)',...
    'Title','RLSFilter Learning Curve');

screen = get(0,'ScreenSize');
outerSize = min((screen(4)-40)/2, 512);
tfescope.Position = [8, screen(4)-outerSize+8, outerSize+8,...
    outerSize-92];
msescope.Position = [8, screen(4)-2*outerSize+8, outerSize+8, ...
    outerSize-92];

% Create UI to tune FIR filter cutoff frequency and RLS filter
%  forgetting factor
Fs = 1e4;
param = struct([]);
param(1).Name = 'Cutoff Frequency (Hz)';
param(1).InitialValue = 0.48 * Fs/2;
param(1).Limits = Fs/2 * [1e-5, .9999];
param(2).Name = 'RLS Forgetting Factor';
param(2).InitialValue = 0.99;
param(2).Limits = [.3, 1];
hUI = HelperCreateParamTuningUI(param, 'RLS FIR Demo');
set(hUI,'Position',[outerSize+32, screen(4)-2*outerSize+8, ...
    outerSize+8, outerSize-92]);

% Execute algorithm
while(numTSteps>=0)
    
    S = HelperUnpackUIData(hUI);

    drawnow limitrate;   % needed to process UI callbacks
    
    [tfe,err] = myRLSFilterSystemIDSim(S);
    
    if S.Stop     % If "Stop Simulation" button is pressed
        break;
    end
    if S.Pause
        continue;
    end
    
    % Plot transfer functions
    tfescope(20*log10(abs(tfe)));
    % Plot learning curve
    msescope(10*log10(sum(err.^2)));
    numTSteps = numTSteps - 1;
end

if ishghandle(hUI)  % If parameter tuning UI is open, then close it.
    delete(hUI);
    drawnow;
    clear hUI
end

scopeHandles.tfescope = tfescope;
scopeHandles.msescope = msescope;
end

MATLAB アプリケーションのテスト

100 のタイム ステップに対してシステム同定アプリケーションを実行します。アプリケーションは 100 タイム ステップの間、または [シミュレーションの中止] をクリックするまでシミュレーションを実行します。結果はスコープにプロットされます。

scope1 = myRLSFilterSystemIDApp(100);
release(scope1.tfescope);
release(scope1.msescope);

高速化するアルゴリズムの準備

MATLAB Coder を使用して MATLAB アルゴリズムを高速化する場合、コードはコード生成に適したものでなければなりません。

1. myRLSFilterSystemIDSim.m で、関数シグネチャの後に %#codegen 命令が含まれていることを確認します。

この命令は、関数のコードを生成することを示します。この命令により、MATLAB エディターでコード アナライザーはコード生成の問題を検出することができます。

2. サポートされない関数または構造体がないようアルゴリズムをスクリーニングします。

coder.screener('myRLSFilterSystemIDSim');

コード生成の準備状態ツールは、このアルゴリズムのコード生成に関する問題を検出しません。

アルゴリズムの高速化

アルゴリズムを高速化するために、この例では MATLAB Coder codegen コマンドを使用します。または、MATLAB Coder アプリを使用できます。コード生成の場合、入力引数の型、サイズおよび実数/複素数を指定しなければなりません。関数 myRLSFilterSystemIDSim は、調整情報を保存する構造体をとります。調整構造体の例を定義して、それを -args オプションを使用して codegen に渡します。

ParamStruct.TuningValues = [2400 0.99];
ParamStruct.ValuesChanged = false;
ParamStruct.Reset = false;
ParamStruct.Pause = false;
ParamStruct.Stop  = false;
codegen myRLSFilterSystemIDSim -args {ParamStruct};
Code generation successful.

codegen は現在のフォルダーに MEX 関数 myRLSFilterSystemIDSim_mex を作成します。

MEX 関数と MATLAB 関数のパフォーマンスの比較

1. myRLSFilterSystemIDSim の 100 回の実行時間を測定します。

clear myRLSFilterSystemIDSim
disp('Running the MATLAB function ...')
tic
nTimeSteps = 100;
for ind = 1:nTimeSteps
     myRLSFilterSystemIDSim(ParamStruct);
end
tMATLAB = toc;
Running the MATLAB function ...

2. myRLSFilterSystemIDSim_mex の 100 回の実行時間を測定します。

clear myRLSFilterSystemIDSim
disp('Running the MEX function ...')
tic
for ind = 1:nTimeSteps
    myRLSFilterSystemIDSim_mex(ParamStruct);
end
tMEX = toc;

disp('RESULTS:')
disp(['Time for original MATLAB function: ', num2str(tMATLAB),...
     ' seconds']);
disp(['Time for MEX function: ', num2str(tMEX), ' seconds']);
disp(['The MEX function is ', num2str(tMATLAB/tMEX),...
    ' times faster than the original MATLAB function.']);
Running the MEX function ...
RESULTS:
Time for original MATLAB function: 1.9438 seconds
Time for MEX function: 0.19591 seconds
The MEX function is 9.922 times faster than the original MATLAB function.

MEX コードの最適化

別の C/C++ コンパイラを使用するか、特定のオプションまたは最適化を使用して、より高速な MEX を生成できる場合があります。MATLAB アルゴリズムの高速化を参照してください。

この例では、MEX はこれ以上最適化しなくても十分に高速です。

MEX 関数を呼び出すためのアプリケーションの変更

myRLSFilterSystemIDSim ではなく myRLSFilterSystemIDSim_mex が呼び出されるように myRLSFilterSystemIDApp を変更します。

変更された関数を myRLSFilterSystemIDApp_acc.m に保存します。

高速化したアルゴリズムでのアプリケーションのテスト

clear myRLSFilterSystemIDSim_mex;
scope2 = myRLSFilterSystemIDApp_acc(100);
release(scope2.tfescope);
release(scope2.msescope);

MEX 関数を呼び出すアプリケーションの動作は、元の MATLAB 関数を呼び出すアプリケーションの動作と同じです。ただし、シミュレーションがより高速であるためプロットはより迅速に更新されます。

スタンドアロン アプリケーションの作成

1. アプリケーション コンパイラ アプリを開くには、[アプリ] タブの [アプリケーションの展開] にあるアプリのアイコンをクリックします。

2. メイン ファイルに myRLSFilterSystemIDApp_acc を指定します。

このアプリによって、このアプリケーションに必要なファイルを決定します。このアプリは、アプリケーションが使用する MATLAB ファイルと MEX ファイルを探すことができます。必要なファイルとして MAT ファイルやイメージなど他の種類のファイルを追加しなければなりません。

3. ツールストリップの [パッケージ化オプション] セクションで、[Web からダウンロードされたランタイム] チェック ボックスが選択されていることを確認します。

このオプションを選択すると、展開された MATLAB アプリケーションで MATLAB Runtime をダウンロードおよびインストールするアプリケーション インストーラーが作成されます。

4. [パッケージ] をクリックし、プロジェクトを保存します。

5. [パッケージ] ウィンドウで、[プロセスが完了したら出力フォルダーを開く] チェック ボックスが選択されていることを確認します。

パッケージ化が完了すると、出力フォルダーが開きます。

アプリケーションのインストール

1. for_redistribution フォルダーを開きます。

2. MyAppInstaller_web を実行します。

3. プロキシ サーバーを使用してインターネットに接続する場合は、サーバーの設定を入力します。

4. インストール ウィザードのページに従って進みます。

  • [インストール オプション] ページで、既定のインストール フォルダーを使用します。

  • [必要なソフトウェア] ページで、既定のインストール フォルダーを使用します。

  • [ライセンス許諾] ページで、ライセンス許諾を読み、ライセンスに同意します。

  • [確認] ページで、[インストール] をクリックします。

MATLAB Runtime がまだインストールされていない場合は、インストーラーがインストールします。

5. [終了] をクリックします。

アプリケーションの実行

1. ターミナル ウィンドウを開きます。

2. アプリケーションがインストールされているフォルダーに移動します。

  • Windows® の場合は、C:\Program Files\myRLSFilterSystemIDApp_acc に移動します。

  • macOS の場合は、/Applications/myRLSFilterSystemIDApp_acc に移動します。

  • Linux の場合は、/usr/myRLSFilterSystemIDApp_acc に移動します。

3. プラットフォームに適したコマンドを使用してアプリケーションを実行します。

  • Windows の場合、application\myRLSFilterSystemIDApp_acc を使用します。

  • macOS の場合、myRLSFilterSystemIDApp_acc.app/Contents/MacOS/myRLSFilterSystemIDApp_acc を使用します。

  • Linux の場合、/myRLSFilterSystemIDApp_acc を使用します。

アプリケーションの起動には、MATLAB の起動とほぼ同じ時間がかかります。

関連するトピック