このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。
parfor 内での関数 sim の使用
メモ
関数 sim
を parfor
ループ内で使用することは推奨されなくなりました。並列シミュレーションの実行では、parsim
を使用してください。並列シミュレーションの実行を参照してください。
parfor 内からの sim の呼び出しの概要
parfor
コマンドを使用すると、モデル (設計) の並列 (同時) Simulink® シミュレーションを実行できます。この場合、モデルの並列実行は、異なる複数のワーカーで複数のモデル シミュレーションを同時に実行することを意味します。parfor
ループ内から sim
を呼び出す方法は、異なる入力または異なるパラメーター設定で同じモデルの複数のシミュレーションを実行する場合に役立ちます。たとえば、パラメーターのスイープやモンテカルロ解析を並列実行して、シミュレーション時間を節減できます。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'); 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のコードと同じです。
ノーマル モードで sim
と parfor
を使用するために、以下のように変更します。
項目 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. openExample('sldemo_suspn_3dof'); 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 ワーカー セッションのワークスペース アクセス. 既定の設定では、parfor
で sim
を実行するために並列プールが自動的に開き、コードを並列実行できます。あるいは、最初に parpool
コマンドを使用して MATLAB ワーカーを開くこともできます。次に、これらの MATLAB ワーカー セッションの parfor
ループ内で parfor
コマンドがコードを実行します。ただし、MATLAB ワーカーは、モデルとその関連ワークスペース変数が読み込まれた MATLAB クライアント セッションのワークスペースへのアクセス権がありません。したがって、モデルを読み込んで、その関連ワークスペース変数を parfor
ループの外側と前で定義した場合は、モデルが読み込まれず、 parfor
反復が実行される MATLAB ワーカー セッションでワークスペース変数も定義されません。これは通常、モデルのパラメーターまたは外部入力をクライアント セッションのベース ワークスペースで定義する場合です。これらのシナリオからワークスペースのアクセスの問題が生じます。
透明性の違反. srcWorkspace
を current
に設定して parfor
内で sim
を実行した場合、Simulink は透明なワークスペースである parfor
ワークスペースを使用します。Simulink はその後透明性違反のエラーを表示します。透明なワークスペースの詳細については、parfor ループまたは spmd ステートメント内での透過性の確保 (Parallel Computing Toolbox)を参照してください。
データ ディクショナリのアクセス. モデルがデータ ディクショナリにリンクされている場合 (データ ディクショナリとはを参照)、ディクショナリ内に保存した変数やオブジェクトにアクセスするコードを parfor
に記述するには、関数 Simulink.data.dictionary.setupWorkerCache
と Simulink.data.dictionary.cleanupWorkerCache
を使用してアクセスの問題を回避しなければなりません。例については、並列シミュレーションを使用したバリアント制御のスイープを参照してください。
ワークスペースのアクセス問題の解決
Simulink モデルが MATLAB クライアント セッションのメモリに読み込まれると、その MATLAB セッションでのみ表示とアクセスが可能です。MATLAB ワーカー セッションのメモリではアクセスできません。同様に、MATLAB クライアント セッションで定義されるモデル (パラメーターや外部入力) に関連付けられているワークスペース変数は、ワーカー セッションで自動的に使用可能になることはありません。そのため、次の 2 つの方法を使用して、モデルが読み込まれ、モデルで参照されているワークスペース変数が MATLAB ワーカー セッションで定義されるようにしなければなりません。
parfor
ループで、sim
コマンドを使用してモデルを読み込み、反復ごとに変わるパラメーターを設定します (もう一つの方法: モデルを読み込んでからg(s)et_param
コマンドを使用してparfor
ループでパラメーターを設定します)。parfor
ループで、MATLABevalin
コマンドと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 コードをループに追加して次の手順を実行することで避けることができます。
現在のフォルダーを書き込み可能な一時フォルダーに変更します。
一時フォルダーで、モデルを読み込み、パラメーターと入力ベクトルを設定して、モデルのシミュレーションを実行します。
最初の現在のフォルダーに戻ります。
一時フォルダーと一時パスを削除します。
このようにして個別の一時フォルダーにモデルを読み込んでシミュレートすることで、同時実行の問題を避けます。以下は、この方法で一般的な同時実行の問題を解決する例です。
Stateflow、MATLAB Function ブロック、または Model ブロックのあるモデル. この例では、モデルがアクセラレータ モードでシミュレーションを実行するように構成されているか、Stateflow、MATLAB Function ブロックまたは Model ブロック (たとえば、sf_bounce
、sldemo_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