这是什么造成的?这是哈希问题吗?
是的,或多或少。
在第8版中,它是否已被修复?
是的(或多或少)。也就是说,它无法被完全修复。但是最常见的情况得到了更好的处理。
除了测试之外,还有其他方法可以知道哪些符号名称会导致减速吗?
我不知道其他的方式。
在版本7中,有一种类似于版本8中的早期修复方法。默认情况下它是关闭的(当我们发货时,我们没有足够的时间测试它,并且它在版本7.0.1中没有被打开)。您可以按照以下步骤访问它。
SetSystemOptions["NeedNotReevaluateOptions"->{"UseSymbolLists"->True}]
这将使您的示例回到合理的范畴。
Module[{weirdness, L}, L = weirdness[]
Do[L = weirdness[L, i], {i, 10^4}]] // Timing
Out[8]= {0.020997, Null}
---edit---
这里稍微详细地解释一下所涉及的优化。首先需要记住的是,Mathematica模拟“无限评估”,也就是说,表达式会不断评估直到它们不再改变。这可能会很耗时,因此需要仔细的短路优化来尽可能地避免。
我们使用的机制是哈希的一种变体,用于指示可能依赖于表达式的符号未更改,因此表达式未更改。这里可能会发生冲突,从而需要更多的工作。
在糟糕的情况下,Mathematica内核可能需要遍历整个表达式才能确定它是否未更改。这种遍历的成本可以与重新评估一样昂贵。版本7中引入的一项优化(如上所述)是明确记录某些类型的表达式依赖的符号。然后,只需检查自上次评估表达式以来这些符号是否已更改,就可以缩短重新评估检查的时间。
实现细节有点复杂(也有点专有,但也许不难猜到)。但总之,这就是底层发生的事情。早期版本有时需要对表达式进行重大遍历,只是为了发现表达式不需要重新评估。现在这种情况仍然可能发生,但它现在是一种更为罕见的事件。
Daniel Lichtblau
Wolfram Research
---end edit---