我需要在一长串对中找到所有数字对的总和.在Mathematica中有很多方法可以做到这一点,但我正考虑使用其中任何一个Plus或Total.由于Total在列表上工作,Map是在那里使用的函数式编程工具,Apply在级别1(@@@)是要使用的Plus,因为Plus要将数字作为参数添加.
这是一些演示代码(警告:在执行此操作之前保存所有工作!):
pairs = Tuples[Range[6000], {2}]; (* toy example *)
TimeConstrained[Plus @@@ pairs; // Timing, 30]
(* Out[4]= {21.73, Null} *)
Total /@ pairs; // Timing
(* Out[5]= {3.525, Null} *)
Run Code Online (Sandbox Code Playgroud)
您可能已经注意到我已添加TimeConstrained到代码中Plus.这是我为你提供的保护措施,因为裸代码使我的PC几乎瘫痪.事实上,上面的代码对我有用,但如果我将第一行的范围增加到7000,我的计算机就会锁定并且永远不会回来.什么都行不通,没有alt-period,程序切换,ctrl-alt-delete,尝试使用任务栏启动进程管理器,关闭笔记本电脑盖让它睡觉等等,真的没什么.
问题是由Plus @@@ pairs线路的极端内存使用引起的.虽然'对'本身占用大约288 MB,而总数的一半,但Plus系列的计算速度很快消耗约7 GB.这是我的免费物理内存的结束,任何更大的内容都会导致在磁盘上使用虚拟内存.当使用虚拟内存时,Mathematica和/或Windows显然效果不佳(BTW,MacOS和Linux表现更好吗?).相反,Total行对内存使用情况图没有明显影响.
我有两个问题:
Plus和(Total如[Total]列表相当于Apply [Plus,list].)如何解释行为的极端差异?我认为这与之间的差异做Apply和Map,但我很好奇,所涉及的内部机制.MemoryConstrained,但是如果您怀疑Mathematica可能会占用您的所有系统资源,那么必须在任何地方使用它是一件痛苦的事.是否有一个全局设置可以告诉Mathematica仅为其所有操作使用物理内存(或者,最好是其中的某一部分)?这将是非常有帮助的,因为这种行为导致了过去几周的一些锁定,并且它真的开始惹恼我.这个问题来自最近的问题" 正确的方法来限制Mathematica内存使用? "
我想知道,是否有可能以编程方式重新启动MathKernel,使当前的FrontEnd进程连接到新的MathKernel进程并在新的MathKernel会话中评估一些代码?我的意思是"透明"重启,它允许用户继续使用FrontEnd,同时拥有新的MathKernel流程,其中一些代码来自之前评估/评估的内核?
这个问题的动机是有一种方法可以在不中断计算而占用太多内存的情况下自动重启MathKernel .换句话说,计算应该在新的MathKernel过程中自动继续,而不与用户交互(但保持用户与Mathematica最初交互的能力).在新内核中应该评估什么代码的细节当然是针对每个计算任务的.我正在寻找一个通用的解决方案如何自动继续计算.
有时当我在Mathematica中编写实验代码时,我很担心是否应该对它进行评估,因为它可能最终导致我的系统陷入困境.
作为一个人为的例子,如果您尝试在64位计算机上运行以下代码片段,它很可能会导致系统在耗尽所有内存后完全停止.
junk = Table[{x, x}, {10^9}]; (* nom nom nom memory. Please don't run this. *)
Run Code Online (Sandbox Code Playgroud)
当然,你可以抛出MemoryConstrained它并希望最好,但有时你不希望它阻止任何进一步的输入.为此,我认为实现中间立场的最佳方式是在单独的内核中执行评估.
这很容易做到:
ClearAll[GetAvailableKernel];
GetAvailableKernel[] := Block[{i, kernels},
kernels = Kernels[];
If[Length@kernels != 0,
For[i = 1, i <= Length@kernels, i++,
If[kernels[[i, 1, 2]] > 0, Return@kernels[[i]]]
]
];
LaunchKernels[1]]
ClearAll[SafeEvaluate];
SetAttributes[SafeEvaluate, HoldFirst];
Options[SafeEvaluate] = {"EvaluationKernel" -> Null,
"ConstrainMemory" -> True, "MaxMemory" -> 2 1024^3};
SafeEvaluate[expr_, OptionsPattern[]] := Block[{evalkernel, result},
If[OptionValue["EvaluationKernel"] != Null,
evalkernel = OptionValue["EvaluationKernel"],
evalkernel = GetAvailableKernel[]
];
result = …Run Code Online (Sandbox Code Playgroud) 对于Mathematica专家来说,这是一个简单的问题:
给出一个清单,比方说
Clear[a, b, c];
data = {a, b, c};
Run Code Online (Sandbox Code Playgroud)
并且我想1,2,3,...Length[data]从开始到结束返回所有长度列表,以便我得到以下内容
out = {{a}, {a, b}, {a, b, c}}
Run Code Online (Sandbox Code Playgroud)
我查看了M中的命令以找到一个可以使用的命令,我可以(查看所有Map和Nest*函数,但不是我可以看到如何使用它).我确信它在那里,但我现在没有看到它.
现在我做这个愚蠢的Do循环来构建它
m=Length[data];
First@Reap[Do[Sow[data[[1;;i]]],{i,1,m}]][[2]]
{{a},{a,b},{a,b,c}}
Run Code Online (Sandbox Code Playgroud)
问题是:Mathematica有内置命令来执行上述操作吗?
上午8点更新
我已经删除了我在一小时前完成的测试,并将很快重新发布.我需要运行它们几次并取平均值,因为这是进行此性能测试的更好方法.
上午9点更新
好的,我已经在下面显示的所有解决方案上重新运行了性能测试.8种方法.对于每种方法,我运行它5次并取平均值.我做了这个,n={1000, 5000, 10000, 15000, 25000, 30000}其中n是要处理的原始列表的长度.
不能超过30,000,将用完ram.我只有4 GB的内存.
我做了一个小函数调用makeTable[n, methods],它生成特定的性能表n.测试代码如下(快速编写,所以不是最干净的代码,不是非常实用,因为我必须去:),但它在下面,任何人都可以更改/清理它等...如果他们想要
结论:Kguler方法是最快的,与Thies方法对于大n,(30,000)几乎相同,所以对于所有实际目的,可能是Thies和Kguler方法可以宣称为大n的赢家?但由于Kguler对小n来说也是最快的,到目前为止,他获得了明显的优势.
同样,测试代码在下面是任何人检查和运行以查看我是否可能在某处发生错误.正如Leonid正确预测的那样,链表方法对于大n来说并不是很好.
我认为需要更多的测试,因为只考虑5的平均值可能还不够,还有其他我可能错过的考虑因素.这不是一个精确的测试,只是一个粗略的想法.
我试着在运行测试时不要使用电脑.我使用AbsoluteTiming []来测量cpu.
这是生成的表格的屏幕截图

这是测试代码:
methods = {nasser, wizard1, wizard2, wizard3, kguler, leonid1,
leonid2, thies};
AppendTo[$ContextPath, "Internal`"];
ClearAll[linkedList, leonid2];
SetAttributes[linkedList, HoldAllComplete];
nasser[lst_] := Module[{m = Length[lst]},
First@Reap[Do[Sow[lst[[1 ;; i]]], {i, …Run Code Online (Sandbox Code Playgroud) asynchronous ×1