简化用sympy codegen生成的表达式

时间:2014-08-14 13:44:32

标签: python c sympy

我正在使用sympy.utilities.codegen生成一些我用于数值计算的C代码。例如,生成的C函数看起来像这样:

double f(double x, double y, double z){
    return M_PI*sin(M_PI*x)*sin(M_PI*y) + sin(M_PI*y)*sin(M_PI*z);
}

所以一般来说我有更大的函数和更多的表达式,这对我的数值计算来说是个问题。由于我使用CUDA,因此我的计算寄存器数量减少了。我想要做的是将表达式拆分为较小的表达式,并进行一些替换,以便昂贵的计算只计算一次。以下是上述代码的示例。

double f(double x, double y, double z){
    double sinx = sin(M_PI*x);
    double siny = sin(M_PI*y);
    double sinz = sin(M_PI*z);
    double result;

    result  = M_PI*sinx*siny;
    result += siny*sinz;
    return result;
}

很明显,对于这些小功能而言,这种替换并没有得到回报,但总的来说,这是让我为更大的功能工作的唯一方法。所以我的问题是,是否有任何简单的内置选项来获得这种行为?对我来说最重要的部分是将计算分成小步骤。我想可以用一些字符串替换例程来完成替换。

1 个答案:

答案 0 :(得分:4)

您很可能想要执行common subexpression elimination。 在您的示例中,siny是唯一实际重用的表达式:

>>> expr = pi*sin(pi*x)*sin(pi*y) + sin(pi*y)*sin(pi*z)
>>> print(cse(expr))
([(x0, sin(pi*y))], [pi*x0*sin(pi*x) + x0*sin(pi*z)])

通常编译器应该已经进行了这些转换 - 至少如果您提出这些转换 忽略例如非关联性浮点乘法(通过传递例如-ffast-math)。我对nvcc没有任何经验。

如果您在使用codegen生成CUDA代码时遇到限制 - 请随时在其上进行改进,并将Pull请求发送到SymPy project。由于Jim Crist目前正在重构代码打印机,所以请务必检查最新的master分支:https://github.com/sympy/sympy/pull/7823