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