技术文章和通讯

从MATLAB生成C代码的乐趣

比尔·周(Bill Chou), MathWorks


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

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

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

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

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

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

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

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

推荐的三步迭代工作流

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

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

MATLAB编码器应用程序指导您通过这个迭代过程,同时使您停留在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代码可以转换为这一行C代码,返回B*C:

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

下面的视频使用牛顿-拉夫森算法来说明考虑实现约束的概念。您将看到使用三步迭代工作流生成的代码与原始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++代码,并将其编译成一个DLL,然后将其集成到运行在PC上的c#应用程序中,分析运动员的运动以诊断损伤。

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

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

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

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

测试生成的代码

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

一个自动化的工作流

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

文章刊登在MathWorks新闻和笔记

发布于2016 - 92987v00