【问题标题】:Simplify expression generated with sympy codegen简化使用 sympy codegen 生成的表达式
【发布时间】:2014-09-15 16:01:57
【问题描述】:

我正在使用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;
}

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

【问题讨论】:

    标签: python c sympy


    【解决方案1】:

    您很可能想要执行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 Requests 发送到 SymPy project。不过,请务必检查最新的主分支,因为 Jim Crist 目前正在重构代码打印机:https://github.com/sympy/sympy/pull/7823

    【讨论】:

    • 谢谢,所以 cse 可以帮助我减少子表达式,但是如何将它与 codegen 一起使用?即如果我在 codegen 之前使用 cse 我有很多新变量,我如何在 codegen 函数中定义这些变量?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多