我正在使用 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;
}
很明显,对于这个小函数来说,这种替换并没有什么返回,但总的来说,这是让我为更大的函数工作的唯一方法。所以我的问题是,是否有任何简单的内置选项可以实现这种行为?对我来说最重要的部分是将计算分成小步骤。我想可以通过一些字符串替换例程来完成替换。
最佳答案
您很可能想要执行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 目前正在重构代码打印机:https://github.com/sympy/sympy/pull/7823
关于python - 简化使用 sympy codegen 生成的表达式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25309580/