Wolfram mathematica 应用vs映射的内存使用。虚拟内存使用和锁定

Wolfram mathematica 应用vs映射的内存使用。虚拟内存使用和锁定,wolfram-mathematica,memory-management,Wolfram Mathematica,Memory Management,我需要在一个长长的成对列表中找到所有成对数字的总和。在Mathematica中有很多方法可以做到这一点,但我正在考虑使用Plus或Total。由于Total在列表上工作,Map是在列表中使用的函数式编程工具,而Apply在级别1(@@@)是用于Plus的工具,因为Plus将要添加的数字作为参数 下面是一些演示代码(警告:在执行此操作之前保存所有工作!): 您可能已经注意到,我在Plus的代码中添加了timeconstraint。这是我为您提供的一项保护措施,因为赤裸裸的代码让我的电脑几乎崩溃。事

我需要在一个长长的成对列表中找到所有成对数字的总和。在Mathematica中有很多方法可以做到这一点,但我正在考虑使用
Plus
Total
。由于
Total
在列表上工作,
Map
是在列表中使用的函数式编程工具,而
Apply
在级别1(@@@)是用于
Plus
的工具,因为
Plus
将要添加的数字作为参数

下面是一些演示代码(警告:在执行此操作之前保存所有工作!):

您可能已经注意到,我在
Plus
的代码中添加了
timeconstraint
。这是我为您提供的一项保护措施,因为赤裸裸的代码让我的电脑几乎崩溃。事实上,上面的代码对我有效,但如果我将第一行的范围增加到7000,我的计算机就会锁定,再也回不来了。什么都不起作用,没有alt周期,程序切换,ctrl-alt-delete,尝试使用任务栏启动process manager,关闭笔记本电脑盖让其睡眠,等等,实际上什么都没有

该问题是由
Plus@@@pairs
行的极端内存使用造成的。虽然“pairs”本身占用了大约288MB的空间,而列表中的数据总量占了其中的一半,但加号线的计算速度很快就消耗了大约7GB。这是我可用物理内存的结束,任何较大的内存都会导致磁盘上使用虚拟内存。而Mathematica和/或Windows显然在使用虚拟内存时表现不佳(顺便说一句,MacOS和Linux是否表现更好?)。相反,总行对内存使用图没有明显的影响

我有两个问题:

  • 鉴于文档中所述的
    Plus
    Total
    之间的等效性(“Total[list]相当于Apply[Plus,list]”),如何解释行为上的极端差异?我认为这与
    Apply
    Map
    之间的差异有关,但我对所涉及的内部机制感到好奇
  • 我知道我可以通过使用
    MemoryConstrained
    来限制命令的内存占用,但在怀疑Mathematica可能占用您所有系统资源的任何地方都必须使用它,这是一种痛苦。是否有一个全局设置,我可以用来告诉Mathematica对其所有操作只使用物理内存(或者,最好是其中的一部分)?这将是非常有帮助的,因为在过去的几周里,这种行为已经导致了一些锁死事件,而且它真的开始让我恼火

  • Plus@@@pairs
    正在解包:

    In[11]:= On["Packing"]
    In[12]:= pairs=Tuples[Range[6000],{2}];
    In[13]:= TimeConstrained[Plus@@@pairs;//Timing,30]
    During evaluation of In[13]:= Developer`FromPackedArray::punpack1: Unpacking array with dimensions {36000000,2}. >>
    Out[13]= $Aborted
    
    这将做同样的事情,并且不会解包,这意味着它使用更少的内存

    On["Packing"]
    pairs=Tuples[Range[6000],{2}];
    a = pairs[[All, 1]];b=pairs[[All, 2]];
    Plus[a, b];
    
    您可以在此处阅读Mathematica中有关包装的更多信息:

    我只想补充一些观察结果,这些观察结果可能会进一步澄清情况。正如@Joshua在回答中指出的(另请参见类似讨论的评论),效率低下的原因与拆包有关。我的猜测是
    Apply
    解包的一般原因是编译器(
    Compile
    )对
    Apply
    的支持非常有限,也就是说,只能使用3个头-
    List
    Plus
    Times
    。因此,在
    SystemOptions[“CompileOptions”]
    中,我们可以看到
    Apply
    的编译长度被设置为无穷大-通常甚至尝试自动编译
    Apply
    都没有意义。然后,当编译长度大于实际数组维度时,它可能会解包。当我们将
    “ApplyCompileLength”
    设置为有限长度时,行为会发生变化:

    On["Packing"]
    pairs=Tuples[Range[2000],{2}];
    SetSystemOptions["CompileOptions"->"ApplyCompileLength"->100];
    TimeConstrained[Plus@@@pairs;//Timing,30]
    
    {0.594,Null}
    
    再次将其更改回可恢复观察到的初始行为:

    In[34]:= 
    SetSystemOptions["CompileOptions" -> "ApplyCompileLength" -> Infinity];
    TimeConstrained[Plus @@@ pairs; // Timing, 30]
    
    During evaluation of In[34]:= Developer`FromPackedArray::punpack1: Unpacking 
    array with dimensions  {4000000,2}. >>
    
    Out[35]= {2.094, Null}
    
    关于你的第二个问题:也许,约束内存的系统方法与@Alexey Popkov所做的一样,使用主内核控制从内核,一旦内存不足,从内核就会重新启动。我可以提供一个远没有那么复杂的黑客,但可能仍然有一些用处。以下函数

    ClearAll[totalMemoryConstrained];
    SetAttributes[totalMemoryConstrained, HoldRest];
    Module[{memException},
      totalMemoryConstrained[max_, body_, failexpr_] :=
       Catch[MemoryConstrained[body,
         Evaluate[
           If[# < 0, Throw[failexpr, memException], #] &@(max -
             MemoryInUse[])], failexpr], memException]]; 
    
    ClearAll[totalMemoryConstrained];
    SetAttributes[totalMemoryConstrained,HoldRest];
    模块[{memException},
    totalMemoryConstrained[最大值,正文,故障表达式]:=
    抓住[记忆训练过的]身体,
    评估[
    如果[#<0,则抛出[failexpr,memException],#]&@(最大值)-
    MemoryUse[])],failexpr],memException]];
    

    将尝试约束内核使用的总内存,而不仅仅是在给定的特定计算中。因此,您可以尝试将其包装在顶级函数调用中,只需一次。因为它依赖于
    MemoryConstrained
    MemoryInUse
    ,所以它只和它们一样好。有关如何使用它的更多详细信息,请参阅Mathgroup post。您可以使用
    $Pre
    自动将其应用到您的输入中,并减少样板代码的数量。

    问题的第二部分对于Mathematica用户来说非常实际。我已经在官方新闻组中提出了相关问题,得到了以下信息:

    2011年3月10日星期四06:12:04-0500 (美国东部时间)亚历克赛·波普科夫写道:

    我更喜欢的不是记忆训练 “FreeMemoryConstrained” 用于防止安全交换的功能

    这不是现代的运作方式 系统工作。所有内存都是虚拟的 记忆。无论它是否有RAM支持, 磁盘或某些其他存储介质已损坏 操作系统的详细信息 管理而不是应用程序(使用 机制例外,如 内存映射文件)。如果 应用程序确实有能力 将其内存锁定在RAM中,这将是 对别人确实很不友好 系统上的应用程序

    你真的想要一个这样的应用程序吗 坚持保留2G内存 自作主张 可容纳200个用户的应用程序 梅格
    ClearAll[totalMemoryConstrained];
    SetAttributes[totalMemoryConstrained, HoldRest];
    Module[{memException},
      totalMemoryConstrained[max_, body_, failexpr_] :=
       Catch[MemoryConstrained[body,
         Evaluate[
           If[# < 0, Throw[failexpr, memException], #] &@(max -
             MemoryInUse[])], failexpr], memException]];