13

Mathematica 中有一个奇怪的错误已经存在多年,至少从 5.1 版开始,并且一直持续到 7 版。


Module[{f, L}, L = f[];
  Do[L = f[L, i], {i, 10^4}]] // Timing
  {0.015,空}
Module[{weirdness, L}, L = weirdness[];
  Do[L = weirdness[L, i], {i, 10^4}]] // Timing
  {2.266,空}

  • 这是什么原因造成的?是哈希问题吗?

  • 它在版本 8 中修复了吗?

  • 除了测试之外,有没有办法知道哪些符号名称会导致减速?

4

2 回答 2

19

这是什么原因造成的?是哈希问题吗?

是的,或多或少。

它在版本 8 中修复了吗?

是的(或多或少)。也就是说,不可能在任何“完整”意义上进行修复。但最常见的情况处理得更好。

除了测试之外,有没有办法知道哪些符号名称会导致减速?

我不知道的任何方式。

在第 7 版中,有一个与第 8 版中类似的早期修复程序。默认情况下它是关闭的(我们在发布时没有足够的时间对其进行测试,并且在 7.0.0 版中没有启用它。 1)。可以按如下方式访问。

SetSystemOptions["NeedNotReevaluateOptions"->{"UseSymbolLists"->True}];

这使您的示例回到了合理的领域。

Module[{weirdness, L}, L = weirdness[];
  Do[L = weirdness[L, i], {i, 10^4}]] // Timing

输出[8]= {0.020997,空}

- -编辑 - -

我可以更详细地解释这里涉及的优化。首先回想一下,Mathematica 模拟“无限求值”,也就是说,表达式不断求值,直到它们不再改变。这可能代价高昂,因此需要仔细优化短路以在可能的情况下阻止它。

我们使用的一种机制是散列的变体,它用于指示表达式可能依赖的符号未更改,因此该表达式未更改。在这里可能会发生碰撞,因此需要做更多的工作。

在不好的情况下,Mathematica 内核可能需要遍历整个表达式以确定它没有改变。这种步行可能与重新评估一样昂贵。版本 7 的新优化(如上所述)是针对某些类型的表达式显式记录它所依赖的那些符号。然后可以通过简单地检查自上次评估表达式以来没有更改过这些符号来缩短重新评估检查。

实现细节有点复杂(也有点专有,虽然可能不那么难猜)。但简而言之,这就是幕后发生的事情。早期版本有时会进行重要的表达式遍历,只是为了发现表达式不需要重新计算。这仍然可能发生,但现在它是一个更加罕见的事件。

---结束编辑---

Daniel Lichtblau Wolfram 研究

于 2011-03-23T16:19:41.370 回答
10

至于版本 8:我尝试了 100,000 个不同长度的随机字符串,没有发现任何异常。

chars = StringCases[CharacterRange["A", "z"], WordCharacter] //Flatten;
res = Table[
       ToExpression[
        StringReplace[
         "First[AbsoluteTiming[Module[{weirdness,L},L=weirdness[];\
    \[IndentingNewLine]Do[L=weirdness[L,i],{i,10^4}]]]]", 
         "weirdness" -> 
          StringJoin[
           RandomChoice[chars, RandomInteger[{1, 20}]]]]], {100000}];

在此处输入图像描述

于 2011-03-23T10:35:33.027 回答