分析 Mathematica 代码

发布于 2024-12-15 01:28:06 字数 539 浏览 4 评论 0原文

有没有在 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

Is there a good way to profile code in Mathematica? I would like to be able to recurse (i.e., if I say f[a_] := b[a], then Profile[f[1]] should give almost the same output as Profile[b[1]]), but I'll settle for being able to do something like applying Timing to every relevant subexpression. It would be nice if I didn't have to special-case things like Module, but I'd like, e.g., Profile[Module[{x=1+2},x!]] to give me an output like

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

倾城花音 2024-12-22 01:28:06

是的,Wolfram Workbench 确实有一个分析器,尽管 根据文档,输出并不完全符合您想要的形式。

我应该指出,Mr.Wizard 在评论中提出的问题 - 缓存的结果将导致不同的计时结果 - 也可以应用在配置文件中。

如果您想在 Mathematica 中专门做一些事情,您可以尝试以下操作:

myProfile[fun_Symbol,inputs_List]:=  
    TableForm[#[[{1,3,2}]]&/@ (Join @@@ ({Timing[f[#]],#} & /@ inputs))]

如果您很高兴将输出设置为 {timing,output, input},而不是问题中指定的 {timing, input, output},那么您可以去掉 #[[{1,3,2}]] 位。

编辑

因为我有工作台,这里是一个例子。我有一个包 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]] ]]
  ]

在调试模式下运行包

然后运行此笔记本

在此处输入图像描述

给出以下输出。

输入图片此处描述

Yes, Wolfram Workbench does have a profiler, although according to the documentation the output isn't quite in the form you want.

I should note that the issue raised by Mr.Wizard in comments - that cached results will lead to different timing results - can also apply in profile.

If you wanted to do something exclusively in Mathematica, you could try something like:

myProfile[fun_Symbol,inputs_List]:=  
    TableForm[#[[{1,3,2}]]&/@ (Join @@@ ({Timing[f[#]],#} & /@ inputs))]

If you were happy enough to have the output as {timing,output, input}, rather than {timing, input, output} as specified in your question, you could get rid of the #[[{1,3,2}]] bit.

EDIT

Since I have Workbench, here is an example. I have a package AdvancedPlots which includes a function CobwebPlot (and yes, the function itself could improved).

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]] ]]
  ]

Running the package in Debug mode

And then running this notebook

enter image description here

Gives the following output.

enter image description here

潦草背影 2024-12-22 01:28:06

这是使用 TraceScan 为各个评估步骤计时的尝试。它使用原始的 AbsoluteTime[] 增量,这可能是好是坏,具体取决于您实际期望的时间。

确保在新内核上运行此示例,否则 Prime 将缓存其结果,并且所有计时都将 ~= 0。

t = AbsoluteTime[]; step = "start";

TraceScan[
  (Print[AbsoluteTime[] - t, " for ", step]; t = AbsoluteTime[]; step = #) &,
  Module[{x = 7 + 7}, Sqrt@Prime[x!]]
]
0.0010001 for start

0.*10^-8 for Module[{x=7+7},Sqrt[Prime[x!]]]

0.*10^-8 for Module

0.*10^-8 for 7+7

0.*10^-8 for Plus

0.*10^-8 for 7

0.*10^-8 for 7

0.*10^-8 for 14

0.*10^-8 for x$149=Unevaluated[14]

0.*10^-8 for Set

0.*10^-8 for x$149=14

0.*10^-8 for 14

0.*10^-8 for Sqrt[Prime[x$149!]]

0.*10^-8 for Sqrt

0.*10^-8 for Prime[x$149!]

0.*10^-8 for Prime

0.*10^-8 for x$149!

0.*10^-8 for Factorial

0.*10^-8 for x$149

0.*10^-8 for 14

0.*10^-8 for 14!

0.*10^-8 for 87178291200

2.6691526 for Prime[87178291200]

0.*10^-8 for 2394322471421

0.*10^-8 for Sqrt[2394322471421]

0.*10^-8 for Sqrt[2394322471421]

0.*10^-8 for Power

0.*10^-8 for 2394322471421

0.*10^-8 for 1/2

This is an attempt to use TraceScan to time individual steps of evaluation. It uses raw AbsoluteTime[] deltas which could be good or bad depending on what you actually expect to time.

Make sure to run this example on a fresh kernel, or Prime will cache its results and all timings will be ~= 0.

t = AbsoluteTime[]; step = "start";

TraceScan[
  (Print[AbsoluteTime[] - t, " for ", step]; t = AbsoluteTime[]; step = #) &,
  Module[{x = 7 + 7}, Sqrt@Prime[x!]]
]
0.0010001 for start

0.*10^-8 for Module[{x=7+7},Sqrt[Prime[x!]]]

0.*10^-8 for Module

0.*10^-8 for 7+7

0.*10^-8 for Plus

0.*10^-8 for 7

0.*10^-8 for 7

0.*10^-8 for 14

0.*10^-8 for x$149=Unevaluated[14]

0.*10^-8 for Set

0.*10^-8 for x$149=14

0.*10^-8 for 14

0.*10^-8 for Sqrt[Prime[x$149!]]

0.*10^-8 for Sqrt

0.*10^-8 for Prime[x$149!]

0.*10^-8 for Prime

0.*10^-8 for x$149!

0.*10^-8 for Factorial

0.*10^-8 for x$149

0.*10^-8 for 14

0.*10^-8 for 14!

0.*10^-8 for 87178291200

2.6691526 for Prime[87178291200]

0.*10^-8 for 2394322471421

0.*10^-8 for Sqrt[2394322471421]

0.*10^-8 for Sqrt[2394322471421]

0.*10^-8 for Power

0.*10^-8 for 2394322471421

0.*10^-8 for 1/2
眼眸里的那抹悲凉 2024-12-22 01:28:06

正如贝利撒留在回答我上面链接的问题时所显示的那样,似乎 Wolfram Workbench 包含一个分析器。不过我不使用 Workbench,所以我无法详细说明它的用法。

As belisarius showed in answer to the question I linked above, it appears that Wolfram Workbench includes a profiler. I do not use Workbench however, so I cannot detail its use.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文