2011-11-11 13 views
12

¿Existe una buena forma de crear un código de perfil en Mathematica? Me gustaría ser recurrente (es decir, si digo f[a_] := b[a], entonces Profile[f[1]] debería dar casi el mismo resultado que Profile[b[1]]), pero me conformaré con poder hacer algo como aplicar Timing a cada subexpresión relevante. Sería bueno si yo no tuviera que constituyen casos especiales cosas como Module, pero me gustaría, por ejemplo, Profile[Module[{x=1+2},x!]] me dan una salida comoProfiling 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

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

+0

También vea: http://stackoverflow.com/questions/4721171/performance-tuning-in-mathematica –

+0

All: Estoy tratando de hacer esto con 'TraceScan' pero Me estoy encontrando con el problema de que Mathematica almacena en caché los resultados, por lo tanto, las llamadas secuenciales a 'Prime [13!]', por ejemplo, toman tiempos muy diferentes para evaluar. –

Respuesta

1

Como belisarius mostró en respuesta a la pregunta que he vinculado arriba, parece que Wolfram Workbench includes a profiler. Sin embargo, no uso Workbench, así que no puedo detallar su uso.

5

Sí, Wolfram Workbench tiene un generador de perfiles, aunque according to the documentation la salida no es del todo el formato que desea.

Debo señalar que el problema planteado por Mr.Wizard en los comentarios, que los resultados almacenados en la memoria caché generarán diferentes tiempos, también puede aplicarse en el perfil.

Si quería hacer algo exclusivamente en Mathematica, podría intentar algo como:

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

Si tuvieron la feliz de tener la salida como {sincronización, de salida, de entrada}, en lugar de {tiempo, entrada, salida} como se especifica en su pregunta, puede deshacerse del bit #[[{1,3,2}]].

EDITAR

Ya que tengo Banco de trabajo, aquí hay un ejemplo. Tengo un paquete AdvancedPlots que incluye una función CobwebPlot (y sí, la función en sí podría mejorarse).

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

ejecutar el paquete en modo de depuración

Y a continuación, ejecutar este portátil

enter image description here

da el siguiente resultado.

enter image description here

+0

Si considera que esta función se puede mejorar, ¿por qué no publicarla en la Revisión de código? –

+1

Esto es casi lo que estoy buscando, pero el perfil parece perder la mayor parte de mi código. El código que intento crear en este momento demora 63 segundos en ejecutarse (según Timing), pero las mayores contribuciones al perfil son 90 llamadas a MakeBoxes [Peak: PeakObject [_List], FormatType_] con tiempo \t 0.718 (¿cada uno? ¿total?) y 723344 \t llamadas a 7 con 0.655 (¿total?). Además, algo como Profile [Do [100000! {100}]] no da ninguna entrada en el perfil. –

4

Este es un intento de utilizar TraceScan a tiempo medidas individuales de evaluación. Utiliza deltas brutos AbsoluteTime[] que pueden ser buenos o malos, dependiendo de lo que realmente espere que sea el tiempo.

Asegúrese de ejecutar este ejemplo en un kernel fresca, o Prime cachear sus resultados y todos los tiempos será ~ = 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