将Julia函数转换为C代码
在这个例子中,我们将演示一种技术,它允许您从Julia中创建的函数生成C代码。
任务说明
让我们假设我们在Julia上有代码,我们想迁移到另一个平台,我们在平台上编译代码不方便。 例如,在微控制器上。 与此同时,保持在Engee内部的模型循环中运行相同代码的能力会很好。 我该怎么办?
让我们使用多态机制。 您可以将数字输入代码,然后它将为您执行并计算数字结果。 你可以提交矩阵,那么结果将是一个矩阵。 让我们输入符号变量,看看会发生什么。
Pkg.add( "Symbolics" )
从简单函数生成代码
考虑从一个非常简单的函数生成代码,该函数返回一个数字。:
simple_fcn(x1, x2) = 2 .* x1 + sin( x2 )
simple_fcn(1, 2)
让我们在全局级别声明两个变量 x1 和 x2,用它可以执行符号操作。
using Symbolics
@variables x_1 x_2
如果我们将符号变量替换为简单函数的参数,我们就不会看到任何不寻常的东西(除了我们会看到嵌入在函数中的方程):
simple_fcn( x_1, x_2 )
但另一方面,我们将得到一个结构良好的对象,我们可以从中生成代码。:
c_model_code = build_function( simple_fcn( x_1, x_2 ), [x_1, x_2]; target=Symbolics.CTarget(), fname="SIMPLE_FCN", lhsname=:c, rhsnames=[:x] )
println( c_model_code )
我们收到了针对特定"目标"优化的代码。 CTarget.
此代码可能需要各种改进。 例如,转换为类型 float 或更改函数名(exp 上 expf),以满足您的平台中使用的标准的要求。 或添加功能 main.
然后可以将此代码保存到文件中。 simple_function.c,用命令编译 gcc -o out simple_function.c -lm.
c_code_standalone = """
#include <stdio.h>
$c_model_code
int main(int argc, char const *argv[]){
double out[1];
double in[] = {1, 2};
SIMPLE_FCN( out, in );
printf( "%f\\n", out[0] );
return 0;
}""";
# Сохраняем в файл доработанный код
open("$(@__DIR__)/simple_function.c", "w") do f
println( f, "$c_code_standalone" )
end
编译生成的代码:
;gcc -o out simple_function.c -lm
并检查生成的二进制文件输出与原始函数相同的值。:
;./out
simple_fcn(1, 2)
结果与我们在示例开始时计算的结果相同。
结论
我们在Julia上为一个非常简单的函数生成了代码,在Engee中编译并执行它,或者我们可以把它放在一个块中。 C Function 以简化半自然测试。
值得注意的是,并非每个代码都可以通过这种方法轻松地翻译成C代码,通常需要显着更改翻译过程,以便允许代码接受矩阵作为输入。 但是通过这种方式,可以生成一个相当大的算法子类,这些算法在半自然模拟场景中很有用。