技术文章和通讯

从MATLAB生成C代码的乐趣

比尔·周(Bill Chou), MathWorks


几十年来,工程师们一直在使用编译器将像C这样的低级语言翻译成机器码。但是否有可能翻译一种高级语言,如MATLAB®用C语言编写代码?大多数工程师都同意这在理论上是可能的,但在实践中可行吗?生成的代码是可读的还是乱七八糟的?有效或浮肿吗?快或慢吗?它支持工业工作流程,还是万博1manbetx仅仅支持研发?

本文将直面这些问题。它提供了使用MATLAB Coder™的技巧和最佳实践,以及Delphi、贝克休斯、iSonea和dorsaVi等公司成功应用生成代码的行业实例。

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

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

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

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

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

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

推荐的三步迭代工作流

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

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

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

图2.左:代码生成不支持的特性和功能的自动检查。右:输入数据类型和大小的自动分析和建议。万博1manbetx

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

实施约束

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

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

让我们进一步研究多态性。多态可以根据您的输入给一行MATLAB代码不同的含义。例如,图3中显示的函数可能意味着标量乘法、点积或矩阵乘法。此外,您的输入可以是不同的数据类型(逻辑、整数、浮点、定点),它们可以是实数或复数。

图3.多态性示例。

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

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

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

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

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

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

行业成功案例

  • 贝克休斯的动力学与遥测组根据序列预测算法生成一个DLL,并将其集成到PC上运行的地面解码软件中,从而在钻井作业中快速、可靠地解码井下数据。
  • dorsaVi从运动分析算法生成C++代码,并将其编译成动态链接库,然后将其集成到PC上运行的C应用程序中,该程序分析运动员的运动以诊断损伤。

  • VivaQuant根据心率监测算法生成定点C代码,并编译为ARM Cortex-M处理器。
  • 特尔斐生成了一个汽车雷达传感器对准算法的C语言代码,并在ARM10处理器上进行了编译。
  • 呼吸根据声呼吸监测算法生成C代码,并将其编译为iPhone应用程序、Android应用程序和基于云的服务器软件。

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

在MATLAB中,-迭代相互独立的循环可以通过替换具有parfor. MATLAB编码器使用开放式多处理(OpenMP)应用程序接口来支持共享内存,从万博1manbetxparfor循环。OpenMP受到许多C编译器万博1manbetx(例如Microsoft)的支持®Visual Studio®专业的)。

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

测试生成的代码

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

一个自动化的工作流

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

文章刊登在MathWorks新闻和笔记

发布于2016 - 92987v00