遗传编程和Python的限制AST表达式LLVM JIT

简单介绍一下基本原理

所以,我正在写在C / C象征主义回归机++叫发光,其目的是对遗传编程文库的JIT(像Pyevolve例如)。The main rationale behind Shine is that we have today a lot of research on speeding Genetic Programming using GPUs (the GPU fever !) or any other special hardware, etc, however we don’t have many papers talking about optimizing GP using the state of art compilers optimizations like we have on clang, gcc, etc.

“热点”或消耗大量的CPU资源的今天遗传编程是每一个人的评价,以计算程序树健身的组件。这种评价往往是在每一组的“培训”的参数设置执行。假设你想的一样勾股定理一个表达式的符号回归,你有1.0的参数的线性空间,以1000.0以0.1步你有你的人口的每一个人(程序树)10.000的评价!

什么服务所做的是下面的图片描述:

它将基因编程引擎的个体转化为LLVM中间表示(LLVM汇编语言),之后它运行的改造经过LLVM的(这里是现代编译器的真正力量在GP背景下进入),然后将LLVM JIT优化的LLVM IR转换为本地代码的指定目标(X86和PowerPC等)。

你可以看到下面的Shine架构:

这种架构带来了遗传规划了很大的灵活性,可以为可能后来由LLVM支持的任何语言你的个人使用情况下写的功能,哪些事项服务是LLVM IR,你可以使用任何语言,LLVM支持然后使用由LLVM产生的IR,可以从C,C ++,Ada的,FORTRAN,d,等混合代码,并使用自己的函数作为遗传规划树的非末端节点。

服务仍是其发展较早,它看起来简单的想法,但我仍然有很多问题需要解决,像对JIT评估过程本身,而不是做呼叫从Python的使用JIT编译的树木ctypes的绑定。

在Python AST本身上进行遗传编程

在服务的发展,一个想法发生在我身上,我可以使用Python的限制抽象语法树(AST)作为一个遗传编程引擎个人表示,这样做的主要优点是灵活性和重用了很多东西的可能性。Of course that a shared library written in C/C++ would be useful for a lot of Genetic Programming engines that doesn’t uses Python, but since my spare time to work on this is becoming more and more rare I started to rethink the approach and use Python and the LLVM bindings for LLVM (LLVMPY我刚刚发现,使用LLVM将一组受限的Python AST JIT为本地代码是非常容易的,这就是这篇文章将要展示的内容。

JIT一个受限的Python AST

LLVM最令人惊奇的部分显然是通过的转换量、JIT,当然还有通过一个简单的API使用整个框架的能力(好吧,有时候并不那么简单)。为了简化这个示例,我将使用Python AST的一个受限AST集,它只支持减法(-)、加法(+)、乘法(*)和除法(/)。

要了解Python的AST,你可以使用Python解析器,转换成源AST:

>>>进口AST >>> ASTP = ast.parse( “2 * 7”)>>> ast.dump(ASTP)“模块(体= [Expr的(值= BinOp(左= NUM​​(N = 2),OP = MULT(),右= NUM​​(N = 7)))])”

什么是解析创建了包含抽象语法树BinOp二元运算)与左操作者数目2时,右操作者如数字7和操作本身作为乘法(Mult),很亚洲金博宝容易理解。为了创建LLVM IR,我们将创建一个访问树的每个节点的访问者。为此,我们可以子类化PythonNodeVisitor从类ast模块。What the NodeVisitor does is to visit each node of the tree and then call the method ‘visit_OPERATOR’ if it exists, when the NodeVisitor is going to visit the node for the BinOp for example, it will call the method ‘visit_BinOp’ passing as parameter the BinOp node itself.

JIT访问器的类结构如下所示:

#导入AST和LLVM进口* LLVM的Python绑定进口AST从llvm.core进口*从llvm.ee进口*进口llvm.passes作为LP级AstJit(ast.NodeVisitor):DEF __init __(个体经营):通

我们现在需要做的是创建一个初始化的方法来保持,这是需要的JIT访问者的最后一个状态,因为我们要JIT Python的AST成一个功能的内容和功能需要返回的最后一个指令什么是由JIT访问的最后一个指令的结果。We also need to receive a LLVM Module object in which our function will be created as well the closure type, for the sake of simplicity I’m not type any object, I’m just assuming that all numbers from the expression are integers, so the closure type will be the LLVM integer type.

DEF __init __(个体,模块,参数):self.last_state =无self.module =模组#参数,将在IR功能self.parameters =参数self.closure_type = Type.int()#的属性以保持被创建链接创建的函数#,所以我们可以用它来JIT后self.func_obj =无self._create_builder()高清_create_builder(个体经营):整数类型则params的#有多少参数= [self.closure_type] * LEN(self.parameters)#函数的原型,返回一个整数#和接收所述整数参数ty_func = Type.function(self.closure_type,则params)#添加的功能名称为“func_ast_jit” self.func_obj = self.module该模块。add_function(ty_func,“func_ast_jit”)#创建用于索引,PNAME在枚举指定的每个参数的函数的参数(self.parameters):self.func_obj.args [索引] = .NAME#PNAME创建一个基本块和助洗剂BB = self.func_obj.append_basic_block( “入口”)self.builder = Builder.new(BB)

现在,我们需要在访问者上实现的是BinOp并为全国矿工工会的名字运营商。我们还将实施创造了返回指令,将返回的最后状态的方法。

'Name'是在访问变量时在AST中生成的节点,如'2+x+y', 'x'和'y'是在AST中为表达式创建的两个名称。这个变量是什么函数参数?index = self。parameter .index(node.id) self。last_state = self.func_obj。args(指数)回归自我。这里我们使用# Num节点创建一个LLVM IR整数常数,在表达式'2+3'上有两个# Num节点,Num(n=2)和Num(n=3)。def visit_Num(self, node): self。last_state = Constant.int(self.closure_type, node.n)返回self获取操作的左右参数lhs = self.visit(node.left) rhs = self.visit(node.right) op = node。如果isinstance(op, as .Sub): op = self.builder,则将每个操作(Sub, Add, Mult, Div)转换为它们的# LLVM IR整数指令。sub(lhs, rhs, 'sub_t') elif isinstance(op, ast.Add): op = self.builder。添加(lhs, rhs, 'add_t') elif isinstance(op, ast.Mult): op = self.builder。if isinstance(op, ast.Div): op = self.builder。sdiv(lhs, rhs, 'sdiv_t') self。last_state = op返回self。使用最后一个状态def build_return(self)构建return(ret)语句:self。Build .ret(self。last_state)

这就是它,我们的客人准备一个Python AST转换为LLVM IR汇编语言编写,运行它,我们将首先创建一个LLVM模块和一个表达式:

模块= Module.new( 'ast_jit_module')#请注意,我使用两个变量 'A' 和 'b' EXPR =“(2 + 3 * B + 33 *(10/2)+ 1 + 3/3 +一)/ 2" 节点= ast.parse(表达式)打印ast.dump(节点)

将输出:

模块(体= [Expr的(值= BinOp(左= BinOp(左= BinOp(左= BinOp(左= BinOp(左= BinOp(左= NUM​​(N = 2),OP =添加(),右= BinOp(左= NUM​​(N = 3),OP = MULT(),右=名称(ID = 'b',CTX =负载()))),OP =添加(),右= BinOp(左= NUM​​(N =33),OP = MULT(),右= NUM​​(N = 2))),OP =添加(),右= NUM​​(N = 1)),OP =添加(),右= NUM​​(N = 3)),OP =添加(),右=名称(ID = 'A',CT​​X =负载())),OP =股利(),右= NUM​​(N = 2)))])

现在我们终于可以在生成的AST上运行我们的访问者,检查LLVM IR输出:

访问者= AstJit(模块,['a', 'b']

将输出LLVM IR:

;的moduleId = 'ast_jit_module' 限定I32 @func_ast_jit(I32%A,I32%B){条目:%mul_t = MUL I32 3,%B%add_t =添加I32 2,%mul_t%add_t1 =添加I32%add_t,165%add_t2=添加I32%add_t1,1个%add_t3 =添加I32%add_t2,1%add_t4 =添加I32%add_t3,%A%sdiv_t = SDIV I32%add_t4,2 RET I32%sdiv_t}

现在是真正的乐趣开始的时候,我们要运行LLVM优化过程具有同等GCC -02优化级别来优化我们的代码,要做到这一点,我们创建一个PassManagerBuilder和PassManager的PassManagerBuilder是增加了通行证组件PassManager,您也可以手动添加像死代码消除,内联函数等任意的变换:

PMB = lp.PassManagerBuilder.new()#优化级别pmb.opt_level =下午2点= lp.PassManager.new()pmb.populate(下午)#执行通入模块pm.run(模块)的打印模块

将输出:

;ModuleID = 'ast_jit_module'定义i32 @func_ast_jit(i32% %a, i32% %b) nounwind readnone {entry: %mul_t = mul i32% %b, 3% add_t3 = add i32% %add_t3, 169% add_t4 = add i32% add_t3, %mul_t %sdiv_t = sdiv i32% add_t4, 2 ret i32% sdiv_t}

这里我们有Python AST表达式的优化的LLVM IR。下一步是将该IR JIT到本地代码中,然后使用一些参数执行它:

EE = ExecutionEngine.new(模块)arg_a = GenericValue.int(Type.int(),100)= arg_b GenericValue.int(Type.int(),42)= RETVAL ee.run_function(visitor.func_obj,[arg_a,arg_b])打印 “返回值:%d” %retval.as_int()

将输出:

返回:197

就是这样,你已经创建了一个AST-> LLVM IR转换器,优化了LLVM IR与改造通行证,然后使用LLVM执行引擎它转换为本地代码。我希望你喜欢=)

引用本文为:基督教S. Perone,“遗传编程和Python的限制AST表达式LLVM JIT,”在亚洲金博宝未知领域,15/08/2012,//www.cpetem.com/2012/08/genetic-programming-and-a-llvm-jit-for-restricted-python-ast-expressions/

关于“限制Python AST表达式的遗传编程和LLVM JIT”的3个想法

  1. 非常不可思议的Christian,我同意这种方法对GP来说是有趣的,而且是对llvmpy的一个很酷的介绍。亚洲金博宝很好的工作!

发表评论

您的电子邮件地址将不会被公布。

这个网站使用Akismet来减少垃圾邮件。了解您的意见如何处理数据