2011-11-11 17 views
12

Esiste un buon metodo per codificare il codice in Mathematica? Vorrei essere in grado di ricorrere (ad esempio, se dico f[a_] := b[a], quindi Profile[f[1]] dovrebbe dare quasi la stessa uscita di Profile[b[1]]), ma mi accontento di poter fare qualcosa come applicare Timing a ogni sottoespressione rilevante. Sarebbe bello se io non dovessi speciale-caso le cose come Module, ma mi piacerebbe, per esempio, Profile[Module[{x=1+2},x!]] di darmi un output comeProfiling Mathematica Code

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 
+0

correlati: http://stackoverflow.com/questions/3418892/profiling-memory-usage-in-mathematica – abcd

+0

Vedere anche: http://stackoverflow.com/questions/4721171/performance-tuning-in-mathematica –

+0

Tutti: Sto cercando di farlo con 'TraceScan' ma io sto incontrando il problema che Mathematica memorizza i risultati nella cache, quindi le chiamate sequenziali a 'Prime [13!]' ad esempio richiedono tempi molto diversi per la valutazione. –

risposta

1

Come Belisario ha mostrato in risposta alla domanda che ho collegato sopra, sembra che Wolfram Workbench includes a profiler. Tuttavia, non utilizzo Workbench, quindi non posso descriverne l'uso.

5

Sì, Wolfram Workbench ha un profiler, anche se according to the documentation l'output non è del tutto nella forma desiderata.

Devo notare che il problema sollevato da Mr.Wizard nei commenti - che i risultati memorizzati nella cache porteranno a risultati temporali diversi - può anche essere applicato nel profilo.

Se si voleva fare qualcosa di esclusivamente in Mathematica, si potrebbe provare qualcosa di simile:

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

Se siete stati abbastanza felice di avere l'output come {tempistica, uscita, ingresso}, piuttosto che {tempistica, input, output} come specificato nella tua domanda, potresti liberarti del bit #[[{1,3,2}]].

EDIT

Dal momento che ho Banco di lavoro, ecco un esempio. Ho un pacchetto che include una funzione CobwebPlot (e sì, la funzione stessa potrebbe essere migliorata).

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

L'esecuzione del pacchetto in modalità debug

E poi l'esecuzione di questo notebook

enter image description here

ha pronunciato la seguente uscita.

enter image description here

+0

Se ritieni che questa funzione possa essere migliorata, perché non pubblicarla su Code Review? –

+1

Questo è quasi quello che sto cercando, ma Profilo sembra perdere gran parte del mio codice. Il codice che sto provando a tracciare adesso richiede 63 secondi (secondo Timing), ma i maggiori contributi al profilo sono 90 chiamate a MakeBoxes [Peak: PeakObject [_List], FormatType_] con tempo \t 0,718 (ciascuno? totale?) e 723344 \t chiamate a 7 con 0,655 (ciascuna? totale?). Inoltre, qualcosa come Profile [Do [100000 !, {100}]] non fornisce alcuna voce nel profilo. –

4

Questo è un tentativo di utilizzare TraceScan in volta le singole fasi di valutazione. Utilizza i delta grezzi AbsoluteTime[] che potrebbero essere buoni o cattivi a seconda di ciò che si aspetta effettivamente.

Assicurarsi di eseguire questo esempio su un kernel fresca, o Prime memorizza nella cache i risultati e tutti i tempi sarà ~ = 0.

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

TraceScan[ 
    (Print[AbsoluteTime[] - t, " for ", step]; t = AbsoluteTime[]; step = #) &, 
    Module[{x = 7 + 7}, [email protected][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