一直以来,工程师都手工编写C语言实现算法再通过编译器编译为机器代码。能否使用编码器将MATLAB这样的高级语言翻译成C语言?大多数工程师认为这是可行的——理论来说。
但实际上是否可行?
生成的代码是可读性如何?效率如何?执行速度如何?
面向工业流程或只是处于研发阶段?
MATLABCoder的使用技巧和最佳实践可以直接回答以上问题,这里还将分享行业将MATLAB生成C代码的成功经验和应用案例(包括Delphi、BakerHughes、iSonea、dorsaVi等)。
-对比MATLAB和C代码-
以下面这个简单的MATLAB乘法函数为例。
functionc=myMult(a,b)
%Multiplytwoinputs
c=a*b;
给定标量输入,MATLABCoder可以生成下面的C代码:
#include"myMult.h"
doublemyMult(doublea,doubleb)
{
returna*b;
}
正如所见,生成的代码清楚地与MATLAB代码相映射。
同样的MATLAB代码,当给定两个矩阵输入时,在生成的C代码中会包含三层嵌套的for循环:
#include"myMult.h"
voidmyMult(constdoublea[12],constdoubleb[20],doublec[15],)
{
inti0;
inti1;
inti2;
for(i0=0;i0< 3; i0++) {
for(i1=0;i1< 5; i1++) {
c[i0+3*i1]=0.0;
for(i2=0;i2< 4; i2++) {
c[i0+3*i1]+=a[i0+3*i2]*b[i2+(i1<< 2 )];
}
}
}
}
推荐!
-三步迭代工作流程-
上述简单的函数可以在一个步骤中实现。但是对于更多的实际项目来说,我们推荐使用三步迭代工作流程的结构化方法:
准备好需要生成代码的算法。检验并修改MATLAB代码来引入生成C代码的要素,使用支持代码生成的MATLAB语言和函数。
使用默认设置测试MATLAB代码生成时的可读性。通过生成并执行MEX文件来检查运行中的错误。如果运行成功,则进行下一步。如果不成功,则重复第一步直到能生成一个MEX函数。
生成C代码或保留第二步的MEX函数。你可以通过迭代MATLAB代码来优化生成的C代码(外观、内存和速度)或MEX函数(性能)。
MATLABCoderapp会引导你在MATLAB环境中完成这一迭代过程:
分析你的MATLAB代码,提供输入数据的类型和大小
生成一个MEX函数,测试你的MATLAB代码是否准备好
执行MEX函数,检查运行错误
等效的命令行函数提供同样的功能,因此你可以生成代码作为脚本或函数的一部分。
左:自动检测不支持代码生成的特征和函数。
右:自动分析和建议输入数据的类型和大小。
-实际生成代码的限制-
当你准备好代码生成的MATLAB算法时,你需要考虑到MATLAB和C代码的差别导致的限制,包括:
内存分配。在MATLAB中,内存分配是自动的。在C代码中,内存分配则是手动的——可以是静态(static),动态(malloc),或者堆栈(局部变量)。
数组语言。MATLAB提供丰富的数组运算集,可以简化数值算法的代码。C代码则需要用明确的for循环表达同样的算法。
动态类型。MATLAB可以在运行时自动地确定数据类型和大小。C语言要求对所有变量和函数进行明确的类型声明。
多态性。MATLAB函数可以支持多种不同输入类型,而C语言要求固定的类型声明。在顶层,你必须明确预期的C函数声明。
这里详细说明多态性。多态性可以根据你的输入给一行MATLAB代码赋予不同的意义。例如,图中的函数可以表示标量乘法,向量点积,或者矩阵乘法。另外,你的输入可以是不同的数据类型(逻辑值,整形,浮点数,定点数),也可以是实数或复数。
MATLAB强大的算法开发环境体现于当你创建算法时,不需要考虑实现的具体细节。但是,对于等效的C代码,你不得不明确操作的含义。例如上述案例,MATLAB代码可以被翻译成一行返回B*C的值的C代码:
doublefoo(doubleb,doublec)
{
returnb*c;
}
或者,它可以被翻译成11行由3层for循环组成的将两个矩阵相乘的C代码:
voidmyMult(constdoublea[12],constdoubleb[20],doublec[15],)
{
inti0;
inti1;
inti2;
for(i0=0;i0< 3; i0++) {
for(i1=0;i1< 5; i1++) {
c[i0+3*i1]=0.0;
for(i2=0;i2< 4; i2++) {
c[i0+3*i1]+=a[i0+3*i2]*b[i2+(i1<< 2 )];
}
}
}
}
-多核代码生成和其他优化方法-
在MATLAB中,迭代过程互相独立的for循环可以简单地通过将for替换为parfor实现并行运行。MATLABCoder使用OpenMultiprocessing(OpenMP)应用程序接口来支持parfor循环中的共享内存和多核代码生成。OpenMP被很多C编译器(例如MicrosoftVisualStudioProfessional)支持。
你可以使用有EmbeddedCoder的MATLABCoder来进一步优化代码效率并定制生成的代码。EmbeddedCoder提供对生成的代码的函数、文件和数据的细粒度控制的优化。
例如你可以使用存储类来控制生成的代码中全局变量的声明和定义,并使用代码生成模板来自定义生成的代码中的横幅和注释。EmbeddedCoder还可以通过使用代码替换库来提高代码效率,代码替换库可以使用为ARMCortex-A和ARMCortex-M等流行的处理器而优化过的实现来替换某些运算符和函数。
-测试生成的代码-
在开发MATLAB算法时,你可以创建单元测试来验证算法是否能产生你预期的结果。使用MATLAB单元测试框架编写的测试可以被用于验证生成的代码的运行情况是否与MATLAB算法一致。使用EmbeddedCoder你可以结合SIL和PIL在测试生成的独立代码或库时实现单元测试的重用。
-自动化工作流程-
MATLABCoder保证了将MATLAB算法转换为C代码的自动化工作流程。这个工作流程可以花费更少的时间编写和调试低C代码,而有更多的时间用于开发、测试和调优设计。
通过MATLAB中的黄金参考,包括算法和测试平台,你可以更快地将算法移植到C代码中。MATLAB单元测试以及EmbeddedCoder的SIL和PIL测试框架等自动化工具,可以让你全面而系统地测试MATLAB代码和C代码。无论你是在传统的PC端,Web服务器,移动设备,还是嵌入式处理器上实现设计,MATLABCoder将帮助您更快地从MATLAB生成C代码,并减少手工错误。