This example shows how to use Simulink.SimulationData.DatasetRef
objects and the parsim
function to stream input data from a version 7.3 MAT-file for parallel simulations. Consider following the steps outlined in this example when the inputs for your simulation are too large to load into memory. For example, you can use data logged to persistent storage from one set of parallel simulations as input for another.
This example uses parsim
to run multiple simulations of a model, with each simulation using unique input data. The model is based on the sldemo_suspn_3dof model, modified to use Inport blocks as the source for inputs instead of the Signal Editor block. The model simulates the response of a suspension system to different road conditions. The MAT-file used in this example contains multiple Simulink.SimulationData.Dataset
objects representing various road conditions. The example uses DatasetRef
objects to stream the contents of an entire referenced Dataset
object as simulation input.
You can also stream data for individual signals into parallel simulations run with parsim
using matlab.io.datastore.SimulationDatastore
objects. For details on creating SimulationDatastore
objects, see Stream Individual Signals Using SimulationDatastore Objects.
Load the ex_sldemo_suspn_3dof_parsim_stream
model. The model receives input data through two Inport blocks, and each Dataset
object used as simulation input contains two elements: one for each Inport.
mdl = 'ex_sldemo_suspn_3dof_parsim_stream';
open_system(mdl)
You can use the Simulink.SimulationData.DatasetRef.getDatasetVariableNames
function to evaluate the contents of the MAT-file containing the input data without loading the data into memory. The function returns a cell array that contains elements for the name of each Simulink.SimulationData.Dataset
variable the file contains. Use the function to access the variable names and determine the number of test cases in the file.
varNames = Simulink.SimulationData.DatasetRef.getDatasetVariableNames('suspn_3dof_test_cases.mat');
numTestCases = numel(varNames);
You can stream the test case data into the model using Simulink.SimulationData.DatsetRef
objects. The DatasetRef
object references a variable in the file used to create it and loads the variable data incrementally. Create a DatasetRef
object for each Simulink.SimulationData.Dataset
object in the test cases file.
for idx1 = 1:numTestCases inputData(idx1) = Simulink.SimulationData.DatasetRef('suspn_3dof_test_cases.mat',... varNames{idx1}); end
To use the set of test case inputs as input for a set of parallel simulations, create an array of Simulink.SimulationInput
objects that you can pass to the parsim
function. Use the setExternalInput
function to specify a Simulink.SimulationData.DatasetRef
object corresponding to a test case as data to stream as simulation input.
in(1:numTestCases) = Simulink.SimulationInput(mdl); for idx2 = 1:numTestCases in(idx2) = setExternalInput(in(idx2),inputData(idx2)); end
Use the parsim
function to run a simulation for each test case. When you have the Parallel Computing Toolbox™, the parsim
function runs simulations in parallel. Without the Parallel Computing Toolbox, the parsim
function runs the simulations in serial.
The parsim
function creates a worker pool based on the Parallel Computing Toolbox configuration. By default, parsim
uses a local pool. If you use remote workers, you can use the AttachedFiles
name-value pair to send the MAT-file containing the test case input data to each worker. When you specify the AttachedFiles
name-value pair, parsim
sends a copy of the file to each worker, which can take some time for large files. For streaming input data from a large file, local workers may be faster because the workers have access to the file without creating and sending copies. When you use remote workers, consider storing the MAT-file in a location that all remote workers can access and creating DatasetRef
objects that reference that copy of the file.
out = parsim(in);
[20-May-2020 08:58:17] Checking for availability of parallel pool... Starting parallel pool (parpool) using the 'local' profile ... Connected to the parallel pool (number of workers: 6). [20-May-2020 08:59:10] Starting Simulink on parallel workers... [20-May-2020 08:59:50] Configuring simulation cache folder on parallel workers... [20-May-2020 08:59:50] Loading model on parallel workers... [20-May-2020 09:00:02] Running simulations... [20-May-2020 09:00:18] Completed 1 of 20 simulation runs [20-May-2020 09:00:18] Completed 2 of 20 simulation runs [20-May-2020 09:00:18] Completed 3 of 20 simulation runs [20-May-2020 09:00:18] Completed 4 of 20 simulation runs [20-May-2020 09:00:19] Completed 5 of 20 simulation runs [20-May-2020 09:00:19] Completed 6 of 20 simulation runs [20-May-2020 09:00:21] Completed 7 of 20 simulation runs [20-May-2020 09:00:21] Completed 8 of 20 simulation runs [20-May-2020 09:00:21] Completed 9 of 20 simulation runs [20-May-2020 09:00:21] Completed 10 of 20 simulation runs [20-May-2020 09:00:21] Completed 11 of 20 simulation runs [20-May-2020 09:00:21] Completed 12 of 20 simulation runs [20-May-2020 09:00:24] Completed 13 of 20 simulation runs [20-May-2020 09:00:24] Completed 14 of 20 simulation runs [20-May-2020 09:00:24] Completed 15 of 20 simulation runs [20-May-2020 09:00:24] Completed 16 of 20 simulation runs [20-May-2020 09:00:24] Completed 17 of 20 simulation runs [20-May-2020 09:00:24] Completed 18 of 20 simulation runs [20-May-2020 09:00:27] Completed 19 of 20 simulation runs [20-May-2020 09:00:27] Completed 20 of 20 simulation runs [20-May-2020 09:00:27] Cleaning up parallel workers...
You can access the simulation results programmatically when the simulations finish. Create a plot showing the vertical displacement for the vehicle for all the road profile test cases.
if isempty(out(1).ErrorMessage) legend_labels = cell(1,numTestCases); for i = 1:numTestCases if isempty(out(i).ErrorMessage) simOut = out(i); ts = simOut.logsout.get('vertical_disp').Values; ts.plot; legend_labels{i} = ['Run ' num2str(i)]; end hold all end title('Response of a 3-DoF Suspension Model') xlabel('Time (s)'); ylabel('Vehicle vertical displacement (m)'); legend(legend_labels,'Location','NorthEastOutside'); end
You can also view parsim
simulation results using the Simulation Manager. To view results in the Simulation Manager, use the ShowSimulationManager
name-value pair for parsim
. With the Simulation Manager, you can monitor the progress of the runs, view simulation data, and show the parsim
results in the Simulation Data Inspector.
When you have finished running parallel simulations, you can close the worker pool.
delete(gcp('nocreate'));