Advertisement
simonjtyler

TimeAv

Aug 15th, 2011
285
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.39 KB | None | 0 0
  1. (*http://stackoverflow.com/questions/4198961/what-is-in-your-mathematica-tool-bag/4199042#4199042*)
  2.  
  3. Unprotect[TimeAv];
  4.  
  5. TimeAv::usage = "\!\(\*
  6. StyleBox[\"TimeAv\", \"TI\"]\)\!\(\*
  7. StyleBox[\"[\", \"TI\"]\)\!\(\*
  8. StyleBox[\"expr_\", \"TI\"]\)\!\(\*
  9. StyleBox[\"]\", \"TI\"]\) takes the average timing of evaluating expr \
  10. and returns a list of the time in seconds used, together with the \
  11. result obtained. \
  12. It has the three main options:
  13. Method\[Rule]Automatic, which can take the values {\"MinTime\", \
  14. num} or {\"MinNum\", num} for num>0.
  15. \"BlockSize\"->Scaled[0.1], which can be of the form num for some \
  16. num>=1, or Scaled[s] (with 0<=s<=1).
  17. \"PrintStats\"->True, which if True will print the statistics for \
  18. the time averaging.
  19. Other options are \"ClearSystemCache\" and \"StoreAllTimings\" \
  20. which have the obvious meanings.
  21. Note that using a Scaled[s] block size is only approximate as it is \
  22. based on the timing of a test evaluation of the expression.";
  23.  
  24. Unprotect[TimeAv];
  25. (*ClearAll[TimeAv];*)
  26.  
  27. SetAttributes[TimeAv, HoldFirst]
  28.  
  29. Options[TimeAv] = {Method -> Automatic, "ClearSystemCache" -> False,
  30. "BlockSize" -> Scaled[.1], "StoreAllTimings" -> False,
  31. "PrintStats" -> True};
  32.  
  33. SyntaxInformation[TimeAv] = {"ArgumentsPattern" -> {_, OptionsPattern[]}};
  34.  
  35. TimeAv::chres =
  36. "Warning: result is not constant each time we calculate its timing. \
  37. Returning the result for the first time it was calculated.";
  38.  
  39. TimeAv::badopt =
  40. "Warning: Bad option value `1` given for the TimeAv option `2`";
  41.  
  42. TimeAv::longtime =
  43. "Warning: The first evaluation took `` seconds, so no more runs will be \
  44. performed. Change the Method option if you want to force an averaging.";
  45.  
  46. TimeAv[func_, OptionsPattern[]] := Catch[
  47. Module[{time, out, time2, out2, count, squares, walltime, mean, alltimes,
  48. test, sys, reap, sow, warn = False,
  49. method = OptionValue[Method],
  50. fullout =
  51. TrueQ[MatchQ[OptionValue["PrintStats"], True | Automatic | Full]],
  52. csc = TrueQ[
  53. MatchQ[OptionValue["ClearSystemCache"], True | Automatic | Full]],
  54. block = OptionValue["BlockSize"] /. Full -> Scaled[1.0]},
  55. If[TrueQ[OptionValue["StoreAllTimings"]], reap = Reap; sow = Sow,
  56. reap = sow = Identity];
  57. alltimes = reap[walltime = AbsoluteTiming[Timing[
  58. If[csc, ClearSystemCache[]];
  59. (* Run once to estimate the timing *)
  60. sow[{time, out} = Timing[func]]; count = 1;
  61. (* If the timing is too small to reliable(ish), then replace with a small, averaged block *)
  62. If[Head[block] == Scaled && TrueQ[time <= .01],
  63. time = First[Timing[Do[func, {10}]]]/10; count = 10];
  64. squares = time^2;
  65. (* Use the first timing and option for Method to determing the structure of the loops *)
  66. Switch[method = OptionValue[Method],
  67. Automatic, Which[
  68. time < .2, method = {"MinTime", .5}; test := time < method[[2]],
  69. time < 2, method = {"MinTime", 4}; test := time < method[[2]],
  70. 2 <= time <= 5, method = {"MinNum", 3};
  71. test := count < method[[2]],
  72. time > 5, Message[TimeAv::longtime, EngineeringForm[time, 3]];
  73. Throw[{time, out}, TimeAv]],
  74. {"MinTime", _?Positive}, test := time < method[[2]],
  75. {"MinNum", _?Positive}, test := count < method[[2]],
  76. _, Message[TimeAv::badopt, method, Method]; Throw[$Failed, TimeAv]];
  77. Switch[block,
  78. _Integer?Positive, Null,
  79. Scaled[s_ /; 0 < s <= 1], Switch[method[[1]],
  80. "MinTime", block = Ceiling[1.1 Abs[N @@ block] method[[2]]/Max[{time, 1*^-5}]],
  81. "MinNum", block = Ceiling[1.1 Abs[N @@ block] method[[2]]]],
  82. _, If[TrueQ[Chop[N[block]] > 0], block = Ceiling[Chop[N[block]]],
  83. Message[TimeAv::badopt, method, "BlockSize"];
  84. Throw[$Failed, TimeAv]]];
  85. (* Throw away test case if time spent on it is small and block size is large *)
  86. If[block > 1 && time < 1, time = count = squares = 0];
  87. (* Loop starts here *)
  88. While[test,
  89. If[csc, ClearSystemCache[]];
  90. sow[{time2, out2} = Timing[Do[func, {block - 1}]; func]];
  91. time += time2; count += block; squares += (time2/block)^2;
  92. If[Not[warn] && out != out2, warn = True; Message[TimeAv::chres]]]]]];
  93. mean = time/count;
  94. (* The outputs *)
  95. If[TrueQ[OptionValue["StoreAllTimings"]],
  96. Print[TableForm[alltimes[[2]], TableDirections -> Row]]];
  97. If[fullout,
  98. Print["Total wall time is ", walltime[[1]],
  99. ", total cpu time is ", walltime[[2, 1]],
  100. " and total time spent evaluating the expression is ", time];
  101. Print["The expression was evaluated ", count, " time",
  102. If[count == 1, "", "s"], ", ",
  103. Sequence @@
  104. If[block == 1, {"without any blocking of the runs."}, {"in blocks of ",
  105. block, " runs."}], " This yields a mean timing of ", mean,
  106. Sequence @@ Which[
  107. count/block == 1, { " with no statistics on the standard deviation"},
  108. block == 1, {" with a standard deviation of ", Sqrt[squares/count - mean^2]},
  109. True, {" with a blocked standard deviation of ", Sqrt[squares/(count/block) - mean^2]}], "."]];
  110. {mean(*{mean,count,block,time,squares}*), out}], TimeAv]
  111.  
  112. Protect[TimeAv];
  113.  
  114. (* Note that clearing the system cache is quite slow. *)
  115. (* So for the small, fast timings that TimeAv is made for, *)
  116. (* it's best to leave that option off. *)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement