parfor
内での関数 sim
の使用
メモ
parfor
ループ内で sim
関数を呼び出して並列シミュレーションを実行することは推奨されません。並列シミュレーションを実行するには、parsim
関数を使用してください。詳細については、並列シミュレーションの実行を参照してください。
parfor
コマンドを使用すると、モデルの同時並列シミュレーションを実行できます。このコンテキストでは、並列とは、同じモデルの複数のシミュレーションが同時に実行され、各同時シミュレーションが異なるワーカーで実行されることを意味します。シミュレーションを並列に実行することは、多くの場合、異なる入力または異なるパラメーター設定で同じモデルの複数のシミュレーションを実行する場合に役立ちます。たとえば、パラメーターのスイープやモンテカルロ解析を実行するとき、シミュレーションを並列に実行することで、シミュレーション時間を節減できます。parfor
を使用して並列シミュレーションを実行する場合、モデルを小さい連結部分に分割して、異なるワーカーで同じシミュレーションの個々の部分を実行することはサポートされていません。
parfor
内の sim
では、ノーマル、アクセラレータ、およびラピッド アクセラレータの各シミュレーション モードがサポートされています。他のシミュレーション モードの場合、有益な結果を生成するには、ワークスペース アクセスの問題とデータの同時実行の問題に対処しなければなりません。具体的には、シミュレーションでは別の名前の出力ファイルとワークスペース変数を作成する必要があります。そうしないと、シミュレーションを実行するたびに同じワークスペース変数とファイルが上書きされたり、変数とファイルを同時に書き込もうとして競合が発生する可能性があります。
アクセラレータ モードおよびラピッド アクセラレータ モードでのシミュレーションの実行について詳しくは、以下を参照してください。
parfor
(Parallel Computing Toolbox) も参照してください。
メモ
parfor
ステートメント内でモデルを開く場合、一時ファイルが残らないようにコマンド bdclose all
を使用してモデルを再び閉じてください。
parfor
内の sim
によるノーマル モードのシミュレーション
このコード フラグメントは、ノーマル モードでの sim
と parfor
の使用方法を示しています。parfor
でシミュレーションを実行する前に、モデルの変更を保存します。保存されたモデルのコピーは、parfor
でのシミュレーション時に並列ワーカーに配布されます。
% 1) Load model and initialize the pool. openExample('sldemo_suspn_3dof'); mdl = 'sldemo_suspn_3dof'; load_system(mdl); 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 % Set up tempdir and cd into it currDir = pwd; addpath(currDir); tmpDir = tempname; mkdir(tmpDir); cd(tmpDir); % Load the model on the worker load_system(mdl) end % 4) Loop over the number of iterations and perform the % computation for different parameter values. parfor idx=1:iterations set_param([mdl '/Road-Suspension Interaction'],'MaskValues',... {'Kf',num2str(Cf_sweep(idx)),'Kr','Cr'}); simout(idx) = sim(mdl,'SimulationMode','normal'); end % 5) Switch all of the workers back to their original folder. spmd cd(currDir); rmdir(tmpDir,'s'); rmpath(currDir); close_system(mdl,0); end close_system(mdl,0); delete(gcp('nocreate'));
parfor
内の sim
と MATLAB Parallel Server によるノーマル モードのシミュレーション
parfor
内の sim
と MATLAB® Parallel Server™ を使用してノーマル モードのシミュレーションを実行するには、parfor 内の sim によるノーマル モードのシミュレーションのコードに次の変更を加えます。
parpool
コマンドを変更して並列プールに名前を付け、プールを参照するために使用できるオブジェクトを作成します。p = parpool('clusterProfile');
並列プールを作成した後、モデルの実行に必要なファイルをプールに添付して、ワーカーに配布します。
files = dependencies.fileDependencyAnalysis(mdl); p.addAttachedFiles(files);
MATLAB Parallel Server クラスターがない場合は、ローカル クラスターを使用します。詳細については、クラスターの検出とクラスター プロファイルの使用 (Parallel Computing Toolbox)を参照してください。
コードを実行する前にクラスターを開始します。
% 1) Load model and initialize the pool. openExample('sldemo_suspn_3dof'); mdl = 'sldemo_suspn_3dof'; load_system(mdl); 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 % Set up 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([mdl '/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(mdl,0); delete(gcp('nocreate'));
parfor
内での sim
によるラピッド アクセラレータ シミュレーション
parfor
ループ内でラピッド アクセラレータ シミュレーションを実行すると、ビルド前の実行可能ファイルの並列ワーカーへの自動配布にスピードが加わります。その結果、このモードでは、ブロック線図の更新フェーズの重複がなくなります。
parfor
ループ内で sim
関数を使用して並列ラピッド アクセラレータ シミュレーションを実行するには、次のようにします。
モデルのシミュレーション モードをラピッド アクセラレータに設定します。
parfor
でシミュレーションを実行する前に、モデルの変更を保存します。保存されたモデルのコピーは、parfor
でのシミュレーション時に並列ワーカーに配布されます。ラピッ ド アクセラレータ ターゲットが既にビルドされ、最新であることを確認します。
sim
の呼び出しで名前と値の引数RapidAcceleratorUpToDateCheck
を'off'
として指定して、ラピッド アクセラレータ ターゲットの最新チェックを無効にします。
2 番目の条件を満たすには、モデルのリビルドを必要としないシミュレーション間でのみパラメーターを変更できます。つまり、パラメーター値を変更するには、モデルの構造的チェックサムは不変でなければなりません。したがって、調整可能なブロック線図パラメーターと、シミュレーション間の調整可能な実行時ブロック パラメーターのみ変更可能です。変更後にリビルドを必要としない調整可能なパラメーターについては、リビルドが必要な変更かどうかの判別を参照してください。
ラピッド アクセラレータ ターゲットの最新チェックを無効にするには、このコードで示すように sim
関数を使用します。
parpool; % Load the model and set parameters mdl = 'vdp'; load_system(mdl); % Build the rapid accelerator target rtp = Simulink.BlockDiagram.buildRapidAcceleratorTarget(mdl); % Run parallel simulations parfor i=1:4 simOut{i} = sim(mdl,'SimulationMode','rapid',... 'RapidAcceleratorUpToDateCheck','off',... 'SaveTime','on',... 'StopTime',num2str(10*i)); close_system(mdl,0); delete(gcp('nocreate'));
この例では、buildRapidAcceleratorTarget
関数の呼び出しによってラピッド アクセラレータ ターゲットが一度生成されます。その後、RapidAcceleratorUpToDateCheck
オプションを off
にして sim
を呼び出すと、ラピッド アクセラレータ ターゲットは再生成されず、データの同時実行の問題が解決されます。
ラピッド アクセラレータの最新チェックを無効にすると、[ブロック パラメーター] ダイアログ ボックスの使用、set_param
関数の使用、または MATLAB 変数の値の変更などによってモデルのブロック パラメーター値に加えた変更はシミュレーションに影響を及ぼしません。新しいパラメーター値をシミュレーションに渡すには、名前と値の引数 RapidAcceleratorParameterSets
を使用します。
ワークスペースのアクセスの問題
MATLAB ワーカーのワークスペース アクセス
既定では、parfor
内で sim
を呼び出すと、並列プールが自動的に開き、シミュレーションを並列で実行できます。あるいは、parpool
関数を使用して最初に MATLAB ワーカーを開くこともできます。次に、parfor
関数は、これらの MATLAB ワーカー セッションで parfor
ループ内のコードを実行します。ただし、MATLAB ワーカーは、モデルとその関連ワークスペース変数が読み込まれた MATLAB クライアント セッションのワークスペースへのアクセス権がありません。したがって、モデルを読み込んで、その関連ワークスペース変数を parfor
ループの外側と前で定義した場合は、モデルが読み込まれず、 parfor
反復が実行される MATLAB ワーカー セッションでワークスペース変数も定義されません。これは通常、モデルのパラメーターまたは外部入力をクライアント セッションのベース ワークスペースで定義する場合です。これらのシナリオからワークスペースのアクセスの問題が生じます。
透過性の違反
srcWorkspace
を current
に設定して parfor
内で sim
を呼び出すと、シミュレーションでは透過的なワークスペースである parfor
ワークスペースが使用されます。このソフトウェアは、透過性の違反に対してエラーを発行します。透過的なワークスペースの詳細については、parfor ループまたは spmd ステートメント内での透過性の確保 (Parallel Computing Toolbox)を参照してください。
データ ディクショナリのアクセス
モデルがデータ ディクショナリにリンクされている場合、ディクショナリ内に保存した変数やオブジェクトにアクセスするコードを parfor
で記述するには、アクセスの問題を回避するために、関数 Simulink.data.dictionary.setupWorkerCache
と Simulink.data.dictionary.cleanupWorkerCache
を使用する必要があります。例については、並列シミュレーションを使用したバリアント制御のスイープを参照してください。詳細については、データ ディクショナリとはを参照してください。
ワークスペースのアクセス問題の解決
モデルが MATLAB クライアント セッションでメモリに読み込まれると、そのモデルはその MATLAB セッションでのみ表示およびアクセス可能となり、ワーカーの MATLAB セッションのメモリではアクセスできなくなります。同様に、MATLAB クライアント セッションで定義されるモデル (パラメーターや外部入力) に関連付けられているワークスペース変数は、ワーカー セッションで自動的に使用可能になることはありません。次のオプションを使用して、モデルが読み込まれ、モデルで参照されているワークスペース変数が各ワーカーの MATLAB セッションで定義されるようにしなければなりません。
parfor
ループで、関数sim
を使用してモデルを読み込み、反復ごとに変わるパラメーターを設定します。あるいは、モデルを読み込んでから、get_param
関数およびset_param
関数を使用してparfor
ループ内でパラメーターを取得および設定します。parfor
ループで、MATLAB 関数evalin
とassignin
を使用して変数に値を代入します。
または、ワークスペース変数をモデル ワークスペースで定義すると、管理しやすくなります。これらの変数は、モデルがワーカー セッションに読み込まれると使用できるようになります。モデル ワークスペースの使用には制限があります。たとえば、Auto
以外のストレージ クラスを使用する Simulink.Signal
オブジェクトをモデル ワークスペースに保存することはできません。モデル ワークスペースの詳細は、モデル ワークスペースを参照してください。
sim
関数の引数としてのパラメーター値の指定
反復のたびに変わるパラメーターを設定するには、parfor
ループで関数 sim
を使用します。
mdl = 'vdp'; load_system(mdl) %Specify parameter values. paramName = 'StopTime'; paramValue = {'10' '20' '30' '40'}; % Run parallel simulations parfor i=1:4 simOut{i} = sim(mdl,... paramName,paramValue{i},... 'SaveTime','on'); end close_system(mdl,0);
または、モデルを読み込んでから set_param
関数を使用して parfor
ループで paramName
を設定する方法もあります。
assignin
を使用して変数値を指定
assignin
または evalin
関数を使用して、モデルまたはシミュレーションの変数の値を MATLAB ワーカーに渡すことができます。次のコードは、この手法を使用して変数値を MATLAB ワーカーの該当するワークスペースに読み込む方法を示しています。
parfor i = 1:4 assignin('base','extInp',paramValue{i}); simOut{i} = sim(model,'ExternalInput','extInp'); end
並列シミュレーションを使用したバリアント制御のスイープ
並列シミュレーションを使用してデータ ディクショナリに保存したバリアント制御 (値が Simulink.VariantExpression
オブジェクトのバリアント条件に影響を与える 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® では、この問題は主に、同じモデルの同時シミュレーション中に parfor
ループが不連続であった結果として発生します。最も一般的な事例は、並列計算中に Stateflow® チャート、参照モデル、または MATLAB Function ブロックのシミュレーション ターゲットのコードが生成または更新されるときに発生します。この場合、原因は、ソフトウェアが複数のワーカー セッションのターゲット データに同時にアクセスしようとすることです。同様に、To File ブロックも並列シミュレーション中に同じファイルにデータを記録しようとしてエラーを引き起こすことがあります。サードパーティのブロックセットまたはカスタムの S-Function が、コードやファイルの同時生成中に、データの同時実行の問題を引き起こす可能性があります。
データの同時実行の副次的な原因は、ネットワーク ポートの保護されていないアクセスです。この種のエラーは、たとえば、シミュレーション中にブロックが TCP/IP を使用して他のアプリケーションと通信する場合に発生します。そのような例の 1 つが、Siemens® ModelSim™ HDL シミュレーターで使用する HDL Verifier™ です。
データの同時実行の問題の解決
parfor
の主要件は、parfor
本体の異なる反復の独立性です。この制約は、現在のシミュレーションに以前のシミュレーションのシミュレーション ターゲットが再利用または更新されるインクリメンタル コード生成を使用したシミュレーションの主要件に合いません。シミュレーション ターゲットの生成を伴うモデルの並列シミュレーション (アクセラレータ モードのシミュレーションなど) 中に、シミュレーション ターゲットに対する同時実行アクセス (更新) が試行されます。ただし、このようなデータの同時実行の問題は、一時フォルダーを parfor
ループ内に作成し、複数行の MATLAB コードをループに追加して次の手順を実行することで避けることができます。
現在のフォルダーを書き込み可能な一時フォルダーに変更します。
一時フォルダーで、モデルを読み込み、パラメーターと入力ベクトルを設定して、モデルのシミュレーションを実行します。
最初の現在のフォルダーに戻ります。
一時フォルダーと一時パスを削除します。
このようにして個別の一時フォルダーにモデルを読み込んでシミュレートすることで、同時実行の問題を避けます。以下は、この方法で一般的な同時実行の問題を解決する例です。
Stateflow チャート、MATLAB Function ブロック、またはモデル参照を含むモデル
この例では、モデルがアクセラレータ モードでシミュレーションを実行するように構成されているか、1 つ以上の Stateflow チャート、MATLAB Function ブロック、またはモデル参照が含まれています。このようなモデルの例には、sf_bounce
や sldemo_autotrans
などがあります。このような場合、ソフトウェアはシミュレーションの初期化フェーズ中にシミュレーション ターゲットを生成します。このようなモデルを parfor
ループでシミュレーションすると、ワーカー セッションで初期化フェーズが実行されている間に、各シミュレーションで同じファイルを使用して同時にシミュレーション ターゲットが生成されます。次のコードに示されているように、parfor
本体の各反復を異なる一時フォルダーで実行することで、このようなデータの同時実行の問題を回避できます。
parfor i=1:4 cwd = pwd; addpath(cwd) tmpdir = tempname; mkdir(tmpdir) cd(tmpdir) load_system(mdl) % set the block parameters, such as filename for To File block set_param(someBlkInMdl,blkParamName,blkParamValue{i}) % set the model parameters by passing them to the sim function out{i} = sim(mdl,mdlParamName,mdlParamValue{i}); close_system(mdl,0); cd(cwd) rmdir(tmpdir,'s') rmpath(cwd) end
また、ファイルの I/O エラーによる他の同時実行の問題も、parfor
本体の各反復に一時フォルダーを使用すると回避できます。
Windows® プラットフォームでは、コマンド rmdir(tmpdir, 's')
の前にコマンド evalin('base','clear mex');
を挿入することを検討してください。この順序では、まず MEX ファイルを閉じてから、rmdir
を呼び出して一時ディレクトリ tmpdir
を削除します。
evalin('base','clear mex'); rmdir(tmpdir,'s')
To File ブロックを含むモデル
parfor
ループ内に 1 つ以上の To File ブロックを含むモデルをシミュレーションすると、ループの不連続性によってファイル I/O エラーが発生する可能性があります。並列シミュレーション中のこのようなエラーを回避するには、一時フォルダーの解決策を使用するか、To File ブロック パラメーターで指定されたファイル名に接尾辞を追加するオプションを使用して、シミュレーションをラピッド アクセラレータ モードで実行します。parfor
本体の反復ごとに一意の接尾辞を与えると、同時実行の問題を回避できます。
rtp = Simulink.BlockDiagram.buildRapidAcceleratorTarget(mdl); parfor idx=1:4 sim(mdl,... 'ConcurrencyResolvingToFileSuffix',num2str(idx),... 'SimulationMode','rapid',... 'RapidAcceleratorUpToDateCheck','off'); end