同情 CSE:避免 pow/powf [英] sympy CSE: avoid pow/powf

查看:26
本文介绍了同情 CSE:避免 pow/powf的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当Sympy生成C代码时,有没有办法对表达式中的 pow(或 powf)出现强制执行 CSE 优化?

例如这个代码片段

c, s = 符号('c s')myexpr = c**6/1800 - c**5/100 - 0.00833333333333333*c**4*s**2 + 19*c**4/200 + 0.1*c**3*s**2 - 9*c**3/20 + c**2*s**4/120 - 0.57*c**2*s**2 + 43*c**2/40 - c*s**4/20 +1.35*c*s**2 + 23*c/50 - 0.000555555555555556*s**6 + 19*s**4/200 - 1.075*s**2 - 2107/1800进口同情从 sympy.codegen.ast 导入实数,float64sub_exprs,final_expr = sympy.cse([myexpr])对于 var,expr in sub_exprs : print "const real",printing.ccode(expr, standard='C99',assign_to=var, type_aliases={real: float64})打印返回",printing.ccode(final_expr[0], standard='C99', type_aliases={real: float64}),";"

产生以下令人失望的输出:

const real x0 = pow(c, 2);const real x1 = pow(c, 3);const real x2 = pow(c, 4);const real x3 = pow(s, 2);const real x4 = pow(s, 4);回报 (1.0/1800.0)*pow(c, 6) - 1.0/100.0*pow(c, 5) + 1.3500000000000001*c*x3 - 1.0/20.0*c*x4 + (23.0/50.0.050505055950559p59)(s, 6) - 0.56999999999999995*x0*x3 + (1.0/120.0)*x0*x4 + (43.0/40.0)*x0 + 0.1000000000000001*x1*x3/x30*39.39*39*30*39/200.0)*x2 - 1.075*x3 + (19.0/200.0)*x4 - 2107.0/1800.0 ;

Pow 优化已被完全忽略.

对此有什么解决方法?

备注:我看到在这里部分提到了这个问题:在许多情况下,代码打印机不会打印最佳代码.一个例子是 C 中的幂.x**2 打印为 pow(x, 2) 而不是 x*x.其他优化(如数学简化)应该发生在代码打印机之前."

解决方案

sympy 中的 CSE 例程并不完美(改进的 CSE 是 列为有待改进的领域),例如:

<预><代码>>>>sympy.cse([x**4, x**3*y])([], [x**4, x**3*y])

在打印机中或在打印机之前扩展 pow 已经讨论过 一段时间后,现在有一个 create_expand_pow 可以帮助一些人的优化:

<预><代码>>>>expand_opt = create_expand_pow_optimization(3)>>>expand_opt(x**5 + x**3)x**5 + x*x*x

但是请注意,如果您向它们传递正确的优化标志,大多数编译器将已经生成最佳程序集(无论源代码中的 CSE).

When Sympy generates C code, is there a way to enforce CSE optimizations for pow (or powf) occurrences in an expression?

For example, this code snippet

c, s = symbols('c s')
myexpr = c**6/1800 - c**5/100 - 0.00833333333333333*c**4*s**2 + 19*c**4/200 + 0.1*c**3*s**2 - 9*c**3/20 + c**2*s**4/120 - 0.57*c**2*s**2 + 43*c**2/40 - c*s**4/20 + 1.35*c*s**2 + 23*c/50 - 0.000555555555555556*s**6 + 19*s**4/200 - 1.075*s**2 - 2107/1800
import sympy
from sympy.codegen.ast import real, float64
sub_exprs,final_expr = sympy.cse([myexpr])
for var,expr in sub_exprs : print "const real", printing.ccode(expr, standard='C99', assign_to=var, type_aliases={real: float64})
print "return ",printing.ccode(final_expr[0], standard='C99', type_aliases={real: float64}),";"

produces the following disappointing output:

const real x0 = pow(c, 2); 
const real x1 = pow(c, 3); 
const real x2 = pow(c, 4); 
const real x3 = pow(s, 2); 
const real x4 = pow(s, 4); 

return (1.0/1800.0)*pow(c, 6) - 1.0/100.0*pow(c, 5) + 1.3500000000000001*c*x3 - 1.0/20.0*c*x4 + (23.0/50.0)*c - 0.00055555555555555599*pow(s, 6) - 0.56999999999999995*x0*x3 + (1.0/120.0)*x0*x4 + (43.0/40.0)*x0 + 0.10000000000000001*x1*x3 - 9.0/20.0*x1 - 0.0083333333333333297*x2*x3 + (19.0/200.0)*x2 - 1.075*x3 + (19.0/200.0)*x4 - 2107.0/1800.0 ;

Pow optimizations have been completely ignored.

What is the workaround for this?

Remark: I saw that this issue is partially mentioned here: "The code printers don’t print optimal code in many cases. An example of this is powers in C. x**2 prints as pow(x, 2) instead of x*x. Other optimizations (like mathematical simplifications) should happen before the code printers."

解决方案

The CSE routine in sympy is not perfect (improved CSE is listed as an area for improvement), e.g.:

>>> sympy.cse([x**4, x**3*y])
([], [x**4, x**3*y])

Expanding pow in the printer or before the printer has been discussed some time, there is now a create_expand_pow optimization which can help some:

>>> expand_opt = create_expand_pow_optimization(3)
>>> expand_opt(x**5 + x**3)
x**5 + x*x*x

Note however that most compilers will already generate optimal assembly (regardless of CSE in the source code) if you pass them the right optimization flags.

这篇关于同情 CSE:避免 pow/powf的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆