Run Co-Simulation Components on Multiple Cores
Simulink® supports cosimulation between components using local solvers or that involves simulation tools. For example, cosimulation can involve an S-function implemented as a cosimulation gateway between Simulink and third-party tools or custom code. It can also involve an FMU in cosimulation mode imported to Simulink or a Model block in accelerator mode.
To improve performance, consider running models that contain cosimulation blocks (components) on multiple threads if:
You are integrating multiple cosimulation components
Integration at the component level is computationally intense
This topic assumes that you are familiar with multithreaded programming and concepts.
Simulink lets you run C MEX S-functions, Co-Simulation FMU blocks, and Model blocks configured for accelerator mode on multiple threads if they are threadsafe. Being threadsafe means that the block can work with multiple threads accessing shared data, resources, and objects without any conflicts.
You can also run a model on multiple threads if the model has a nondirect feedthrough block followed by a direct feedthrough block (see Singlethreaded Versus Multithreaded Simulations). Direct feedthrough means that the output port signal of a block is computed from the values of its input port signals in the same time step.
Note
Multithreaded cosimulation for Level-2 MATLAB S-Function blocks is not supported.
By default, Simulink configures all models to run on multiple threads. If performance can be improved, Simulink automatically runs all models on multiple threads. However, not all models have cosimulation components that can run on multiple threads, and not all models benefit from running on multiple threads.
Singlethreaded Versus Multithreaded Simulations
When evaluating a model for possible concurrencies in your system for multithread execution, Simulink uses a graph-based algorithm to analyze data dependencies among eligible blocks and form multiple task groups. This algorithm ensures that the different task groups:
Have no data dependencies on each other
Can execute in parallel using multiple cores
For example, Simulink might look for non-direct feedthrough blocks followed by direct feedthrough blocks. If the following direct feedthrough blocks depend only on a nondirect feedthrough block, the software can group the blocks in the same branch for parallel execution.
This example compares the serial execution of a series of blocks partitioned for parallel execution.
Using Multithreaded Simulation to Speed up Simulation on Multiple Cores
Consider the Graph-Based Multithread Simulation
example, which uses
four nondirect feedthrough blocks followed by four direct feedthrough blocks. Direct
feedthrough means that the output port signal of a block is computed from the values of its
input port signals in the same time step.
Simulink analyzes the data dependencies and forms four branches. Each branch contains
nondirect feedthrough blocks followed by direct feedthrough blocks. Then, Simulink uses multithreading to run those four branches. In this way, Simulink can speed up the simulation up to four times on a four or more core machine
compared to a single-threaded simulation on the same machine. You can manually measure the
simulation of the model before and after changing the MultithreadedSim
parameter.
This code shows how to capture timing information for simulation of the
Graph-Based Multithread Simulation
example.
openExample('simulink/GraphBasedMultithreadSimulationExample') mdl = 'slexGraphBasedMultiThreadSimExample';
To configure the baseline simulation, create a Simulink.SimulationInput
object. The SimulationInput
object stores parameter values to use in the
simulation.
simin = Simulink.SimulationInput(mdl); simin = setModelParameter(simin,'MultithreadedSim','off');
To capture baseline timing information, simulate the model.
out = sim(simin);
Access the timing information for the baseline simulation and extract the total elapsed time.
timingInfo = out.SimulationMetadata.TimingInfo; execSingleThreadTime = timingInfo.TotalElapsedWallTime;
Simulate the model again and enable MultithreadedSim
.
simin = setModelParameter(simin,'MultithreadedSim','on'); out = sim(simin);
Access the timing information for the multithreaded simulation and extract the total elapsed time.
timingInfo = out.SimulationMetadata.TimingInfo; execMultithreadTime = timingInfo.TotalElapsedWallTime;
Calculate simulation improvement.
execTimeImprovement = execSingleThreadTime/execMultithreadTime
The simulation time improvement may vary on different hardware. When you run this code on a Windows® desktop with AMD EPYC™ 74F3 CPU @ 3.19 GHz 24 Cores 2 Threads processor, the multithreaded simulation executes almost three times faster than the single-threaded simulation.
Using the MultithreadedSim
Parameter
You can specify that an entire model run on multiple threads, or specify that particular
blocks run on multiple threads, using the MultithreadedSim
parameter.
Specify that an entire model runs on multiple threads if all the cosimulation blocks in the
model are threadsafe. If some, but not all blocks, are threadsafe, identify only those
blocks to run on multiple threads. The model and blocks use the
MultithreadedSim
parameter as follows:
Setting | Description |
---|---|
| (Default) Let Simulink decide if the block can run on multiple threads. |
| Disable the block or model from running on multiple threads. |
a Starting in R2021a, when you open a model created in a previous release,
Simulink interprets the |
Enabling the MultithreadedSim
parameter does not mean that the block
or model simulates on multiple threads. Simulation on multiple threads occurs when
MultithreadedSim
is enabled and:
The block and/or model operate at a single rate.
The block and/or model are threadsafe. (For example, they do not use static or global data).
The block and/or model is exception-free. For S-function blocks, use the
ssSetOptions
function to setSS_OPTION_EXCEPTION_FREE_CODE
.
Multithreading does not allow solver reset checks, and therefore skips over any use of
the ssSetSolverNeedsReset
and
ssBlockStateForSolverChangedAtMajorStep
functions. Conversely, in
accelerator mode, if these functions are used or there are continuous states, multithreading
is automatically turned off.
Configuring S-Function Blocks to Run Single or Multithreaded
Whether an S-function block runs single or multithreaded depends on the
MultithreadedSim
parameter value and the ssSetRuntimeThreadSafetyCompliance
function.
MultithreadedSim Setting | ssSetRuntimeThreadSafetyCompliance Setting | Single or Multithread |
---|---|---|
'auto' | RUNTIME_THREAD_SAFETY_COMPLIANCE_UNKNOWN | Single thread |
'auto' | RUNTIME_THREAD_SAFETY_COMPLIANCE_TRUE | Multithread |
'auto' | RUNTIME_THREAD_SAFETY_COMPLIANCE_FALSE | Single thread |
'off' | — | The setting is ignored and the S-function block runs singlethreaded |
Co-Simulation on Multiple Threads Limitations and Guidelines
The simulation runs on a single thread for accelerator and rapid accelerator modes. Multithreading is enabled when the simulation mode is normal.
Set model simulation mode to normal.
There is no code generation for cosimulation components.
Multithreading is not activated for blocks with constant sample time.
Multithreading is not enabled when the Simulink debugger is on.
Turn off Simulink debugger.
A block that depends on a non-thread-safe block cannot be multithreaded. Consider breaking the dependency, for example, by using a Unit Delay block.
S-Function Block Limitations
Must have a single rate.
Consider revising your model to break down multirate components into individual single-rate components.
Multithreading is not enabled when an S-function has variable sample time.
Consider using a different sample time (see Specify Sample Time).
Multithreading is not enabled when an S-function has continuous states and solver is fixed-step, which together trigger a continuous states consistency check. To disable continuous states consistency checks, use the
ssSetSkipContStatesConsistencyCheck
function.Must be thread safe — In
ssSetRuntimeThreadSafetyCompliance(SimStruct *S,int_T val)
,val
must beRUNTIME_THREAD_SAFETY_COMPLIANCE_TRUE
.For more information, see Guidelines for Writing Thread-Safe S-Functions.
Must be exception-free — In
ssSetOptions(SimStruct *S,uint_T options)
,options
must includeSS_OPTION_EXCEPTION_FREE_CODE
.For more information, see Guidelines for Writing Thread-Safe S-Functions.
Multithreading is not enabled when the S-function Analyzer is on. Try multithreading in normal mode.
Multithreading is not enabled when S-function has continuous sample time. Consider using a different sample time (see Specify Sample Time).
Multithreading concurrently runs output and update methods. The block must have an output or update method.
FMU Import Block Limitations
Must be in cosimulation mode.
Consider switching FMU mode from Model Exchange to Co-Simulation.
Must be thread-safe, for example, multiple FMUs must not access the same file at the same time.
Multithreading is not enabled when FMU block logging displays in the MATLAB® command window. Redirect FMU block logging to a file using:
set_param(blockName,'FMUDebugLoggingRedirect','File')
Multithreading is not supported when FMU is running out-of-process. To disable this setting, use:
set_param(blockName,'DebugExecutionForFMUViaOutOfProcess','off')
Model Block Limitations
Multithreading is not enabled when a Model block has event ports.
Cannot be inside a For Each Subsystem block.
Consider moving the Model block out of the For Each Subsystem block.
Must be in accelerator mode.
Must have single rate.
Consider revising your model to break down multirate components into individual single-rate components.
Cannot use blocks with variable sample time.
Consider using a different sample time (see Specify Sample Time).
Cannot have continuous states.
Consider breaking the dependency between blocks, for example, by using a Unit Delay block.
Must have a fixed-step solver.
Cannot access any global data stores.
Multithreading is not enabled when a model contains a Simulink Function block.
Cannot use any Simulink functions or caller blocks.
Cannot contain To File blocks. For more information, see Save Simulation Data.
Cannot contain From File blocks.
Consider feeding data into the referenced model via an inport from the top-level model.
See Also
FMU | S-Function | ssSetRuntimeThreadSafetyCompliance
| ssGetRuntimeThreadSafetyCompliance