Simulink 提供了三种仿真模式:
- 正常(Normal)
- 加速(Accelerator)
- 快速加速(Rapid Accelerator)
这三种模式有什么区别,适用于什么样的场合,“加速”和“快速加速”到底能快多少呢?
普通模式
在正常模式下,Simulink引擎的求解器会调用模型方法(Model methods)来更新每个时间步的状态和输出。
由于正常模式下会用解释的方式执行每个模块,所以正常模式支持包括调试、诊断等功能,但性能没有得到优化。
如果需要经常修改模型,通常选择正常模式,因为不需要模式那样单独的编译步骤。
加速模式
加速模式下,Simulink 将模型编译(compiles)到运行内存中的执行引擎(execution engine)中,从而消除了正常模式下解释仿真模型的开销。
加速模式又分为:
-
即时加速模式。
-
经典加速模式。
默认情况下,加速器模式使用即时 (JIT) 加速在内存中生成执行引擎,而不是生成 C 代码或 MEX 文件。
1. 即时加速模式
在默认的即时加速模式下,Simulink 在内存中只为顶级模型(而不为引用模型)生成执行引擎。因此,仿真过程中不需要使用 C 编译器。
由于加速目标代码在内存中,因此只要模型处于打开状态,就可以重用这些代码。Simulink 还会序列化加速目标代码,因此当模型处于打开状态时,不需要重新构建模型。
加速器模式支持调试器(debugger)和分析器(profiler),但只支持有限的运行时诊断。当仿真时间远长于编译时间时,通常可选择加速模式。
2. 经典加速模式
在此模式下,Simulink 会生成代码并将代码链接到与 Simulink 软件进行通信的共享库。MATLAB 与 Simulink 的目标代码执行过程相同。
由于经典加速模式不是默认模式,需要使用下面的命令来启用
set_param(0,'GlobalUseClassicAccelMode','on');
相较于即时加速模式,经典加速模式会在目录下生成生成C代码或MEX文件。
快速加速模式
快速加速模式为模型创建一个快速加速独立可执行文件。这个可执行文件包含求解器和模型方法,但位于 MATLAB 和 Simulink 的外部,可以在单独的进程上运行。
快速加速独立可执行文件使用外部模式与 Simulink 进行通信。
外部模式允许 Simulink 框图与根据生成的代码构建的独立程序之间进行通信。在此模式下,实时程序充当进程间通信服务器,响应来自 Simulink 引擎的请求。
只有当完整模型能够生成代码时,才能使用快速加速模式。该模式会限制模拟期间与模型的交互。例如,快速加速器模式不支持调试。与加速器模式一样,当模拟时间比一次性编译时间长很多时,最好使用快速加速器模式。
性能对比
下图展示了三种仿真模式在速度与灵活性上的对比,可以看到二者成反比的关系,因此需要根据模型的实际情况做出取舍。
示例
这里选择一个发动机的燃料控制系统模型进行演示,在MATLAB命令行中输入下述代码即可打开该模型。
openExample('simulink_automotive/ModelingAFaultTolerantFuelControlSystemExample')
设置仿真参数
model = "sldemo_fuelsys";
simIn = Simulink.SimulationInput(model);
simIn = setModelParameter(simIn,"StopTime","10000");
%% 正常模式
simIn = setModelParameter(simIn,"SimulationMode","normal");
normalMode = sim(simIn);
normalInit = normalMode.SimulationMetadata.TimingInfo.InitializationElapsedWallTime; %初始化耗时
normalExec = normalMode.SimulationMetadata.TimingInfo.ExecutionElapsedWallTime; %计算耗时
normalTotal = normalMode.SimulationMetadata.TimingInfo.TotalElapsedWallTime; %总耗时
%% 加速模式
simIn = setModelParameter(simIn,"SimulationMode",'accelerator');
acceleratorMode = sim(simIn);
acceleratorInit = acceleratorMode.SimulationMetadata.TimingInfo.InitializationElapsedWallTime; %初始化耗时
acceleratorExec = acceleratorMode.SimulationMetadata.TimingInfo.ExecutionElapsedWallTime; %计算耗时
acceleratorTotal = acceleratorMode.SimulationMetadata.TimingInfo.TotalElapsedWallTime; %总耗时
%% 快速加速模式
simIn = setModelParameter(simIn,"SimulationMode",'rapid');
rapidAcceleratorMode = sim(simIn);
rapidAcceleratorInit = rapidAcceleratorMode.SimulationMetadata.TimingInfo.InitializationElapsedWallTime; %初始化耗时
rapidAcceleratorExec = rapidAcceleratorMode.SimulationMetadata.TimingInfo.ExecutionElapsedWallTime; %计算耗时
rapidAcceleratorTotal = rapidAcceleratorMode.SimulationMetadata.TimingInfo.TotalElapsedWallTime; %总耗时
创建一个时间表来对比每种模式的时间:
InitializationTime = [normalInit;acceleratorInit;rapidAcceleratorInit];
ExecutionTime = [normalExec;acceleratorExec;rapidAcceleratorExec];
TotalSimulationTime = [normalTotal;acceleratorTotal;rapidAcceleratorTotal];
simNames = ["Normal Mode";"Accelerator";"Rapid Accelerator"];
timingTable = table(TotalSimulationTime,InitializationTime, ...
ExecutionTime,RowNames=simNames)
结果为:
可以看到正常模式的初始化时间为3.8s,但计算时间达到了63s之多。
加速模式下初始化时间较正常模式稍长,但求解时间降低至16.3s。
快速加速模式消耗了接近19s在初始化阶段,也就是模型编译阶段,但求解效率大大增强,仅耗时6.2s。
结合总耗时来看,加速模式凭借即时加速带来的较短的编译时间,在总耗时上有着最好的表现。
但考虑到模型编译仅在初次消耗较多的时间,当我们再次使用上述三种模式运行仿真,可以看到正常模式与加速模式的耗时与第一次仿真差异不大,但快速加速模式由于无需在初始化编译上消耗额外的时间,总耗时仅为初次仿真的1/3,计算效率远高于其他两种模式。
选择建议
通常,在处于需要经常进行结构性修改(添加或删除块)并仿真测试的开发阶段,建议使用正常模式。
当只是想要运行多个仿真而不进行结构性修改(可进行参数修改)时,可考虑使用加速器模型或快速加速器模式。
当仿真执行时间为几分钟或更长时,加速和快速加速模式的执行性能一般要高于普通模式。
包含大量Stateflow或MATLAB Function模块的模型在速度提升方面可能只是略高于普通模式,因为这些模块在普通模式下也通过代码生成进行仿真。