分析 Mathematica 代码
Posted
技术标签:
【中文标题】分析 Mathematica 代码【英文标题】:Profiling Mathematica Code 【发布时间】:2011-11-11 01:37:08 【问题描述】:有没有在 Mathematica 中分析代码的好方法?我希望能够递归(即,如果我说f[a_] := b[a]
,那么Profile[f[1]]
应该给出与Profile[b[1]]
几乎相同的输出),但我会满足于能够做一些事情,比如应用Timing
到每个相关的子表达式。如果我不必像 Module
这样的特殊情况会很好,但我想,例如,Profile[Module[x=1+2,x!]]
给我一个输出像
Time Expression Result
0 1 1
0 2 2
0 1 + 2 3
0 x$1234 3
0 x$1234 ! 6
0 Module[x=1+2,x!] 6
6
【问题讨论】:
相关:***.com/questions/3418892/… 另见:***.com/questions/4721171/… All:我正在尝试使用TraceScan
执行此操作,但我遇到了 Mathematica 缓存结果的问题,因此例如对 Prime[13!]
的连续调用需要非常不同的时间来评估。跨度>
【参考方案1】:
是的,Wolfram Workbench 确实有一个分析器,尽管 according to the documentation 的输出不是您想要的形式。
我要注意的是,Mr.Wizard 在 cmets 中提出的问题——缓存的结果会导致不同的计时结果——也可以应用在配置文件中。
如果您只想在 Mathematica 中做某事,您可以尝试以下方法:
myProfile[fun_Symbol,inputs_List]:=
TableForm[#[[1,3,2]]&/@ (Join @@@ (Timing[f[#]],# & /@ inputs))]
如果您很高兴将输出设为 timing,output, input,而不是问题中指定的 timing, input, output,则可以去掉 #[[1,3,2]]
位。
编辑
因为我有 Workbench,所以这里有一个例子。我有一个包AdvancedPlots
,其中包含一个函数CobwebPlot
(是的,函数本身可以改进)。
CobwebPlot[x_?MatrixQ, opts___Rule] /;
And @@ (NumericQ /@ Flatten[x]) :=
Module[n, \[Theta]s, numgrids, grids, struts, gridstyle, min, max,
data, labels, epilabels, pad,
n = Length[First[x]];
\[Theta]s = (2 \[Pi])/n Range[0, n] + If[OddQ[n], \[Pi]/2, 0];
numgrids =
If[IntegerQ[#] && Positive[#], #,
NumberofGrids /.
Options[CobwebPlot] ] & @ (NumberofGrids /. opts);
min, max = Min[#], Max[#] &@ Flatten[x];
gridstyle = GridStyle /. opts /. Options[CobwebPlot];
pad = CobwebPadding /. opts /. Options[CobwebPlot];
grids =
Outer[List, \[Theta]s, FindDivisions[0, max + 1, numgrids]];
struts = Transpose[grids];
labels = CobwebLabels /. opts /. Options[CobwebPlot];
epilabels =
If[Length[labels] == n,
Thread[Text[
labels, (1.2 max) Transpose[Cos[Most[\[Theta]s]],
Sin[Most[\[Theta]s]]]]], None];
data = Map[Reverse,
Inner[List, Join[#, First[#]] & /@ x, \[Theta]s, List], 2];
Show[ListPolarPlot[grids, gridstyle, Joined -> True, Axes -> False,
PlotRangePadding -> pad],
ListPolarPlot[struts, gridstyle, Joined -> True, Axes -> False],
ListPolarPlot[data,
Sequence @@ FilterRules[opts, Options[ListPolarPlot]],
Sequence @@
FilterRules[Options[CobwebPlot], Options[ListPolarPlot]],
Joined -> True, Axes -> None] ,
If[Length[labels] == n, Graphics /@ epilabels,
Sequence @@ FilterRules[opts, Options[Graphics]] ]]
]
在调试模式下运行包
然后运行这个笔记本
给出以下输出。
【讨论】:
如果你觉得这个功能可以改进,为什么不把它贴在 Code Review 上呢? 这几乎是我要找的,但 Profile 似乎错过了我的大部分代码。我现在尝试分析的代码需要 63 秒才能执行(根据时序),但对分析的最大贡献是 90 次调用 MakeBoxes[Peak:PeakObject[List],FormatType]时间为 0.718(每个?总计?),723344 次调用 7,时间为 0.655(每个?总计?)。此外,像 Profile[Do[100000!, 100]] 这样的东西根本不会在配置文件中提供任何条目。【参考方案2】:这是尝试使用TraceScan
来计时各个评估步骤。它使用原始的AbsoluteTime[]
deltas,这可能是好是坏,具体取决于您实际期望的时间。
确保在新内核上运行此示例,否则Prime
将缓存其结果,所有时间都将是 ~= 0。
t = AbsoluteTime[]; step = "start";
TraceScan[
(Print[AbsoluteTime[] - t, " for ", step]; t = AbsoluteTime[]; step = #) &,
Module[x = 7 + 7, Sqrt@Prime[x!]]
]
0.0010001 开始 0.*10^-8 为 Module[x=7+7,Sqrt[Prime[x!]]] 0.*10^-8 用于模块 0.*10^-8 为 7+7 0.*10^-8 加号 0.*10^-8 为 7 0.*10^-8 为 7 0.*10^-8 为 14 0.*10^-8 for x$149=未评估[14] 0.*10^-8 用于设置 0.*10^-8 对于 x$149=14 0.*10^-8 为 14 0.*10^-8 对于 Sqrt[Prime[x$149!]] 0.*10^-8 为 Sqrt 0.*10^-8 为 Prime[x$149!] 0.*10^-8 为素数 0.*10^-8 x 149 美元! 0.*10^-8 为阶乘 0.*10^-8 x $149 0.*10^-8 为 14 0.*10^-8 为 14! 0.*10^-8 为 87178291200 2.6691526 为 Prime[87178291200] 0.*10^-8 为 2394322471421 0.*10^-8 为 Sqrt[2394322471421] 0.*10^-8 为 Sqrt[2394322471421] 0.*10^-8 功率 0.*10^-8 为 2394322471421 0.*10^-8 为 1/2
【讨论】:
【参考方案3】:正如贝利撒留在回答我上面链接的问题时所显示的那样,Wolfram Workbench includes a profiler 似乎是。但是我不使用 Workbench,所以我不能详细说明它的使用。
【讨论】:
以上是关于分析 Mathematica 代码的主要内容,如果未能解决你的问题,请参考以下文章