12 Stimmen

Profiling Mathematica-Code

Gibt es eine gute Möglichkeit, Code in Mathematica zu profilieren? Ich möchte in der Lage sein, rekursiv vorzugehen (d.h., wenn ich f[a_] := b[a] sage, sollte Profile[f[1]] fast den gleichen Output wie Profile[b[1]] geben), aber ich würde mich damit zufriedengeben, wenn ich etwas ähnliches wie Timing auf jeden relevanten Teilausdruck anwenden könnte. Es wäre schön, wenn ich nicht spezielle Fälle wie Module behandeln müsste, aber ich hätte gerne, z.B., dass Profile[Module[{x=1+2},x!]] mir einen Output wie

Zeit    Ausdruck            Ergebnis
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

5voto

Verbeia Punkte 4380

Ja, Wolfram Workbench hat tatsächlich einen Profiler, obwohl laut der Dokumentation die Ausgabe nicht ganz in der Form ist, die Sie möchten.

Ich sollte darauf hinweisen, dass das von Herrn Wizard in den Kommentaren angesprochene Problem - dass zwischengespeicherte Ergebnisse zu unterschiedlichen Zeitmessungsergebnissen führen werden - sich auch im Profilieren zeigen kann.

Wenn Sie etwas ausschließlich in Mathematica machen möchten, könnten Sie Folgendes versuchen:

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

Wenn Sie damit zufrieden wären, die Ausgabe als {Zeitmessung, Ausgabe, Eingabe} zu haben, anstatt {Zeitmessung, Eingabe, Ausgabe} wie in Ihrer Frage angegeben, könnten Sie den #[[{1,3,2}]] Teil loswerden.

BEARBEITEN

Da ich Workbench habe, hier ist ein Beispiel. Ich habe ein Paket AdvancedPlots, das eine Funktion CobwebPlot enthält (und ja, die Funktion selbst könnte verbessert werden).

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

Das Paket im Debug-Modus ausführen

Und dann dieses Notebook ausführen

Eingabebeschreibung hier eingeben

Gibt die folgende Ausgabe.

Eingabebeschreibung hier eingeben

4voto

Mr.Wizard Punkte 23929

Dies ist ein Versuch, TraceScan zu verwenden, um einzelne Schritte der Auswertung zu timen. Es verwendet reine AbsoluteTime[]-Deltas, die je nach dem, was Sie tatsächlich timen möchten, gut oder schlecht sein könnten.

Stellen Sie sicher, dass Sie dieses Beispiel in einem frischen Kernel ausführen, sonst wird Prime seine Ergebnisse zwischenspeichern und alle Zeitmessungen werden ungefähr 0 sein.

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

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

0,0010001 für start

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

0.\*10^-8 für Module

0.\*10^-8 für 7+7

0.\*10^-8 für Plus

0.\*10^-8 für 7

0.\*10^-8 für 7

0.\*10^-8 für 14

0.\*10^-8 für x$149=Unevaluated\[14\]

0.\*10^-8 für Set

0.\*10^-8 für x$149=14

0.\*10^-8 für 14

0.\*10^-8 für Sqrt\[Prime\[x$149!\]\]

0.\*10^-8 für Sqrt

0.\*10^-8 für Prime\[x$149!\]

0.\*10^-8 für Prime

0.\*10^-8 für x$149!

0.\*10^-8 für Fakultät

0.\*10^-8 für x$149

0.\*10^-8 für 14

0.\*10^-8 für 14!

0.\*10^-8 für 87178291200

2,6691526 für Prime\[87178291200\]

0.\*10^-8 für 2394322471421

0.\*10^-8 für Sqrt\[2394322471421\]

0.\*10^-8 für Sqrt\[2394322471421\]

0.\*10^-8 für Potenz

0.\*10^-8 für 2394322471421

0.\*10^-8 für 1/2

1voto

Mr.Wizard Punkte 23929

Wie Belisarius in seiner Antwort auf die oben verlinkte Frage gezeigt hat, scheint es, dass Wolfram Workbench einen Profiler enthält. Ich benutze Workbench jedoch nicht, daher kann ich seine Verwendung nicht im Detail erklären.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X