Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

parfor 内での関数 sim の使用

メモ

関数 simparfor ループ内で使用することは推奨されなくなりました。並列シミュレーションの実行では、parsim を使用してください。並列シミュレーションの実行を参照してください。

parfor 内からの sim の呼び出しの概要

parfor コマンドを使用すると、モデル (設計) の並列 (同時) Simulink® シミュレーションを実行できます。この場合、モデルの並列実行は、異なる複数のワーカーで複数のモデル シミュレーションを同時に実行することを意味します。parfor ループ内から sim を呼び出す方法は、異なる入力または異なるパラメーター設定で同じモデルの複数のシミュレーションを実行する場合に役立ちます。たとえば、パラメーターのスイープやモンテカルロ解析を並列実行して、シミュレーション時間を節減できます。parfor を使用する並列シミュレーションは、モデルを小さい連結部分に分割して、複数のワーカーで個々の部分を同時に実行する機能は現在サポートしていません。

parfor では、ノーマル、アクセラレータ、およびラピッド アクセラレータ シミュレーション モードが sim でサポートされています (シミュレーション モードの選択方法の詳細はシミュレーション モードの選択、シミュレーション実行時間の最適化の詳細は効果的に高速化するためのモデル設計を参照してください)。他のシミュレーション モードの場合、有益な結果を生成するには、ワークスペース アクセスの問題とデータの同時実行の問題に対処しなければなりません。具体的には、シミュレーションでは別の名前の出力ファイルとワークスペース変数を作成する必要があります。そうしないと、シミュレーションを実行するたびに同じワークスペース変数とファイルが上書きされたり、変数とファイルを同時に書き込もうとして競合が発生する可能性があります。

ラピッド アクセラレータ モードにおけるコードの再生成とパラメーター処理の詳細は、ラピッド アクセラレータ モードでのパラメーター調整を参照してください。

parfor (Parallel Computing Toolbox) も参照してください。

メモ

parfor ステートメント内でモデルを開いている場合は、一時ファイルが残らないように bdclose all を使用してモデルを再び閉じてください。

ノーマル モードでの parfor の sim

このコードのフラグメントは、ノーマル モードでの simparfor の使用方法を示しています。parfor でシミュレーションを実行する前に、モデルの変更を保存します。保存されたモデルのコピーは、parfor でのシミュレーション時に並列ワーカーに配布されます。

% 1) Load model and initialize the pool.
model = 'sldemo_suspn_3dof';
load_system(model);
parpool;

% 2) Set up the iterations that we want to compute.
Cf                  = evalin('base', 'Cf');
Cf_sweep            = Cf*(0.05:0.1:0.95);
iterations          = length(Cf_sweep);
simout(iterations)  = Simulink.SimulationOutput;

% 3) Need to switch all workers to a separate tempdir in case 
% any code is generated for instance for StateFlow, or any other 
% file artifacts are  created by the model.
spmd
    % Setup tempdir and cd into it
    currDir = pwd;
    addpath(currDir);
    tmpDir = tempname;
    mkdir(tmpDir);
    cd(tmpDir);
    % Load the model on the worker
    load_system(model);
end

% 4) Loop over the number of iterations and perform the
% computation for different parameter values.
parfor idx=1:iterations   
    set_param([model '/Road-Suspension Interaction'],'MaskValues',...
        {'Kf',num2str(Cf_sweep(idx)),'Kr','Cr'});
    simout(idx) = sim(model, 'SimulationMode', 'normal');
end

% 5) Switch all of the workers back to their original folder.
spmd
    cd(currDir);
    rmdir(tmpDir,'s');
    rmpath(currDir);
    close_system(model, 0);
end

close_system(model, 0);
delete(gcp('nocreate'));

ノーマル モードおよび MATLAB Parallel Server ソフトウェアでの parfor の sim

このコード フラグメントは、ノーマル モードでの parfor の simのコードと同じです。

.ノーマル モードで simparfor を使用するために、以下のように変更します。

  • 項目 1 で、以下のように parpool コマンドを変更してオブジェクトを作成し、クラスター名を呼び出すために使用します。

    p = parpool('clusterProfile');
    % 'clusterProfile' is the name of the distributed cluster

  • 項目 1 で、モデルが依存するファイルを検索し、リモート マシンでクラスター ワーカーに配布するためにそれらのファイルをモデルに添付します。

    files = dependencies.fileDependencyAnalysis(modelName);
    p.addAttachedFiles(files);

  • MATLAB® Parallel Server™ クラスターがない場合は、ローカル クラスターを使用します。詳細については、クラスターの検出とクラスター プロファイルの使用 (Parallel Computing Toolbox)を参照してください。

コードを実行する前にクラスターを開始します。

% 1) Load model and initialize the pool.
model = 'sldemo_suspn_3dof';
load_system(model);
parpool;

% 2) Set up the iterations that we want to compute.
Cf                  = evalin('base', 'Cf');
Cf_sweep            = Cf*(0.05:0.1:0.95);
iterations          = length(Cf_sweep);
simout(iterations)  = Simulink.SimulationOutput;

% 3) Need to switch all workers to a separate tempdir in case 
% any code is generated for instance for StateFlow, or any other 
% file artifacts are  created by the model.
spmd
    % Setup tempdir and cd into it
    addpath(pwd);
    currDir = pwd;
    addpath(currDir);
    tmpDir = tempname;
    mkdir(tmpDir);
    cd(tmpDir);
    % Load the model on the worker
    load_system(model);
end

% 4) Loop over the number of iterations and perform the
% computation for different parameter values.
parfor idx=1:iterations   
    set_param([model '/Road-Suspension Interaction'],'MaskValues',...
        {'Kf',num2str(Cf_sweep(idx)),'Kr','Cr'});
    simout(idx) = sim(model, 'SimulationMode', 'normal');
end

% 5) Switch all of the workers back to their original folder.
spmd
    cd(currDir);
    rmdir(tmpDir,'s');
    rmpath(currDir);
    close_system(model, 0);
end

close_system(model, 0);
delete(gcp('nocreate'));

ラピッド アクセラレータ モードでの parfor の sim

ラピッド アクセラレータ シミュレーションを parfor で実行すると、ビルド前の実行可能ファイルの parforワーカーへの自動配布にスピードが加わります。その結果、このモードでは、ブロック線図の更新フェーズの重複がなくなります。

sim および parfor コマンドを使用してラピッド アクセラレータ モードで並列シミュレーションを実行するには、以下のことを行う必要があります。

  • モデルがラピッド アクセラレータ モードで実行するように構成します。

  • parfor でシミュレーションを実行する前に、モデルの変更を保存します。保存されたモデルのコピーは、parfor でのシミュレーション時に並列ワーカーに配布されます。

  • ラピッ ド アクセラレータ ターゲットが既にビルドされ、最新であることを確認します。

  • sim コマンド オプション RapidAcceleratorUpToDateCheck'off' に設定して、ラピッド アクセラレータ ターゲットの最新チェックを無効にします。

2 番目の条件を満たすには、モデルのリビルドを必要としないシミュレーション間でのみパラメーターを変更できます。つまり、モデルの構造的なチェックサムは不変でなければなりません。したがって、調整可能なブロック線図パラメーターと、シミュレーション間の調整可能な実行時ブロック パラメーターのみ変更可能です。変更後にリビルドを必要としない調整可能なパラメーターについては、シミュレーションをリビルドするかどうかの指定を参照してください。

ラピッド アクセラレータ ターゲットの最新チェックを無効にするには、このサンプルで示すように sim コマンドを使用します。

parpool;
% Load the model and set parameters
model = 'vdp';
load_system(model);
% Build the Rapid Accelerator target
rtp = Simulink.BlockDiagram.buildRapidAcceleratorTarget(model);
% Run parallel simulations
parfor i=1:4
   simOut{i} = sim(model,'SimulationMode', 'rapid',...
               'RapidAcceleratorUpToDateCheck', 'off',...
               'SaveTime', 'on',...
               'StopTime', num2str(10*i));
   close_system(model, 0);
end

close_system(model, 0);
delete(gcp('nocreate'));

この例では、関数 buildRapidAcceleratorTarget の呼び出しによってコードが一度生成されます。以降は、RapidAcceleratorUpToDateCheck オプションを off にして sim を呼び出すと、そのコードは再生成されません。こうしてデータの同時実行の問題が解消します。

RapidAcceleratorUpToDateCheck'off' に設定した場合は、モデルのブロック パラメーター値に対して (ブロックのダイアログ ボックスの使用、関数 set_param の使用、または MATLAB 変数の値の変更などによって) 加えた変更はシミュレーションに影響を及ぼしません。代わりに、RapidAcceleratorParameterSets を使用して新しいパラメーター値をシミュレーションに直接渡します。

ワークスペースのアクセスの問題

MATLAB ワーカー セッションのワークスペース アクセス-  既定の設定では、parforsim を実行するために並列プールが自動的に開き、コードを並列実行できます。あるいは、最初に parpool コマンドを使用して MATLAB ワーカーを開くこともできます。次に、これらの MATLAB ワーカー セッションの parfor ループ内で parfor コマンドがコードを実行します。ただし、MATLAB ワーカーは、モデルとその関連ワークスペース変数が読み込まれた MATLAB クライアント セッションのワークスペースへのアクセス権がありません。したがって、モデルを読み込んで、その関連ワークスペース変数を parfor ループの外側と前で定義した場合は、モデルが読み込まれず、 parfor 反復が実行される MATLAB ワーカー セッションでワークスペース変数も定義されません。これは通常、モデルのパラメーターまたは外部入力をクライアント セッションのベース ワークスペースで定義する場合です。これらのシナリオからワークスペースのアクセスの問題が生じます。

透明性の違反-  srcWorkspacecurrent に設定して parfor 内で sim を実行した場合、Simulink は透明なワークスペースである parfor ワークスペースを使用します。Simulink はその後透明性違反のエラーを表示します。透明なワークスペースの詳細については、parfor ループまたは spmd ステートメント内での透過性の確保 (Parallel Computing Toolbox)を参照してください。

データ ディクショナリのアクセス-  モデルがデータ ディクショナリにリンクされている場合 (データ ディクショナリとはを参照)、ディクショナリ内に保存した変数やオブジェクトにアクセスするコードを parfor に記述するには、関数 Simulink.data.dictionary.setupWorkerCacheSimulink.data.dictionary.cleanupWorkerCache を使用してアクセスの問題を回避しなければなりません。例については、並列シミュレーションを使用したバリアント制御のスイープを参照してください。

ワークスペースのアクセス問題の解決

Simulink モデルが MATLAB クライアント セッションのメモリに読み込まれると、その MATLAB セッションでのみ表示とアクセスが可能です。MATLAB ワーカー セッションのメモリではアクセスできません。同様に、MATLAB クライアント セッションで定義されるモデル (パラメーターや外部入力) に関連付けられているワークスペース変数は、ワーカー セッションで自動的に使用可能になることはありません。そのため、次の 2 つの方法を使用して、モデルが読み込まれ、モデルで参照されているワークスペース変数が MATLAB ワーカー セッションで定義されるようにしなければなりません。

  • parfor ループで、sim コマンドを使用してモデルを読み込み、反復ごとに変わるパラメーターを設定します (もう一つの方法: モデルを読み込んでから g(s)et_param コマンドを使用して parfor ループでパラメーターを設定します)。

  • parfor ループで、MATLAB evalin コマンドと assignin コマンドを使用してデータ値を変数に割り当てます。

または、ワークスペース変数をモデル ワークスペースで定義すると、管理しやすくなります。これらの変数は、モデルがワーカー セッションに読み込まれるときに自動的に読み込まれます。ただし、この方法には制限があります。たとえば、Auto 以外のストレージ クラスを使用する信号オブジェクトをモデル ワークスペースで保存することはできません。モデル ワークスペースの詳細は、モデル ワークスペースを参照してください。

sim コマンドを使用したパラメーター値の指定-  反復のたびに変わるパラメーターを設定するには、parfor ループで sim コマンドを使用します。

%Specifying Parameter Values Using the sim Command
    
model = 'vdp';
load_system(model)
    
%Specifying parameter values. 
paramName = 'StopTime';
paramValue = {'10', '20', '30', '40'};
    
% Run parallel simulations
parfor i=1:4
    simOut{i} = sim(model, ...
                    paramName, paramValue{i}, ...
                    'SaveTime', 'on'); %#ok
end
    
close_system(model, 0);

または、モデルを読み込んでから set_param コマンドを使用して parfor ループで paramName を設定する方法もあります。

assignin コマンドを使用した変数値の指定-  assignin または evalin コマンドを使用して、モデルまたはシミュレーションの変数の値を MATLAB ワーカーに渡すことができます。次の例は、この方法を使用して変数値を MATLAB ワーカーの該当するワークスペースに読み込む方法を示しています。

parfor i = 1:4
    assignin('base', 'extInp', paramValue{i})%#ok
    % 'extInp' is the name of the variable in the base 
    % workspace which contains the External Input data
    simOut{i} = sim(model, 'ExternalInput', 'extInp'); %#ok
end

並列シミュレーションを使用したバリアント制御のスイープ-  並列シミュレーションを使用してデータ ディクショナリに保存したバリアント制御 (値が Simulink.Variant オブジェクトのバリアント条件に影響を与える Simulink.Parameter オブジェクト) をスイープするには、このコードをテンプレートとして使用します。モデル、データ ディクショナリおよびバリアント制御の名前と値をアプリケーションに一致するように変更します。

ブロック パラメーターの値、あるいはブロック パラメーターを設定するために使用するワークスペース変数の値をスイープするには、データ ディクショナリへのプログラム インターフェイスの代わりに Simulink.SimulationInput オブジェクトを使用します。ブロック パラメーター値の最適化、推定およびスイープを参照してください。

並列シミュレーションを実行するには、Parallel Computing Toolbox™ ライセンスがなければなりません。

% For convenience, define names of model and data dictionary
model = 'mySweepMdl';
dd = 'mySweepDD.sldd';

% Define the sweeping values for the variant control
CtrlValues = [1 2 3 4];

% Grant each worker in the parallel pool an independent data dictionary 
% so they can use the data without interference
spmd 
    Simulink.data.dictionary.setupWorkerCache
end

% Determine the number of times to simulate
numberOfSims = length(CtrlValues);

% Prepare a nondistributed array to contain simulation output
simOut = cell(1,numberOfSims);

parfor index = 1:numberOfSims
    % Create objects to interact with dictionary data
    % You must create these objects for every iteration of the parfor-loop
    dictObj = Simulink.data.dictionary.open(dd);
    sectObj = getSection(dictObj,'Design Data');
    entryObj = getEntry(sectObj,'MODE'); 
    % Suppose MODE is a Simulink.Parameter object stored in the data dictionary
    
    % Modify the value of MODE
    temp = getValue(entryObj);
    temp.Value = CtrlValues(index);
    setValue(entryObj,temp);

    % Simulate and store simulation output in the nondistributed array
    simOut{index} = sim(model);
    
    % Each worker must discard all changes to the data dictionary and
    % close the dictionary when finished with an iteration of the parfor-loop
    discardChanges(dictObj);
    close(dictObj);
end

% Restore default settings that were changed by the function
% Simulink.data.dictionary.setupWorkerCache
% Prior to calling cleanupWorkerCache, close the model

spmd
    bdclose(model)
    Simulink.data.dictionary.cleanupWorkerCache
end

メモ

データ ディクショナリが開いている場合は、コマンド Simulink.data.dictionary.cleanupWorkerCache を使用できません。開いているデータ ディクショナリを特定するには、Simulink.data.dictionary.getOpenDictionaryPaths を使用します。

データの同時実行の問題

データの同時実行の問題は、ソフトウェアがデータの入出力のために同じファイルに同時にアクセスしようとするシナリオに関するものです。Simulink では、この問題は主に、Simulink モデルの同時実行中に parfor ループが不連続であった結果として発生します。最も一般的な事例は、並列計算中に Stateflow®Model ブロックまたは MATLAB Function ブロックのシミュレーション ターゲットのコードが生成または更新されるときに発生します。この場合、原因は Simulink が複数のワーカー セッションのターゲット データに同時にアクセスしようとすることです。同様に、To File ブロックも並列シミュレーション中に同じファイルに同時にデータのログを作成しようとして I/O エラーを引き起こす場合があります。または、サードパーティのブロックセットまたはユーザー作成の S-Function がコードやファイルを同時生成中に、データの同時実行の問題を引き起こす可能性があります。

データの同時実行の副次的な原因は、ネットワーク ポートの保護されていないアクセスです。この種のエラーは、たとえば、シミュレーション中に TCP/IP を使用して他のアプリケーションと通信するブロックを Simulink 製品が提供している場合に発生します。そのような製品の 1 つが、Mentor Graphics® ModelSim® HDL シミュレーターと一緒に使用する HDL Verifier™ です。

データの同時実行の問題の解決

parfor の主要件は、parfor 本体の異なる反復の独立性です。この制約は、現在のシミュレーションに以前のシミュレーションのシミュレーション ターゲットが再利用または更新されるインクリメンタル コード生成を使用したシミュレーションの主要件に合いません。したがって、コードの生成を伴うモデルの並列シミュレーション (アクセラレータ モードのシミュレーションなど) 中に、Simulink はシミュレーション ターゲットに対して同時実行アクセス (更新) を試みます。ただし、このようなデータの同時実行の問題は、一時フォルダーを parfor ループ内に作成し、複数行の MATLAB コードをループに追加して次の手順を実行することで避けることができます。

  1. 現在のフォルダーを書き込み可能な一時フォルダーに変更します。

  2. 一時フォルダーで、モデルを読み込み、パラメーターと入力ベクトルを設定して、モデルのシミュレーションを実行します。

  3. 最初の現在のフォルダーに戻ります。

  4. 一時フォルダーと一時パスを削除します。

このようにして個別の一時フォルダーにモデルを読み込んでシミュレートすることで、同時実行の問題を避けます。以下は、この方法で一般的な同時実行の問題を解決する例です。

StateflowMATLAB Function ブロック、または Model ブロックのあるモデル-  この例では、モデルがアクセラレータ モードでシミュレーションを実行するように構成されているか、Stateflow、MATLAB Function ブロックまたは Model ブロック (たとえば、sf_bouncesldemo_autotrans または sldemo_mdlref_basic) が含まれています。このような場合、Simulink はシミュレーションの初期化の段階でコードを生成します。このようなモデルを parfor でシミュレーションを実行すると、同じファイルにコードが生成されますが、初期化の段階ではワーカー セッションで実行します。下の図のように、そのようなデータの同時実行の問題は、parfor 本体の各反復を異なる一時フォルダーで実行すると回避できます。

parfor i=1:4
   cwd = pwd;
   addpath(cwd)
   tmpdir = tempname;
   mkdir(tmpdir)
   cd(tmpdir)
   load_system(model)
   % set the block parameters, e.g., filename of To File block
   set_param(someBlkInMdl, blkParamName, blkParamValue{i})
   % set the model parameters by passing them to the sim command
   out{i} = sim(model, mdlParamName, mdlParamValue{i});
   close_system(model,0);
   cd(cwd)
   rmdir(tmpdir,'s')
   rmpath(cwd)
end

次の点に注意してください。

  • また、ファイルの I/O エラーによる他の同時実行の問題も、parfor 本体の各反復に一時フォルダーを使用すると回避できます。

  • Windows® プラットフォームで、rmdir(tmpdir, 's') の前の evalin('base', 'clear mex'); コマンドの挿入について考えます。このシーケンスは、tmpdir を削除するために rmdir を呼び出す前に MEX ファイルをまず閉じます。

evalin('base', 'clear mex');
rmdir(tmpdir, 's')

To File ブロックのあるモデル-   To File ブロックのあるモデルのシミュレーションを parfor ループ内から実行すると、ループの不連続性によってファイルの I/O エラーが発生する可能性があります。並列シミュレーション中のこのようなエラーを防ぐには、上記の一時フォルダーを使用するか、ラピッド アクセラレータ モードで sim コマンドを使用して、ファイル名にサフィックスを付加するオプションをモデルの To File ブロックで指定します。parfor 本体の反復ごとに一意の接尾辞を与えると、同時実行の問題を回避できます。

rtp = Simulink.BlockDiagram.buildRapidAcceleratorTarget(model); 
       parfor idx=1:4 
       sim(model, ... 
           'ConcurrencyResolvingToFileSuffix', num2str(idx),... 
           'SimulationMode', 'rapid',... 
           'RapidAcceleratorUpToDateCheck', 'off'); 
        end

関連するトピック