内存管理

MemoryInUse[]当前 Wolfram 系统所使用内存的字节数
MaxMemoryUsed[]在这个进程中 Wolfram 系统所使用内存的最大字节数

找出所用的内存.

特别是在符号运算中,内存是限制计算量的主要资源. 计算速度慢时,只要延长计算时间即可. 但是,如果一个计算产生的中间表达式不能放入内存时,就无法使计算继续下去.

Wolfram 系统使用内存时很仔细,每次当所产生的中间结果不再使用时,Wolfram 系统就立即回收分配给它的内存. 这意味着在进程的任意点,Wolfram 系统仅保存实际需要的那些表达式,它不保存后面不需要的对象.

这里给出 Wolfram 系统当前所使用内存的字节数.
In[1]:=
Click for copyable input
Out[1]=
这里产生 10000 个元素的列表.
In[2]:=
Click for copyable input
Out[2]=
需要额外的内存去存放这个列表.
In[3]:=
Click for copyable input
Out[3]=
这个列表是 Out[2] 的值,所以保存了它. 当删除 Out[2] 时,该列表就不再使用.
In[4]:=
Click for copyable input
所使用的内存减少.
In[5]:=
Click for copyable input
Out[5]=
这里显示了在此进程的任意点所需要的最大内存.
In[6]:=
Click for copyable input
Out[6]=

经常出现的一个问题是在某一计算机系统中 Wolfram 系统实际能使用多少内存. 通常,某个时刻在该计算机上运行的所有过程能使用的内存是一个确定的量. 有时候,该内存量等于该计算机中 RAM 的物理字节数. 常常还包括一些虚拟内存,这是通过与存储设备交换数据而得到的.

运行 Wolfram 系统时,数据和代码都需要空间. 完整的 Wolfram 系统代码一般有几兆字节. 对任何特定的计算而言,通常仅使用其代码的一部分. 然而,在计算 Wolfram 系统数据的总有效空间时,不要忘记 Wolfram 系统代码所占用的空间. 另外,还要包括正在计算机上运行的其它过程所占用的空间. 运行的作业少时,自己的作业就可以使用更多的内存.

也要看到所需计算时间在很大程度上也依赖于物理内存量. 尽管虚拟内存可以使我们使用大量的内存空间,但通常它比物理内存的访问要慢几百甚至几千倍. 因此,需要虚拟内存的大型计算运行非常慢.

MemoryConstrained[expr,b]计算 expr,当所需要的内存大于 b 时放弃
MemoryConstrained[expr,b,failexpr]当没有满足内存限制时,返回 failexpr

限制内存的计算.

MemoryConstrainedTimeConstrained 的工作过程相同. 当所需要的内存超过指定值时,MemoryConstrained 就试图放弃所给的计算. 与 TimeConstrained 相同,在放弃计算之前所使用的实际内存可能会超过给定值.

ByteCount[expr]存放 expr 所需内存的最大字节
LeafCount[expr]expr 表达式树中的终结点数

找出表达式的大小.

尽管 ByteCount 在估计能处理类型表达式的大小时是有用的,但 ByteCount 给出的结果随着 Wolfram 系统版本的不同有很大的差异.

一个要点是 ByteCount 给出的总是存储一个表达式时所需的最大内存. Wolfram 系统通常使用少得多的内存去存放这个表达式. 主要问题是该表达式中有多少子表达式可以共用.

等表达式中,这两个子表达式 完全相同,但它们实际上不一定能存放在计算机内存的同一块内存中. ByteCount 假设所有子表达式都不共用,在此基础上给出存放表达式所需要的字节数. 但要看到一旦使用了 操作符等运算后,就破坏了子表达式的共用.

然而,可以通过使用函数 Share 明确告诉 Wolfram 系统去共用子表达式. 用这一方法,可以大大减少存放一个表达式时所需的实际内存.

Share[expr]expr 的存储中共用相同的表达式
Share[]在整个内存中共用相同的子表达式

优化内存使用.

在大部分计算机系统中,运行一个程序时所需的内存分为两部分:由程序明确分配的内存和堆栈空间. 在程序中每次调用一个内部例行子程序时,一定量的堆栈空间就用来存放与这个调用有关的参数. 在许多计算机系统中,由一个程序所使用的堆栈空间的最大值必须事先给出. 当指定的堆栈空间被超过时,该程序通常就退出.

在 Wolfram 系统中,堆栈空间的主要用途之一就是处理 Wolfram 系统函数的相互调用. 所有这样的调用被明确记录在Wolfram 系统 Stack 中,如 "计算堆栈" 中所述. 用户可以通过设置全局参数 $RecursionLimit 控制这个堆栈的大小. 应该将这个参数设置得足够小以保证在所用计算机系统中不会用尽堆栈空间.