技术文章及通讯

从MATLAB生成C代码的乐趣

作者:Bill Chou, MathWorks


几十年来,工程师们一直在使用编译器将C等低级语言翻译成机器代码。但是有可能翻译像MATLAB这样的高级语言吗®使用编码员到C语言?大多数工程师都同意这在理论上是可行的,但在实践中可行吗?生成的代码是可读的还是面条?高效还是臃肿?快还是慢?它支持工业工作流程,还是金宝app只支持研发?

本文将正面解决这些问题。它提供了使用MATLAB Coder™的技巧和最佳实践,以及由Delphi、Baker Hughes、iSonea和dorsaVi等公司成功应用生成代码的行业示例。

本文中的代码示例可用于下载。

比较MATLAB和C代码:一个乘法的例子

下面这个简单的MATLAB函数将两个输入相乘。

给定标量输入,MATLAB Coder生成以下C代码:

如您所见,生成的代码清楚地映射回MATLAB代码。

同一段MATLAB代码,当给定两个矩阵输入时,生成三个嵌套的矩阵C中的-loops:

推荐的三步迭代工作流

上面所示的简单函数可以在一个步骤中实现。但是对于更实质性的项目,我们建议使用一个结构化的方法,使用一个三步迭代工作流(图1):

  1. 为代码生成准备算法。检查和修改MATLAB代码,以介绍低级C代码所需的实现注意事项,并使用MATLAB支持的语言和函数金宝app代码生成。
  2. 使用默认设置测试MATLAB代码对代码生成的准备情况。通过生成并执行MEX文件检查运行时错误。如果成功,执行下一步。如果没有,请重复步骤1,直到可以生成MEX函数。
  3. 生成C代码或保留步骤2中的MEX函数。您可以迭代MATLAB代码以优化生成的C代码(为了观感、内存和速度)或MEX函数(为了性能)。
图1。用于生成代码的三步迭代工作流。

MATLAB Coder应用程序指导您完成这个迭代过程,同时使您能够留在MATLAB环境中。它分析您的MATLAB代码,为您的输入提出数据类型和大小。它通过生成MEX函数来测试您的MATLAB代码是否已准备好进行代码生成,然后执行MEX函数以检查运行时错误(图2)。等效的命令行函数提供相同的功能,因此您可以将代码作为脚本或函数的一部分生成。

图2。左:自动检查代码生成不支持的特性和函数。金宝app右:输入数据类型和大小的自动分析和建议。

下面的视频用一个生成卡尔曼滤波器来预测弹跳球的轨迹的例子说明了这些步骤。您将看到,三步迭代过程使我们能够生成与原始MATLAB结果紧密匹配的代码,并满足其跟踪要求。

实现约束

在为代码生成准备MATLAB算法时,需要考虑由于MATLAB和C代码之间的差异而导致的实现约束。这些包括:

  • 内存分配。在MATLAB中,内存分配是自动的。在C代码中,内存分配是手动的——它是静态分配的(使用静态),动态(使用malloc),或者在堆栈上(使用局部变量)。
  • 基于数组的语言。MATLAB提供了一组丰富的数组运算,允许对数值算法进行简洁的编码。C代码要求显式-loops来表达相同的算法。
  • 动态类型。MATLAB在代码运行时自动确定数据类型和大小。C要求对所有变量和函数进行显式类型声明。
  • 多态性。MATLAB函数可以支持许多不同的输入类型金宝app,而C需要固定的类型声明。在顶层,必须指定预期的C函数声明。

让我们仔细看看多态性。多态性可以根据您的输入赋予单行MATLAB代码不同的含义。例如,图3中显示的函数可以表示标量乘法、点积或矩阵乘法。此外,您的输入可以是不同的数据类型(逻辑、整数、浮点、定点),它们可以是实数或复数。

图3。多态性的例子。

MATLAB是一个强大的算法开发环境,因为在创建算法时不需要担心实现细节。然而,对于等效的C代码,您必须指定操作的含义。例如,上面显示的MATLAB代码行可以转换为返回B*C的单行C代码:

或者,它可以被翻译成11行C代码两个矩阵相乘的-循环:

下面的视频使用Newton-Raphson算法来说明考虑实现约束的概念。您将看到使用三步迭代工作流生成的代码与原始的MATLAB结果完全匹配。

使用生成的代码:四个用例

使用MATLAB Coder从MATLAB算法生成可读和可移植的C/ c++代码后,您有几个使用它的选项。例如,你可以:

  • 将MATLAB算法作为源代码或库集成到更大的软件项目中,例如在pc和服务器上运行的自定义模拟器或软件包(观看视频4:17)
  • 在嵌入式处理器(如ARM)上实现和验证MATLAB算法®处理器和移动设备(观看视频(0:26))
  • 将您的MATLAB算法原型化为pc上的独立可执行文件(观看视频2:57)
  • 通过生成调用编译后的C/ c++代码的MEX函数,加速MATLAB代码的计算密集型部分(观看视频4:21)

行业成功故事

  • 贝克休斯的动力学和遥测组通过序列预测算法生成DLL,并将其集成到PC机上运行的地面解码软件中,可以在钻井作业期间快速可靠地解码井下数据。
  • dorsaVi从运动分析算法生成c++代码,并将其编译成一个DLL,然后集成到他们在PC上运行的c#应用程序中,分析运动员的动作以诊断损伤。

  • VivaQuant从心律监测算法生成定点C代码,并将其编译到ARM Cortex-M处理器上。
  • 特尔斐生成了汽车雷达传感器对齐算法的C代码,并将其编译到ARM10处理器上。
  • Respiri从声学呼吸监测算法生成C代码,并将其编译为iPhone应用程序、Android应用程序和基于云的服务器软件。

多核代码生成及其他优化方法

在MATLAB中,-loops的迭代彼此独立,可以通过简单地替换并行运行parfor.MATLAB Coder使用开放多处理(OpenMP)应用程序接口来支持共享内存,多核代码生成金宝appparfor循环。OpenMP被许多C金宝app编译器所支持(例如,Microsoft®Visual Studio®专业)。

您可以使用MATLAB编码器与嵌入式编码器®为了进一步优化代码效率和定制生成的代码。嵌入式Coder提供了对生成代码的函数、文件和数据进行细粒度控制的优化。例如,你可以使用存储类在生成的代码中控制全局变量的声明和定义,并使用代码生成模板在生成的代码中自定义横幅和注释。嵌入式Coder还通过使用代码替换库来提高代码效率,这些替换库将某些操作符和函数替换为为流行处理器优化的实现,如手臂皮层®——一个而且手臂Cortex-M

测试生成的代码

在开发MATLAB算法时,可以创建单元测试来验证算法是否产生了预期的结果。使用MATLAB单元测试框架可以重复使用,以验证生成的代码与MATLAB算法的行为相同。下面的视频展示了如何将嵌入式Coder中的单元测试与生成的独立代码或库上的软件在循环(SIL)和处理器在循环(PIL)测试结合起来重用(图4)。

自动化的工作流程

MATLAB Coder实现了将MATLAB算法转换为C代码的自动化工作流。有了这个工作流,您可以花更少的时间编写和调试低级C代码,而花更多的时间开发、测试和调优设计。通过在MATLAB中维护一个黄金参考,包括算法和测试工作台,您可以更快地将算法更改传播到C代码中。自动化工具,如MATLAB单元测试框架和嵌入式Coder SIL和PIL测试框架,可以让您彻底而系统地测试MATLAB代码和C代码。您是否正在实现运行的设计传统的个人电脑,web服务器,移动设备,或嵌入式处理器, MATLAB Coder将帮助您更快地从MATLAB到C代码,并减少手动翻译错误。

文章刊登于MathWorks新闻与笔记

发布2016年- 92987v00