Parallel Simulations: Your options to configure data when using parsim and batchsim
Today I am happy to welcome guest blogger Reid Spence. Reid helps Simulink users running simulations in parallel using functions like parsim or batchsim. In this post, he shares best practices to manage the data needed by Simulink models in the context of parallel simulations.
The Problem
Did you ever run into a situation where you have a model that simulates successfully when using the sim command or the play button, but errors out when simulated using parsim and the Parallel Computing Toolbox? This can happen for various reasons, let's begin with the one I see the most often.
Let's start with this simple model, which uses 3 variables defined in the MATLAB base workspace: k, c, and m:
I can successfully simulate this model:
k=5; c=3; m=2;
mdl = 'simpleSuspension';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = sim(in,'ShowProgress','off');
figure;
plot(out(1).logsout.get('x').Values); hold on
plot(out(2).logsout.get('x').Values);
Now, let's try to use parsim to simulate the model in parallel with different values of k:
mdl = 'simpleSuspension';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = parsim(in,'ShowProgress','on','ShowSimulationManager','on');
As you can see, the simulations errored out. We can look at the Simulation Manager to learn more on the error.
What Happened?
Let's look in details at what happened. For that, we can look at the progress displayed by parsim. The first thing we see is that parsim starts a parallel pool.
[08-Nov-2022 14:11:17] Checking for availability of parallel pool...
Starting parallel pool (parpool) using the 'Processes' profile ...
Connected to the parallel pool (number of workers: 2).
Starting a parallel pool means the MATLAB session you are interacting with (the Client in the next image) is launching new MATLAB sessions in the background, without the user interface (the Workers in the next image)
Once the parallel workers are up and running, we start Simulink on each worker:
[08-Nov-2022 14:11:39] Starting Simulink on parallel workers...
To avoid conflicts between workers, we configure each of them to use a different cache folder:
[08-Nov-2022 14:11:46] Configuring simulation cache folder on parallel workers...
The model is loaded on each worker:
[08-Nov-2022 14:11:47] Loading model on parallel workers...
Finally, the model is being simulated:
[08-Nov-2022 14:11:52] Running simulations...
Hopefully, you see where I am going with that... the parallel workers need to be configured! In the above example, "be configured" means loading variables in the base workspace. If you are dealing with large complex models, you probably understand that "be configured" can mean a lot of things.
What we will discuss in this post are the different options offered by parsim and batchsim to automate the configuration of the parallel workers
Multiple Options to Configure Parallel Workers
Articles have been published on this blog on the topic of parallel simulations:
- 2010: Parallel Computing with Simulink: Running Thousands of Simulations!
- 2016: Tips for simulating models in parallel
- 2017: Simulating models in parallel made easy with parsim
If you go through those posts, you will see that the process of configuring parallel workers have been significantly simplified throughout the years. As of MATLAB R2022b, parsim offers many options to automatically configure the parallel workers.
Here is a picture giving an overview of what parsim configures automatically versus what you can optionally opt-in.
In the next sections, we will cover the following options to configure parallel workers:
- Data Dictionary and Model Workspace
- Transferring the Client Base Workspace
- Project Startup Tasks
- Model Callbacks
- SetupFcn Callback
- preSimFcn Callback
Data Dictionary and Model Workspace
If all your model is missing is data, one option is to store the data in a Data Dictionary or in the Model Workspace. That way parsim will automatically make the associated files available to the parallel workers.
With a data dictionary, all you need to do is use setVariable to specify the variables to be different in each simulation:
clear
mdl = 'simpleSuspensionWithSldd';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = parsim(in,'ShowProgress','off');
Transferring the Client Base Workspace
If, for some reason, you cannot or don't want to use a data dictionary, it is possible is to use the TransferBaseWorkspaceVariables option of parsim and batchsim to send a copy of the client's base workspace to the workers.
clear;
k=5; c=3; m=2;
mdl = 'simpleSuspension';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = parsim(in,'TransferBaseWorkspaceVariables','on','ShowProgress','on');
What are the pros and cons of this approach?
- Pro: Simplicity, one additional argument and we automatically copy the entire client base workspace to the workers.
- Con: Possibly inefficient if the client session has many large variables in its base workspace that are not needed by the simulation.
Project Startup Tasks
If your model is part of a MATLAB Project and the MATLAB Project is open on the client, parsim will transfer and open the project on the the workers, which will execute the Project Startup Tasks.
clear
openProject('ParsimDataManagment.prj');
mdl = 'simpleSuspension';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = parsim(in,'ShowProgress','off');
close(currentProject);
Model Callbacks
If you are not using a MATLAB Project, another option is to use callback functions such as the model preLoadFcn. For my example model, I can define k, c and m that way:
When the model will be loaded on the workers, the preLoadFcn callback will execute and define the variables needed by the model.
clear;
mdl = 'simpleSuspensionWithCallback';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = parsim(in,'ShowProgress','off');
SetupFcn Callback
If none of the above works for you, parsim offers a SetupFcn callback that can be used to run any additional custom setup on the workers. The setupFcn callback will be run once per worker. As a simple example, the SetupFcn can evaluate code in the worker's Base Workspace.
mdl = 'simpleSuspension';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setVariable('k',10);
in(2) = in(2).setVariable('k',20);
out = parsim(in, 'SetupFcn',@()mySetupFunction());
With the setup function being:
function mySetupFunction()
evalin('base','c=3;k=5;m=2;');
end
preSimFcn Callback
In addition to the SetupFcn callback that runs once per worker, the SimulationInput object offers the preSimFcn callback to run any MATLAB code on the workers before each simulation. The SimulationInput object is passed as an argument so we can make changes to the object on the worker. We can use preSimFcn's to parallelize time intensive setups. The flexibility of the preSimFcn can also make it ideal for integrating legacy MATLAB code you may have for setting up simulation runs.
clear
mdl = 'simpleSuspension';
in(1:2) = Simulink.SimulationInput(mdl);
in(1) = in(1).setPreSimFcn(@(in) presim(in,10));
in(2) = in(2).setPreSimFcn(@(in) presim(in,20));
out = parsim(in);
With the presim function:
function in = presim(in, k)
in = in.setVariable('k',k*rand);
in = in.setVariable('c',3);
in = in.setVariable('m',2);
end
Now it’s your turn
Let us know in the comments below which combinations of the methods listed in this post you use to set up your parallel simulations.
댓글
댓글을 남기려면 링크 를 클릭하여 MathWorks 계정에 로그인하거나 계정을 새로 만드십시오.