numexpr:临时变量还是重复的子表达式?

时间:2017-02-23 03:54:27

标签: python numpy optimization refactoring numexpr

如果同一个子表达式出现在一个 numexpr 表达式中的多个位置,是否会多次重新计算(或者是否已经足够聪明地检测到并重复使用结果)?

有没有办法在numexpr表达式中声明临时变量?这有两个目标:

  1. 鼓励numexpr考虑缓存和重用,而不是重新计算结果;
  2. 简化表达式(使源代码更易于阅读和维护)。
  3. 我正在尝试计算 f(g(x))其中 f g 本身都是复杂的表达式(例如对于像素 - 基于主题分类, f 是一个涉及多个阈值的嵌套决策树, g 是一组归一化差异比, x 是多个波段光栅图像)。

1 个答案:

答案 0 :(得分:0)

是的,如果子表达式在numexpr表达式中重复,则不会重新计算。

可以将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缓存中执行此完整计算序列有关)大小的块来规避内存延迟。)

尽管如此,使用字符串替换可以格式化更易读的代码:

f = """where({g} > 0.5,
             0,
             {g} + 10)"""
g = "x**2"
expr = f.format(g=g)