如何提高Simulink仿真性能呢?有哪些使用技巧?

描述

无论模型的复杂程度如何,每个 Simulink 用户都希望提高仿真性能。本文介绍了许多实用技巧和技术,来帮助您在仿真工作流中获得最佳的性能。

提高仿真性能的第一步

您首先需要查看您的仿真工作流,搞清楚针对模型所需要运行的编辑、初始化和仿真的次数。例如,以下四种常见工作流具有非常不同的特征。仿真模式和性能选项的最佳选择将取决于您正在使用的这四个工作流中的哪一个。 第一个工作流是“编辑-更新-重复”(图1)。当您按 Ctrl+D 以确保模型更新时,这个工作流是典型的,但您还没有准备好进行仿真验证;当您对模型进行大量修改时,此工作流是典型的。

simulink仿真

图1:“编辑-更新-重复”工作流 第二个工作流是“编辑-仿真-重复”工作流,它需要每次编辑结构并初始化模型(图2)。

simulink仿真

图2:“编辑-仿真-重复”工作流 第三个工作流是“调参-仿真-重复”(图3)。它关注于一些参数的迭代调优,不需要编辑模型结构。

simulink仿真

图3:“调参-仿真-重复”工作流 第四个工作流是 multisim 工作流(图4)。通常是跑那些验证过的模型的仿真,其中分担执行将有所帮助【译者注:如利用多核并行】

simulink仿真

图4:multisim 工作流

影响我们选择性能解决方案的另一个因素是仿真的哪个阶段在总耗时中占主导地位。您可以在 Simulink 中返回的 SimulationMetadata 对象中使用计时信息。SimulationOutput 对象,以查看初始化或执行所占用的总时间的比例。例如,在下面的例子中,我们可以说这个模型的性能是由执行时间决定的,所以我们应该关注性能解决方案来加速模型的执行,而不是初始化。 您可以查看在最常见的工作流中使用的模型的仿真元数据,以进一步了解仿真属性。

SimulationMetadata 对象包含关于仿真运行的信息,包括模型信息、定时信息和执行信息等。你可以通过访问 out.SimulationMetadata.TimingInfo 属性来获取计时信息。仿真元数据的计时信息示例如下:

 

          WallClockTimestampStart: '2021-12-16 1015'
           WallClockTimestampStop: '2021-12-16 1044'
    InitializationElapsedWallTime: 0.6918
         ExecutionElapsedWallTime: 87.8463
       TerminationElapsedWallTime: 0.4087
             TotalElapsedWallTime: 88.9468
                     ProfilerData: 'Profiler is not enabled'

 

根据您特定的仿真工作流程和模型特征(初始化时间与执行时间等),您可以快速参考下面的表1来选择并尝试正确的技术。

  编辑-更新-重复 编辑-仿真-重复 调参-仿真-重复 multisim
仿真模式   x x x
快速启动     x x
仿真缓存 x x x x
模型引用-并行编译 x x    
模型引用-增量加载和重新编译 x x    
Simulink Profiler x x x x
Solver Profiler   x x x
修改你的模型   x x x
并行仿真       x
 

表1:提高仿真性能的典型技术。

选择正确的仿真模式

Simulink 提供了三种仿真模式:普通、加速和快速加速(图5)。顾名思义,加速通常比普通快,快速加速更快。速度的每一次提高通常都意味着牺牲灵活性、交互性和/或诊断性。在许多情况下,如果您可以在没有这些功能的情况下工作(至少暂时如此),那么仿真速度将得到改善。

simulink仿真

图5:Simulink仿真模式

正常模式下,Simulink 在每次仿真运行期间解释您的模型。如果您经常更改模型,这通常是首选的模式,因为它不需要像加速模式和快速加速模式那样单独的编译步骤。

加速模式下(Accelerator),Simulink 将模型编译成内存中的执行引擎,从而消除了正常模式下块到块的解释仿真的开销。加速模式支持调试器和分析器,但只支持一组有限的运行时诊断。当仿真时间比编译时间长得多时,通常使用加速模式。

快速加速模式(Rapid Accelerator)下,Simulink 将模型编译为一个独立的可执行文件,它可以在单独的进程中运行。只有当整个模型能够生成代码时,才能使用快速加速模式。这种模式限制了仿真过程中与模型的交互。例如,快速加速模式不支持调试。

与加速模式一样,当您的仿真时间比一次性编译时间长得多时,最好使用快速加速模式。 您可能想知道应该为您的工作流选择哪种模式。图 6 显示了假设模型仿真在普通、加速和快速加速模式下的性能。

simulink仿真

图6:一个假设模型在不同仿真模式下的性能

通常,当您处于“开发”工作流中,您经常修改模型并在修改之间执行更新图或简短的仿真时,建议使用正常模式。相反,当您希望运行多个仿真而不对模型进行结构更改(例如添加或删除块)时,请使用快速加速模式。 如果您知道模型不会在运行之间被更改,您可以通过将 RapidAcceleratorUpToDateCheck 设置为“off”来指示 Simulink 跳过快速加速初始化。请记住,对不可调参数的更改将被忽略。如果您的模型遇到了阻止使用快速加速模式的限制,请使用加速模式代替。 

当加速模式对某些模型的好处大于其他模型时

有时,您可能会注意到某些模型比其他模型更受益于加速或快速加速模式。如果您的模型没有看到很大的性能改进,则可能出现以下情况:

模型的算法主要包含在几个复杂的块中,例如快速傅立叶变换块或查找表。小型模型在加速模式下可能运行较慢,因为本机块是高度优化的。相比之下,具有许多基本块的模型更有可能从加速中受益。

您的模型包含大部分编译代码,例如来自 s 函数,Stateflow 块和 MATLAB functions 的代码。使用编译步骤不会进一步提高模型速度。

您的仿真运行包括初始化或终止阶段。因为加速模式只在每次运行的仿真阶段工作,如果它们需要耗时的初始化或终止阶段,它们可能不会提供太大的改进。有关详细信息,请参见本文的加速初始化阶段一节。

您的模型包含无法编译的块,例如解释执行的 MATLAB Function 块,或解释模式下的 MATLAB 系统对象。

为仿真迭代启用快速重启

在典型的 Simulink 仿真工作流程中,当您按下 Run 按钮时,Simulink 将首先更新和编译模型,然后仿真它。这个过程在以后的运行中重复。但是,如果您的仿真迭代只需要更改模型输入或可调参数,则通常不需要编辑模型结构。对于这些工作流,初始化阶段在第一次运行后通常是不必要的,并且在运行数百甚至数千次仿真时将迅速增加。 Simulink 提供了一个很好的功能,叫做快速重启(Fast Restart)。顾名思义,它允许您通过只编译一次模型来运行仿真迭代(图7)。

simulink仿真

图7:在 Simulink 中启用快速重启

启用“Fast Restart 快速重启”后,模型不会在每次运行后自动终止。相反,使用保存的初始化信息为下一组仿真再次自动初始化模型,而无需重新编译。 当使用 Fast Restart 时,模型将被锁定,并且您将无法编辑模型结构。在仿真完成之前,这可以防止模型发生任何结构变化。但是,您仍然可以更改可调参数或更改输入信号,并查看它们对仿真的影响。 您可以从上面所示的工具栏和使用 sim 和 parsim 函数的编程仿真中打开快速重启。

使用仿真工作点

工程师通常会针对不同的输入、边界条件和操作条件对 Simulink 模型进行仿真迭代。在许多情况下,这些仿真共享一个共同的启动阶段,在这个阶段中,模型从初始状态转换到其他状态。例如,在测试各种控制顺序之前,可能会使电动机加速。

使用仿真工作点,您可以在启动阶段结束时保存仿真快照,然后将其恢复为将来仿真的初始状态。这种技术本身并不能提高仿真速度,但是它可以减少连续运行的总仿真时间,因为启动阶段只需要仿真一次(参见下面的图8)。

simulink仿真

图8:使用快速重启和工作点恢复

并行运行多个仿真

通过使用 Simulink 和 Parallel Computing Toolbox 在多个处理核心之间分配仿真任务,您可以减少运行多个独立仿真所需的总时间。通过使用 MATLAB Parallel Server,您可以将仿真扩展到集群和云,从而进一步减少总体仿真时间。 并行运行仿真的常见用例包括蒙特卡罗分析、设计优化和测试用例扫描。例如,您可以设置一个蒙特卡罗仿真,在该仿真中,您可以在预定范围内改变参数的值。

然后,您可以在多个核心上独立并并行地对每个参数值执行仿真。 您可以并行处理设计优化中涉及的许多任务,包括从测试数据中估计模型参数、调整控制器增益以获得期望的响应、优化设计参数、执行灵敏度分析和执行鲁棒性分析。总仿真时间随着使用的处理器数量的增加而减少。

通常,关于如何设置并行多仿真运行,您有两种选择:Multiple Simulations 面板或调用 parsim 函数的脚本。您可以直接使用 Simulink 编辑器中的 Multiple simulation 面板设置和运行仿真(参见图 9)。在 Multiple simulation 面板中,您可以为仿真指定块参数和工作空间变量的值。通过选择“使用并行”选项,您可以自动启用仿真的并行执行。

simulink仿真

图9:使用 multisim 面板启动并行仿真 您还可以使用 parsim 构造来使用 MATLAB 脚本启动并行仿真。

使用模型引用和 Simulink 缓存

模型引用允许您使用模块将一个模型包含在另一个模型中。这样的每个实例都称为模型引用。与子系统一样,模型引用允许您组织大型模型层次结构(图10)。

simulink仿真

图10:模型引用 rebuild 选项

使用模型引用有很多性能上的好处:

增量加载。被引用的模型只在需要时加载。

加速仿真。模型引用允许您将仿真的部分存储在不同的模型文件中。如果仿真的大部分没有改变,可以将其放在加速器模式下的模型引用中。该部分第一次只编译一次,并在后续运行中更快地初始化和仿真。

增量 rebuild。如果选择的模型引用 Rebuild 选项是“如果检测到已知依赖项中的任何更改”,则实现这些引用模型的仿真目标不会在每次运行仿真时生成,而只会在引用模型和/或其任何依赖项或接口更改时重新生成。此选项比选择“如果检测到任何更改”选项要快,因为它跳过了计算模型校验和的步骤。如果您确定在仿真过程中模型结构没有改变,则可以将 Rebuild 选项设置为“Never”以进一步加速该过程。

并行编译。对于包含大型模型引用层次结构的模型,您可以通过并行编译引用模型来减少代码生成和编译时间。使用并行计算工具箱或 MATLAB 并行服务器,您可以在您的配置中跨多个 MATLAB worker 分发代码生成和编译任务。

模型引用通常在团队环境中使用,在这种环境中,您可以基于其他人构建的组件运行仿真。对于层次结构中的每个模型,Simulink 可以将这些构建的工件打包到具有. slxc 扩展名的单个 Simulink 缓存文件中(图11)。

simulink仿真

图11:Simulink缓存文件

对于 Simulink 缓存文件,只要将 Rebuild 配置参数设置为“如果检测到任何更改(默认)”或“如果检测到已知依赖项的任何更改”,Simulink 只编译过期的文件。您和您的团队成员可以彼此共享这些 SLXC 文件和相应的 Simulink 模型文件。 当您在机器上运行仿真时,Simulink 将从每个模型的 SLXC 文件中提取必要的派生文件。

因此,Simulink 不需要执行不必要的重新编译,并更快地完成仿真。 另外,Simulink 缓存文件适用于多种类型的编译工件,这些工件可能不是模型引用仿真目标(例如,快速加速器目标)。共享这些 Simulink 缓存文件可以显著降低基于团队的工作流中的重新编译成本。

分析模型的仿真瓶颈

在 Simulink 中有内置的功能,可以帮助您系统地理解模型,识别仿真性能瓶颈,并提高仿真速度。

Performance Advisor

Performance Advisor可以与Simulink Profiler和Solver Profiler一起从debug选项卡启动(图12)。

simulink仿真

图12:启动 Performance Advisor

Performance Advisor 分析模型,并对可能导致仿真性能低下的条件和配置设置进行不同的检查。Performance Advisor 提供了关于更好的模型配置设置的建议,以及自动或手动修复问题的机制。 一旦将建议的更改应用到您的模型中,Performance Advisor 就可以验证在提高性能方面发挥了多大作用(图13)。

simulink仿真

图13:Simulink Performance Advisor 

Simulink Profiler

在Simulink中,有两种类型的分析器可以用来对仿真速度慢的模型进行分析。如果您不确定使用哪一个,请参考图14快速入门。Simulink Profiler用于确定哪些块占用最多的仿真时间;Solver Profiler分析了变步求解器执行某些步骤的原因。

simulink仿真

图14:使用 Simulink Profiler 和 Solver Profiler

Simulink Profiler 允许您量化仿真的每个阶段需要多少时间以及每个块需要多少时间来仿真。在设计阶段,Simulink Profiler 通常与正常模式一起使用,以便您可以检查每个块的时间成本。

使用 Simulink Profiler 可以生成大量的数据。为了尽量减少需要检查的数据量,请关注那些花费最多时间和最频繁调用的方法。

Simulink Profiler 识别仿真速度慢的缘由,以便您可以手动评估仿真执行时间的性能。您还可以用轻量级块替换计算量最大的块,以加速仿真(图15)。

simulink仿真

图15:Simulink Profiler

Solver Profiler

当使用可变步长求解器模型仿真的速度变慢、需要太多小步长或停止响应时,Solver Profiler 可以帮助您理解求解器的行为并识别影响仿真速度的因素。 多种因素会影响求解器的行为并限制仿真速度。Solver Profiler 记录并报告模型仿真时发生的所有主要事件:

讨论二阶导数过零事件

求解器异常事件

解算器重置事件

雅可比矩阵计算事件

如果您的模型包含 Simscape 块,您还可以使用 Simscape Results Explore 查看这些块的各种物理量。

Solver Profiler 显示有关仿真、求解器设置、事件和错误的图形和统计信息。您可以使用这些数据来识别模型中导致仿真瓶颈的位置,并采取措施,例如更新系统的刚度以获得更好的仿真性能。

Solver Profiler 通常与可变步长求解器一起使用,以帮助解释为什么你的仿真需要太多步或为什么一个步长如此之小。另一方面,如果您关注的是为什么每个仿真步需要很长时间才能完成,或者如果您使用的是固定步长求解器,那么在前一节中讨论的Simulink Profiler就是适合的工具(图16)。

simulink仿真

图16:Solver Profiler 

修改和简化你的模型

到目前为止描述的大多数技术只需要对模型本身进行很少的更改(如果有的话)。您可以通过应用涉及对模型进行修改的技术来实现额外的性能提升。

加速初始化阶段

当您更新或打开模型时,Simulink 将运行掩码初始化代码。如果您有复杂的掩码初始化命令,其中包含许多对 set_param 的调用,请考虑将对 set_param() 的连续调用合并为具有多个参数对的单个调用。这可以减少与这些调用相关的开销。 

如果您使用 MATLAB 脚本来加载和初始化数据,您通常可以通过加载 mat 文件来提高性能。缺点是 mat 文件中的数据不是人类可读的形式,因此可能比脚本更难处理。但是,加载通常比等效脚本更快地初始化数据。 进一步了解:

数据导入和导出: https://ww2.mathworks.cn/help/matlab/data-import-and-export.html

降低模型复杂度

在不牺牲保真度的情况下简化模型是提高仿真性能的有效方法。以下是降低模型复杂性的三种方法。

用较低保真度的替代方案替换子系统。

在许多情况下,您可以通过使用以下方法之一替换复杂的子系统模型来简化您的模型:

使用系统识别工具箱从测量的输入输出数据创建的线性或非线性动态模型

使用基于模型的标定工具箱创建的高保真非线性统计模型

使用 Simulink Control Design 创建的线性模型

查找表

您可以在库中维护子系统的两种表示,并使用不同的子系统来管理它们。 

减少块的数量。

当您减少模型中的块数量时,在仿真期间需要更新的块就会更少,从而得到更快的仿真运行。向量化是减少块计数的一种方法。例如,如果您有几个并行信号,它们经历了类似的一组计算,请尝试将它们组合成一个向量并执行单个计算。另一种方法是在配置参数的 optimization > General 部分中启用 Block Reduction 优化。

使用基于帧的处理。

在基于帧的处理中,样品是分批处理的,而不是一次处理一个。例如,如果您的模型包含模数转换器,则可以在缓冲区中收集输出样本,并通过单一操作(例如快速傅立叶变换)处理缓冲区。以这种方式处理数据块可以减少必须调用模型中的块的次数。通常,调度开销随着帧大小的增加而减少。然而,更大的帧会消耗更多的内存,并且内存限制会对复杂模型的性能产生不利影响。尝试不同的帧大小,以找到一个最大限度地提高基于帧的处理的性能优势,而不会导致内存问题。

减少交互

一般来说,模型的互动性越强,仿真所需的时间就越长。本节中的技巧说明了通过放弃一些交互性来提高性能的方法。

关闭调试诊断开关。

有些启用了诊断功能的模型仿真速度明显较慢。您可以在“配置参数”对话框的“诊断”窗格中禁用它们。 注意:array bounds exceeded 与 solver data inconsistency 诊断项可能会导致模型运行时性能明显降低。

禁用仿真动画。

默认情况下,Stateflow chart 突出显示当前的活动状态,并将模型运行时发生的状态转换动画化。这个特性对调试很有用,但它会减慢仿真速度。要加速仿真,请关闭所有 Stateflow chart 或禁用动画。同样,如果您正在使用 Simulink 3D Animation、SimMechanics 可视化、FlightGear 或其他 3D 动画包,请考虑禁用动画或降低场景保真度以提高性能【译者注:尤其是 3D 动画,一定要开着的话,最好得有一块性能还过得去的独立显卡】。 

调整特定于查看器的参数,并通过启用的子系统管理查看器。

如果您的模型包含一个显示大量数据点的示波器查看器,并且您无法消除示波器,请尝试调整查看器参数从而在速度与保真度之间折衷。但是,请注意,通过使用抽取来减少绘制的数据点的数量,您可能会错过短暂的瞬变和其他现象,这些现象在使用更多数据点时可能会很明显。您可以将查看器放置在已启用的子系统中,以更精确地控制启用哪些可视化以及何时启用。 

使用 MATLAB functions 代替解释执行的 MATLAB Function 块

要在 Simulink 模型中调用 MATLAB 函数,请使用 MATLAB functions 而不是解释的 MATLAB Function 块或 MATLAB S-function。MATLAB function 是更快的选择。它支持生成可嵌入的 C 代码。虽然 MATLAB function 不支持所有 MATLAB 函数,但它所支持的 MATLAB 语言子集是广泛的。 要快速找到模型中的所有解释执行的 MATLAB Function 块,请使用 Performance Advisor。 

你记录大量的数据集。当记录大量数据时(例如,在包括 To Workspace、To File 或 Scope 块的模型中),使用抽取或将记录的输出限制为仿真的最后一部分。避免记录冗余数据(例如,只记录一次时间)和无关数据(例如,在可行的情况下记录整数值而不是双精度)。日志覆盖(Logging override)还可以用于控制记录哪些信号,而无需为加速模式重新编译仿真目标。

其他有用的技术

以下技术适用于一些特定的模型;如果您的模型属于下面描述的模式,您可能可以使用这些模式来提高仿真速度。

优化硬件加速

单指令多数据(SIMD)是一种数据级并行处理技术,可以同时对多个数据点执行相同的操作。许多现代 CPU 都有 SIMD 指令,例如,一次执行多个加法或乘法。对于支持块上的计算密集型操作,SIMD 指令可以提高仿真性能。 Simulink 在所有使用代码生成技术的仿真模式(例如,加速器或快速加速器模式)中支持 SIMD 硬件加速。

Simulink 提供了一个 configset 参数来控制仿真目标面板中的 SIMD 类型。对于硬件加速选项,默认选择(“利用通用硬件”)在所有 X86 cpu 上都可用,不需要重新构建。另一种选择(“利用本地硬件”)依赖于 CPU。如果您的 CPU 支持较新的 SIMD 指令集,如 SSE2/AVX2/AVX512,那么这种选择可以提供更快的仿真速度(图17)。

simulink仿真

图17:配置硬件加速选项 当您使用仿真目标时,有许多因素可以确定 SIMD 是否可用,或者 SIMD 是否可以提高仿真速度。您可以使用前面描述的性能顾问在仿真目标下运行一个带有“检查硬件加速设置”的检查,以了解 SIMD 是否对您的特定模型有帮助。 

利用多核仿真

在 Simulink 中,有几种不同的技术可以通过调度模型的某些部分用于多核执行来加速单个仿真。这些技术并不适用于所有的模型,但可能对您的特定用例有用。

数据流域的多核仿真。

如果您在 Simulink 中建模和仿真计算密集型信号处理或多速率信号处理系统,数据流域(dataflow domain)将提高性能。数据流域是使用计算同步数据流模型进行仿真的一种新的执行域。数据流执行域是数据驱动的,可以使用多个 CPU 核进行仿真。 通过使用 Property Inspector 将 domain 参数设置为 dataflow,可以指定 dataflow 作为子系统的执行域。数据流域自动划分您的模型,并使用多线程仿真系统,以获得更好的仿真性能(图18)。

simulink仿真

图18:数据流执行域 您可以使用多核选项卡上的运行分析按钮来对数据流域进行仿真性能分析。它可以分析模型,计算每个块的执行时间,找到模型中存在的并行性,并将其划分为多个线程。它可以建议一个延迟值,通过流水线执行块来进一步提高仿真吞吐量。下面图 19 中的分析建议将延迟设置为从 0 到 2 以获得最佳性能。

simulink仿真

图19:分析数据流域的仿真性能 

具有协同仿真组件的多核仿真。

您的仿真模型可能包括协同仿真的组件。协同仿真组件可以是一个 s-function 块,它被实现为 Simulink 和第三方工具或自定义代码之间的协同仿真网关。它也可以是导入到 Simulink 的联合仿真模式下的 FMU 或加速器模式下的模型块。如果这些协同仿真组件是线程安全的,那么这些组件就可以在多个线程上运行。线程安全意味着块可以与访问共享数据、资源和对象的多个线程一起工作,而不会产生任何冲突。 并不是所有的模型都有可以在多线程上运行的协同仿真组件。另外,多线程协同仿真只支持普通仿真模式。默认情况下,Simulink 将所有符合条件的模型和块配置为准备多线程执行。如果性能可以提高,Simulink 将自动在多线程上运行所有模型。

 For Each 子系统多核仿真。

For Each 子系统是 Simulink 中的一个子系统,它在仿真步中对输入信号或掩码参数数组中的子数组的每个元素重复算法执行。如果您的模型包含计算密集的 For Each 子系统,您可以通过在多线程上执行 For Each 子系统迭代来潜在地加速仿真。

For Each 子系统的多核仿真只支持快速加速仿真模式。默认情况下,for Each 子系统的多线程仿真支持是被启用状态。Simulink 将自动对仿真进行动态配置。只有在检测到性能优势时才并行执行才会被启用。您可以使用模型参数“multithreaddsim”手动选择加入或退出多线程仿真。

具体实践及效果对比

为了说明这些技术在实际项目中的相对有效性,我们通过将上面建议的一些更改应用于自动变速器系统模型(图20)来测量仿真时间性能改进。

simulink仿真

图20:某自动变速器系统的 Simulink 模型 为了提高性能,我们首先使用 Performance Advisor 运行检查,并提出以下建议更改:

禁用了检查求解器数据不一致、按奇异矩阵除法、Inf NaN 块输出、仿真范围检查和超出数组边界等代价较高的诊断项

将解释执行的 MATLAB Function 块替换为 MATLAB functions(此更改具有最大的单一效果)。

启用 Block reduction 优化

关闭并注释掉 Scope

这些变化将仿真时间从平均 57 秒减少到 3.3 秒。使用优化的模型,我们现在可以应用快速加速和并行仿真来比较这些技术的性能(表2)。  

原始模型,正常模式,串行执行,快速重启 5731 秒
改进模型,正常模式,串行执行,快速重启 328 秒
改进模型,正常模式,串行执行,快速重启 307 秒
改进模型,快速加速模式,串行执行,带 RapidAcceleratorUpToDateCheck Off 236 秒
改进模型,正常模式,并行仿真,快速重启(4 个 worker) 198 秒
改进模型,快速加速模式,并行仿真,与 RapidAcceleratorUpToDateCheck Off (4 个 worker) 85 秒
 

表 2:Time for 100 iterations of each model for 2000 seconds of simulation time. System used: Lenovo T490s with Intel Core i7-8665U CPU (1.9 GHz, 2112 MHz, 4 Cores), 32 GB DDR4 2400 MHz PC4-19200 SODIMM, Drive: 1 TB SSD, Windows 10 Enterprise, MATLAB R2022a.








审核编辑:刘清

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分