如果同一子表达出现在一个 numexpr 表达式中的多个位置中,是否会被多次重新计算(或者数字足够聪明,可以检测到这一点并重复使用结果)?
有什么方法可以在数字表达式中声明临时变量?这将有两个目标:
- 鼓励NumExpr考虑缓存和重新利用而不是重新计算结果;
- 简化表达式(使源代码易于阅读和维护)。
我正在尝试计算 f(g(x))其中 f 和 g 本身都是复杂的表达式(例如,对于像素 - 基于主题分类, f 是涉及多个阈值的嵌套决策树, g 是一组归一化的差异比例,而 x 是多个频段栅格图像)。
是的,如果在数字表达式中重复一个子表达,则不会重新计算。
可以通过用numexpr.evaluate(expr)
替换numexpr.disassemble(numexpr.NumExpr(expr))
来验证这一点。
例如,表达式"where(x**2 > 0.5, 0, x**2 + 10)"
被编译为以下类型
y = x*x
t = y>0.5
y = y+10
y[t] = 0
(注意乘法仅出现一次,而不是两次。)
因此,最好将整个计算作为单个数字表达输入。避免在Python中执行子计算(将中间结果或临时变量分配到Numpy阵列中),因为这只会增加内存使用情况并破坏Numexpr的优化/加速度(这与执行CPU-CACHE大小块中的完整计算序列有关内存延迟)。
尽管如此,可以使用字符串替换来格式化更可读的代码:
f = """where({g} > 0.5,
0,
{g} + 10)"""
g = "x**2"
expr = f.format(g=g)