ドキュメンテーション センター

  • 評価版
  • 製品アップデート

最新のリリースでは、このページがまだ翻訳されていません。 このページの最新版は英語でご覧になれます。

System Object、MATLAB Coder™ および Parallel Computing Toolbox™ を使用したシミュレーションの高速化

この例では、MATLAB の通信アルゴリズムのシミュレーションを高速化する 3 つの方法を示します。具体的には、System object の使用、MATLAB からの C コード生成、および MATLAB 関数 parfor を使用した並列処理実行がシミュレーション速度に与える効果を示します。

これらの方法を組み合わせると、通常のシミュレーション時間を桁違いに短縮できる場合があります。この違いは、シミュレーションを一晩中実行するか、数時間で終わるかの違いになります。

この例で取り上げる System object は、Communications System Toolbox™ 製品で利用できます。この例の MATLAB から C コードを生成するセクションを実行するには、MATLAB Coder™ のライセンスが必要です。この例の並列処理セクションを実行するには、Parallel Computing Toolbox™ のライセンスが必要です。

はじめに

この例では、以下の送受信システムのさまざまな実装を調べます。

このシステムは、送信機、チャネル モデル、および受信機で構成されています。送信機は、入力ビット ストリームをたたみ込みエンコーダー、インターリーバー、変調器、および MIMO 空間時間ブロック エンコーダーで処理します [ 1 ]、[ 2 ]。送信された信号は次に 2x2 MIMO チャネルと加法性ホワイト ガウス ノイズ (AWGN) チャネルによって処理されます。受信機は入力信号を 2x2 MIMO 空間時間ブロック デコーダー、復調器、デインターリーバー、およびビタビ デコーダーで処理し、入力ビット ストリームの最良推定値を受信機で復元します。

例の構造

この例のワークフローは以下のとおりです。

  1. 基本となる関数ベースのアルゴリズムから始める

  2. MATLAB プロファイラー GUI を使用した速度ボトルネックの特定

  3. System object を使用したシミュレーション時間の向上

  4. MATLAB からの C コード生成によるシミュレーションの高速化

  5. 並列処理実行を使用した高速シミュレーションの達成

基本となる関数ベースのアルゴリズムから始める

このアルゴリズムの初版である、基本の実装を表す関数から始めます。関数 commaccelerationbaseline への入力は、現在のフレームの Eb/No 値 (EbNo) とアルゴリズムが処理するビットの数 (MaxNumBits) です。Eb/No は、ビットあたりのエネルギーとノイズ パワー スペクトル密度の比です。関数の出力は、アルゴリズムのビット誤り率 (BER) です。基本アルゴリズムの実装では、localmimoencoder、localmimodecoder、localmimochannel などのユーザー定義の関数と共に、Communication System Toolbox の関数とデータ オブジェクトが使用されます。

type commaccelerationbaseline
function ber = commaccelerationbaseline(EbNo, maxNumBits)
rng('default');
FRM = 2000;                                              % Input Bit Frame
M=4;                                                     % Modulation Order
k=log2(M);                                               % Bits per Symbol
codeRate = 1/2;                                          % Coding Rate
adjSNR = EbNo - 10*log10(1/codeRate) + 10*log10(k);
tblen = 32;
trellis = poly2trellis(7, [171 133]);
LEN=4012;permvec=[1:3:LEN 2:3:LEN 3:3:LEN]';
%% Setup Algorithm Parameters
persistent hMod hDemod
if isempty( hMod)
    hMod   = modem.pskmod  ('M', M, 'SymbolOrder', 'Gray', 'InputType',  'Bit');
    hDemod = modem.pskdemod('M', M, 'SymbolOrder', 'Gray', 'OutputType', 'Bit');
end
%% Run Simulation
totErrs = 0;totBits = 0;
while (totBits <= maxNumBits)                      
    data     = [randn(FRM, 1)>0; false(6,1)];  
    u1       = convenc(data, trellis);                   % Convolutional Encoder
    u2       = intrlv(double(u1),permvec');              % Interleaver
    u3       = modulate(hMod, u2);                       % QPSK Modulator
    u5       = localmimoencoder(2, u3);                  % Alamouti Space-Time Block Encoder
    [u6, u7] = localmimochannel(u5,2);                   % 2x2 MIMO Channel
    u8       = awgn(u6, adjSNR, 'measured', [], 'dB');   % AWGN channel
    u9       = localmimodecoder(u8,u7,2);                % Alamouti Space-Time Block Decoder
    uA       = demodulate(hDemod, u9);                   % QPSK Demodulator
    uB       = deintrlv(uA,permvec');                    % Deinterleaver
    uC       = vitdec(uB(:),trellis, tblen,...           % Viterbi Decoder
                   'term', 'hard'); 
    bitErrs  = biterr(uC(1:FRM), data(1:FRM));
    totErrs  = totErrs + bitErrs;
    totBits  = totBits + FRM;
end
ber = totErrs / totBits;

始点として、MATLAB でこの基本アルゴリズムを実行するのに要する時間を測定します。MATLAB 時間関数 (tic および toc) を使用し、この関数が 0 ~ 7 dB の Eb/No 値で反復する for ループ内で呼び出されたときにこの関数の実行に要した経過時間を記録します。

MaxSNRdB=7;EbNo=1;MaxNumBits=2e5;
N=1;str='Baseline';
commaccelerationbaseline(EbNo,1e4);
berBaseline=zeros(size(0:MaxSNRdB));
fprintf(1,'Processing the baseline algorithm.\n');
tic;
for EbNo=0:MaxSNRdB
    y=commaccelerationbaseline(EbNo,MaxNumBits);
    berBaseline(EbNo+1)=y;
end
a=toc;
Processing the baseline algorithm.

結果は基本アルゴリズムのシミュレーション時間 (秒単位) を示します。この測定値を基準として使用して、アルゴリズムの後続バージョンと比較します。

commaccelerationreportresults(N,a,a,str);
----------------------------------------------------------------------------------------------
Versions of the Transceiver                         | Elapsed Time (sec)| Acceleration Ratio
1. Baseline                                         |           48.1736 |       1.0000
----------------------------------------------------------------------------------------------

MATLAB プロファイラー GUI を使用した速度ボトルネックの特定

MATLAB プロファイラーを使用して、基本アルゴリズムの処理ボトルネックと問題点を特定します。プロファイラー情報は次のスクリプトを実行して取得します。

profile on
y=commaccelerationbaseline(EbNo,1e5);
profile off

プロファイラー レポートプロファイラー レポートには、アルゴリズムの関数呼び出しごとの実行時間が降順で示されます。プロファイラー ウィンドウに表示されている最初のいくつかの関数は、アルゴリズムの速度ボトルネックを表します。この場合、2 つのユーザー定義の関数 (localmimodecoder と localmimochannel) および関数 vitdec (System Toolbox のビタビ デコーダー関数) が主要な速度ボトルネックとして特定されます。

System Object を使用したシミュレーション時間の向上

関数 commaccelerationsystemobjects は、Communications System Toolbox の System object を使用する、第 2 版アルゴリズムを実装します。このアルゴリズムの基本バージョンにある 10 の関数呼び出しのうち 9 つが、使用可能な System object の対応する呼び出しで置き換えられます。その結果、関数 commaccelerationsystemobjects は次の 2 つの異なる部分で構成されます。

  • System object を作成する宣言部分

  • 特定の工程を実行するために System object ごとに step メソッドを呼び出す実行部分

type commaccelerationsystemobjects
function ber = commaccelerationsystemobjects(EbNo, maxNumBits)
%#codegen
coder.extrinsic('rng');
rng('default');
FRM = 2000;                                      % Input Bit Frame
M=4;                                             % Modulation Order
k=log2(M);                                       % Bits per Symbol
codeRate=1/2;                                    % Coding Rate
adjSNR=EbNo-10*log10(1/codeRate)+10*log10(k);
tblen = 32;
trellis = poly2trellis(7, [171 133]);
LEN=4012;permvec=[1:3:LEN 2:3:LEN 3:3:LEN]';
%% Setup Algorithm Parameters
persistent hConvEncoder hViterbi hInterleaver hDeinterleaver
persistent hModulator hDeModulator hOSTBCComb hOSTBCEnc hAWGN
if isempty(hConvEncoder)
    hConvEncoder=comm.ConvolutionalEncoder(trellis,...
        'TerminationMethod','Terminated');    
    hModulator = comm.PSKModulator('ModulationOrder',4, ...
        'SymbolMapping','gray', ...
        'PhaseOffset',0, ...
        'BitInput',true);
    hAWGN=comm.AWGNChannel('NoiseMethod','Variance',...
        'VarianceSource','Input port');
    hDeModulator = comm.PSKDemodulator('ModulationOrder',4, ...
        'SymbolMapping','gray', ...
        'PhaseOffset',0, ...
        'BitOutput',true, ...
        'DecisionMethod','Hard decision');
    hViterbi=comm.ViterbiDecoder(trellis,...
        'InputFormat','Hard',...
        'TracebackDepth',tblen,...
        'OutputDataType', 'logical',...
        'TerminationMethod','Terminated');
    hOSTBCEnc = comm.OSTBCEncoder('NumTransmitAntennas', 2);
    hOSTBCComb = comm.OSTBCCombiner('NumTransmitAntennas',2,'NumReceiveAntennas',2);
    hInterleaver=   comm.BlockInterleaver('PermutationVector',permvec);
    hDeinterleaver= comm.BlockDeinterleaver('PermutationVector',permvec);
end
%% Run Simulation
totErrs = 0; totBits = 0;
while (totBits < maxNumBits)
    data      = randn(FRM, 1)>0;
    u1        = step(hConvEncoder, data);        % Convolutional Encoder
    u2        = step(hInterleaver,u1);           % Interleaver
    u3        = step(hModulator, u2);            % QPSK Modulator
    u5        = step(hOSTBCEnc,u3);              % Alamouti Space-Time Block Encoder
    [u6,~,u7] = localmimochannel(u5,2);          % 2x2 MIMO Channel
    sigDB     = 10*log10(var(u6(:)));          
    noisevar  = real(10.^(0.1*(sigDB-adjSNR)));
    u8        = step(hAWGN,u6,noisevar);         % AWGN channel
    u9        = step(hOSTBCComb,u8,u7);          % Alamouti Space-Time Block Decoder
    uA        = step(hDeModulator, u9);          % QPSK Demodulator
    uB        = step(hDeinterleaver,uA);         % Deinterleaver
    uC        = step(hViterbi,uB);               % Viterbi Decoder
    bitErrs   = sum(abs(uC(1:FRM)-data));
    totErrs   = totErrs + bitErrs;
    totBits   = totBits + FRM;
end
ber = totErrs/totBits;

このバージョンのアルゴリズムのシミュレーション時間を測定します。前と同じ for ループでこの関数の実行に要した経過時間を記録します。

N=2;
str='Using System objects';
commaccelerationsystemobjects(EbNo,1e4);
berSystemobject=zeros(size(berBaseline));
fprintf(1,'Processing the System object version of the algorithm.\n');
tic;
for EbNo=0:MaxSNRdB
    y=commaccelerationsystemobjects(EbNo,MaxNumBits);
    berSystemobject(EbNo+1)=y;
end
b=toc;
Processing the System object version of the algorithm.

結果はアルゴリズムの System object バージョンのシミュレーション時間を示します。関数の呼び出しを System object の呼び出しで置き換えると、アルゴリズムがより高速で実行されることに注目してください。System object を使用する利点の 1 つは効率性であるため、これは予想されていた動作です。System object を使用するアルゴリズムは宣言を実行と区別します。これによって、関数ベースのアルゴリズムに存在する入力検証および確認ルーチンの反復が回避されます。System object を使用するアルゴリズム実装では、パラメーターの処理と初期化が一度だけループの外側で実行され、System object の効果的な MEX 実装が活用されて、シミュレーションの性能を全体的に向上させます。

commaccelerationreportresults(N,a,b,str);
----------------------------------------------------------------------------------------------
Versions of the Transceiver                         | Elapsed Time (sec)| Acceleration Ratio
1. Baseline                                         |           48.1736 |       1.0000
2. Using System objects                             |           12.8705 |       3.7429
----------------------------------------------------------------------------------------------

MATLAB からの C コード生成によるシミュレーションの高速化

MATLAB Coder は、MATLAB コード生成サブセットの一部であるアルゴリズムから、移植と判読が可能な C コードを生成します。第 2 版アルゴリズムの関数 commaccelerationsystemobjects では、MATLAB Coder でコード生成をサポートする System object を使用します。そのため、このアルゴリズムを MEX (MATLAB 実行可能ファイル) 関数として MATLAB にコンパイルすることもリンクすることもできます。MATLAB Coder の codegen コマンドを使用して、アルゴリズムの System object バージョンを MEX 関数 (commaccelerationsystemobjects_mex と呼ばれている) にコンパイルします。

メモ: 例のこのセクションを実行するには、MATLAB Coder ライセンスが必要です。

codegen('commaccelerationsystemobjects.m','-args',{EbNo,MaxNumBits})

MEX バージョンのアルゴリズムのシミュレーション時間を測定します。前と同じ for ループでこの関数の実行に要した経過時間を記録します。

N=3;
str='MATLAB to C code generation';
commaccelerationsystemobjects_mex(EbNo,1e4);
berCodegen=zeros(size(berBaseline));
fprintf(1,'Processing the MEX function of the second version of the algorithm.\n');
tic;
for EbNo=0:MaxSNRdB
    y=commaccelerationsystemobjects_mex(EbNo,MaxNumBits);
    berCodegen(EbNo+1)=y;
end
c=toc;
Processing the MEX function of the second version of the algorithm.

結果はアルゴリズムの MEX バージョンのシミュレーション時間を示します。System object アルゴリズムを MEX 関数にコンパイルすることによって、アルゴリズムの MEX バージョンは、第 2 版アルゴリズムや基本バージョンよりも高速で実行されることに注目してください。MATLAB からの C コード生成を使用する利点の 1 つはシミュレーションの高速化であるため、これは予想されていた動作です。System object を使用するアルゴリズムは高度に最適化されていますが、コード生成は、関数内の変数のサイズとデータ型を整理することによってシミュレーションを高速化できます。この処理によって、コードのすべての行でサイズとデータ型を調べるインタープリター言語のオーバーヘッドが取り除かれるため、実行がより効率的になります。

commaccelerationreportresults(N,a,c,str);
----------------------------------------------------------------------------------------------
Versions of the Transceiver                         | Elapsed Time (sec)| Acceleration Ratio
1. Baseline                                         |           48.1736 |       1.0000
2. Using System objects                             |           12.8705 |       3.7429
3. MATLAB to C code generation                      |            5.2268 |       9.2167
----------------------------------------------------------------------------------------------

並列処理実行を使用した高速シミュレーションの達成

タスクを並列で実行することによって、複数のコアを利用してシミュレーションを高速化します。MATLAB で並列処理実行 (parfor ループ) を使用して、使用可能なワーカー数で作業を実行します。Parallel Computing Toolbox を使用すると、シミュレーションを異なる反復回数で並列化して実行できます。関数 matlabpool を使用し、後続の parfor ループを実行するために複数の MATLAB ワーカーを予約します。この例では、2 つのワーカーが MATLAB クライアント マシンでローカルに実行されます。

メモ: 例のこのセクションを実行するには、Parallel Computing Toolbox のライセンスが必要です。

if matlabpool('size') <= 0, matlabpool open; end

前の例で使用されている for ループではなく、 parfor ループ内で実行される MEX バージョンのアルゴリズムのシミュレーション時間を測定します。

N=4;
str='Parallel simulation runs with parfor';
commaccelerationsystemobjects_mex(EbNo,1e4);
berPct=zeros(size(berBaseline));
fprintf(1,'Processing the MEX function of the second version of the algorithm within a parfor-loop.\n');
tic;
parfor EbNo=0:MaxSNRdB
    y=commaccelerationsystemobjects_mex(EbNo,MaxNumBits);
    berPct(EbNo+1)=y;
end
d=toc;
Processing the MEX function of the second version of the algorithm within a parfor-loop.

結果は parfor ループ内で実行される MEX バージョンの 2 番目のアルゴリズムのシミュレーション時間を示します。parfor ループ内でこのバージョンを実行することによって、シミュレーションの性能が最速になります。parfor ループの基本概念は、標準的な MATLAB の for ループと同じです。違いは、parfor は各ワーカーが全反復回数のうちの一部を実行するように、ループの反復をグループに分ける点です。いくつかの MATLAB ワーカーが同一のループで同時に計算できるため、parfor ループは同様の for ループよりも非常に優れた性能を提供します。

commaccelerationreportresults(N,a,d,str);
----------------------------------------------------------------------------------------------
Versions of the Transceiver                         | Elapsed Time (sec)| Acceleration Ratio
1. Baseline                                         |           48.1736 |       1.0000
2. Using System objects                             |           12.8705 |       3.7429
3. MATLAB to C code generation                      |            5.2268 |       9.2167
4. Parallel simulation runs with parfor             |            2.8600 |      16.8440
----------------------------------------------------------------------------------------------

まとめ

以下の手法を組み合わせることで、

  • System object

  • MATLAB からの C コード生成

  • 並行処理実行

通信アルゴリズムのシミュレーションを大幅に高速化できます。

  • System object は、実行ループの外側でパラメーターの処理と初期化を 1 回だけ実行し、System object の効率的な MEX 実装を利用し、関数ベースのアルゴリズムにある入力検証および確認のルーチンの繰り返しを避けることによって、シミュレーションの速度を向上させます。

  • MATLAB からの C コード生成は、すべての変数のデータ型とサイズを整理し、コードの各行の変数のサイズとデータ型をチェックするインタープリター言語のオーバーヘッドを低減することによって、シミュレーションを高速化します。

  • 並列処理実行は、多くの使用可能な MATLAB ワーカーでアルゴリズムのさまざまな反復を同時に計算することによって、シミュレーションを大幅に高速化できます。

その他の調査

この例では、関数 matlabpool を使用して MATLAB クライアント マシンをローカルに実行する多数の MATLAB ワーカーを予約します。並列化設定を変更し、MATLAB クライアント マシン上には存在しないワーカーの大きなクラスターでアルゴリズムを実行することによって、シミュレーションをさらに高速化できます。並列化設定の管理方法と使用方法の詳細は、『Parallel Computing Toolbox User's Guide』の「Programming with User Configurations」のページを参照してください。

BER の結果

次の図は、入力ビット数が 1000 万に設定された (つまり、MaxNumBits=1e7) 3 つのバージョンのアルゴリズムをそれぞれ実行して得られる BER 曲線を示しています。3 つの実装でアルゴリズムが同一であるため、BER の結果も等しくなります。このプロットは、基準となる低速の関数およびオブジェクトと、高速の System Object の間で動作が維持されていることを示しています。

付録

この例では以下の関数が使用されています。

参考文献

  1. S. M. Alamouti, "A simple transmit diversity technique for wireless communications," IEEE Journal on Selected Areas in Communications, vol. 16, no. 8, pp.1451-1458, Oct. 1998.

  2. V. Tarokh, H. Jafarkhami, and A. R. Calderbank, "Space-time block codes from orthogonal designs," IEEE Transactions on Information Theory, vol. 45, no. 5, pp.1456-1467, Jul. 1999.

この情報は役に立ちましたか?