【问题标题】:Optimizing Mathematica's main loop优化 Mathematica 的主循环
【发布时间】:2011-03-14 08:04:56
【问题描述】:

早安,

阅读此thread 关于Mathematica 中的模式匹配和函数的性能 我对Timo's idea 关于优化表达式的评估印象深刻:

我有时会构建一个 所有功能的调度表 I 需要并手动将其应用到我的 开始表达。这提供了一个 比正常速度显着增加 评估为非 Mathematica 的 需要解析内置函数 反对我的表达。

这样的Dispatch表究竟应该如何构造?在哪些情况下会推荐这种方法?它是如何工作的?是否有其他优化主循环的方法?

【问题讨论】:

  • 毫无疑问,@Timo 很快就会给出明确的答案,但是关于 Dispatch 的文档会在你等待的时候带来有趣的阅读;)
  • 我猜你已经看过 Parallel ComputingCompileGPU ComputingLightweight网格客户端
  • @belisarius 是的,当然。问题是关于优化标准 Mathematica 的主循环本身。它的灵感来自于 Timo 关于“与正常评估相比显着提高速度”的评论。

标签: optimization wolfram-mathematica


【解决方案1】:

为此,首先您需要能够计算符号的依赖关系。在 Mathematica Journal 的过刊中有一个包可以做到这一点,现在可以在线免费使用。这是网址:http://www.mathematica-journal.com/issue/v6i1/。请参阅文章“Power Programming:依赖分析”。

这是一个有效的例子:

In[1]:= <<"/path/to/DEPEND.MA"

In[2]:= $ContextPath

Out[2]= {DependencyAnalysis`,PacletManager`,WebServices`,System`,Global`}

In[3]:= f[x_]:=x x

In[4]:= g[x_]:=x+1

In[5]:= h[x_]:=f[x]+g[x]

In[6]:= i[x_]:=f[g[x]]

In[7]:= DependsOn[g][[2]]

Out[7]= {Blank,Pattern,Plus,x}

In[8]:= DownValues@@@DependsOn[g][[2]]

Out[8]= {{},{},{},{}}

In[9]:= getDownValues[s_Symbol]:=DownValues[s]

In[10]:= getDownValues[s_HoldForm]:=getDownValues@@s

In[11]:= getDownValues[s_]:={}

In[12]:= hasDownValues[x_]:=getDownValues[x]=!={} 

In[13]:= ruleListEntries[x_List]:=Union[Union@@ruleListEntries/@x,{x}]

In[14]:= ruleListEntries[x_]:=Select[Union[DependsOn[x][[2]],{x}],hasDownValues]

In[15]:= ruleListEntries[f]

Out[15]= {f}

In[16]:= ruleListEntries[g]

Out[16]= {g}

In[17]:= ruleListEntries[h]

Out[17]= {h,f,g}

In[18]:= ruleListEntries[i]

Out[18]= {i,f,g}

In[19]:= dispatch=getDownValues/@ruleListEntries[i]//Flatten//Union//Dispatch

Out[19]= {HoldPattern[f[x_]]:>x x,HoldPattern[g[x_]]:>x+1,HoldPattern[i[x_]]:>f[g[x]]}

In[20]:= i[x]

Out[20]= (1+x)^2

In[21]:= HoldForm[i[x]]//.dispatch

Out[21]= (x+1) (x+1)

我看不到获取内置符号的 DownValues 的方法,因此这仅在将表达式简化为仅包含内置符号的程度时才有用。

【讨论】:

  • 据我了解,这种方法可能只有在代码不包含递归定义的情况下才能正常工作?知道在哪些情况下这种方法有望显着提高性能会很有趣。
【解决方案2】:

这样的Dispatch表究竟应该如何构造?

假设您有一个由n 循环中的顶点组成的图(网络):

In[1] := rules =
           With[{n = 1000},
             Table[ToString@i -> ToString@Mod[i + 1, n],
               {i, 0, n - 1}]];

您希望通过将这些重写规则应用于初始顶点来遍历图形。您可以使用i /. rules 执行单个步骤,但这是对rules 进行线性搜索,试图找到具有与表达式i 匹配的lhs 的Rule。所以多次应用规则很慢:

In[2] := Nest[# /. rules &, 0, 10000] // AbsoluteTiming

Out[2] = {1.7880482, 0}

Mathematica 的 Dispatch 允许我们预先计算一个哈希表,将线性查找转换为常数时间查找:

In[3] := dispatch = Dispatch[rules];

多次应用调度表获得相同答案的速度要快几个数量级:

In[4] := Nest[# /. dispatch &, 0, 10000] // AbsoluteTiming

Out[4] = {0.0550031, 0}

在哪些情况下会推荐这种方法?

时间:

  • 您正在使用相同的重写规则集进行多次重写,并且

  • 重写规则集包含至少 30 条具有恒定 lhs 模式的规则,即仅由符号、序列和文字组成。

它是如何工作的?

它只是构建一个以常量模式作为键的哈希表。

还有其他优化主循环的方法吗?

最有效的通用方法是用另一种语言重写规则。特别是 ML 系列语言(SML、OCaml 和 F#)具有非常高效的模式匹配编译器和垃圾收集器,因此它们能够比 Mathematica 的通用重写器更快地重写术语。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-20
    • 1970-01-01
    相关资源
    最近更新 更多