2011-11-30 57 views
15

我正在编码基于Ukkonen的算法在Mathematica中构建后缀树的算法。传递大量数据的变量是否会在Mathematica中花费大量内存和时间?

我的问题是,将我的整个树结构(我已经存储在一个列表中)传递给一个函数进行搜索,耗费我的程序大量的内存和时间,因为我必须使用一些函数在算法中多次?

例如,我有搜索特定节点的子功能,我用的是Select功能来搜索整个树。

getChildren[parentID_] := Select[tree, #[[3]] == parentID &]; 

但是我需要访问树,所以将整个树结构传递给函数是合理的吗?因为似乎没有办法在整个笔记本上创建一个可变的全局变量。还是有一些替代方法来解决这个问题?

+4

你说的意思是“有没有办法让一个变量全局到整个笔记本“?如果你定义了'tree = 5',那么在'Global'上下文中(这是默认的),'tree'是无处不在的。默认情况下它是全局的,除非你在其他行为之后。 – acl

回答

23

不,它不花费额外的内存通过表情。正如通常的函数式语言一样,Mathematica对象是immutable:它们不能被修改,而是在使用某些函数转换它们时创建一个新对象。这也意味着如果你不转换它们,不管它们在函数之间传递多少,它们都不会被复制。


从用户的角度来看,数学表达式树,但我相信,在内部它们存储为directed acyclic graphs,即相同的子表达式可以在内存中存储的只有一次,不管有多少次出现在完整的表达(参见例如Share[]的文档页面)。

下面是一个例子来说明:

首先,确保In/Out不占用额外的内存:

In[1]:= $HistoryLength = 0; 

查看内存使用情况:

In[2]:= MemoryInUse[] 
Out[2]= 13421756 

让我们的表达占用大量内存:

In[3]:= s = [email protected][1000000]; 

In[4]:= MemoryInUse[] 
Out[4]= 17430260 

现在重复这个表达式一百遍......

In[5]:= t = ConstantArray[s, 100]; 

...并注意内存的使用情况几乎没有增加:

In[6]:= MemoryInUse[] 
Out[6]= 18264676 

ByeCount[]是误导,因为它不报告的实际物理内存使用,但将用于如果公共子不允许共享相同的内存内存:

In[7]:= ByteCount[t] 
Out[7]= 400018040 

有趣的一点要注意:如果你从s删除f[...],并且使双方st一个普通的数字阵列,那么这个内存共享不会发生,和内存使用率会跳转到〜400 MB。


无论你做tree一个全局变量或getChildren的说法,它不会使内存使用情况的差异。

+4

优秀的答案!为了进一步确认你描述的图片,一个 可以对't'中的某个元素进行赋值,例如:'t [[1,1,1]] = 2; ',并且注意到与单个'''实例的大小相对应的内存消耗的直接跳跃。你用数值数组观察的原因很微妙:这是* only *,因为'Range'产生打包数组,*和*你使用了'ConstantArray'(而不是'Table')。重点是,'ConstantArray'将从一个压缩数组中产生一个压缩数组,并且你不能在一个大的压缩数组中共享内存,因为它是......基于直接C存储器布局的... –

+1

...。你应该使用''ur = Developer'FromPackedArray [Range [1000000]]; t = ConstantArray [ur,{100}]''或'r = Range [1000000]; t = Table [r,{100}];',你会观察到相同的内存共享,因为结果没有打包(这意味着有中间指针,共享是可能的 - 至少这是我此刻的图片)。 –

+0

我会稍微改变关于不变性的陈述,例如:“除非将它们存储在变量中,否则不能修改它们” - Mathematica不是纯粹的函数式语言,并且可能存在可变性。 –

4

继索博回答,如果你确实需要修改数据时,你可能会发现在传递通过引用有用的这个问题:

simple question on passing data between functions

+1

既然你提出了这个话题,让我来提一下,虽然接受的答案可以工作,我通常建议不要在程序设计的角度以这种方式使用'Unevaluated':应该设计自包含的函数,而函数只有在用户不忘记将“未评估”而且,这个功能本身也没有办法解决这个问题。在这种情况下,IMO,Hold-attributes强烈倾向于“未评估”。 –

+0

@ Leonid - 我改变了链接来引用你的答案。 (这是我的第一个意图。) –

+0

谢谢,但我的答案也没有一般性建议 - 这个问题受到CDF限制的限制,其中明确的Hold属性不能附加到符号。显然,现在还没有人在SO上提出过一个简单的问题,题目是“Mathematica中的Pass-by-Reference”(或者至少我是这样认为的),而对这样的话题进行SO讨论似乎是非常理想的。 –

相关问题