Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (*http://stackoverflow.com/questions/4198961/what-is-in-your-mathematica-tool-bag/4199042#4199042*)
- Unprotect[TimeAv];
- TimeAv::usage = "\!\(\*
- StyleBox[\"TimeAv\", \"TI\"]\)\!\(\*
- StyleBox[\"[\", \"TI\"]\)\!\(\*
- StyleBox[\"expr_\", \"TI\"]\)\!\(\*
- StyleBox[\"]\", \"TI\"]\) takes the average timing of evaluating expr \
- and returns a list of the time in seconds used, together with the \
- result obtained. \
- It has the three main options:
- Method\[Rule]Automatic, which can take the values {\"MinTime\", \
- num} or {\"MinNum\", num} for num>0.
- \"BlockSize\"->Scaled[0.1], which can be of the form num for some \
- num>=1, or Scaled[s] (with 0<=s<=1).
- \"PrintStats\"->True, which if True will print the statistics for \
- the time averaging.
- Other options are \"ClearSystemCache\" and \"StoreAllTimings\" \
- which have the obvious meanings.
- Note that using a Scaled[s] block size is only approximate as it is \
- based on the timing of a test evaluation of the expression.";
- Unprotect[TimeAv];
- (*ClearAll[TimeAv];*)
- SetAttributes[TimeAv, HoldFirst]
- Options[TimeAv] = {Method -> Automatic, "ClearSystemCache" -> False,
- "BlockSize" -> Scaled[.1], "StoreAllTimings" -> False,
- "PrintStats" -> True};
- SyntaxInformation[TimeAv] = {"ArgumentsPattern" -> {_, OptionsPattern[]}};
- TimeAv::chres =
- "Warning: result is not constant each time we calculate its timing. \
- Returning the result for the first time it was calculated.";
- TimeAv::badopt =
- "Warning: Bad option value `1` given for the TimeAv option `2`";
- TimeAv::longtime =
- "Warning: The first evaluation took `` seconds, so no more runs will be \
- performed. Change the Method option if you want to force an averaging.";
- TimeAv[func_, OptionsPattern[]] := Catch[
- Module[{time, out, time2, out2, count, squares, walltime, mean, alltimes,
- test, sys, reap, sow, warn = False,
- method = OptionValue[Method],
- fullout =
- TrueQ[MatchQ[OptionValue["PrintStats"], True | Automatic | Full]],
- csc = TrueQ[
- MatchQ[OptionValue["ClearSystemCache"], True | Automatic | Full]],
- block = OptionValue["BlockSize"] /. Full -> Scaled[1.0]},
- If[TrueQ[OptionValue["StoreAllTimings"]], reap = Reap; sow = Sow,
- reap = sow = Identity];
- alltimes = reap[walltime = AbsoluteTiming[Timing[
- If[csc, ClearSystemCache[]];
- (* Run once to estimate the timing *)
- sow[{time, out} = Timing[func]]; count = 1;
- (* If the timing is too small to reliable(ish), then replace with a small, averaged block *)
- If[Head[block] == Scaled && TrueQ[time <= .01],
- time = First[Timing[Do[func, {10}]]]/10; count = 10];
- squares = time^2;
- (* Use the first timing and option for Method to determing the structure of the loops *)
- Switch[method = OptionValue[Method],
- Automatic, Which[
- time < .2, method = {"MinTime", .5}; test := time < method[[2]],
- time < 2, method = {"MinTime", 4}; test := time < method[[2]],
- 2 <= time <= 5, method = {"MinNum", 3};
- test := count < method[[2]],
- time > 5, Message[TimeAv::longtime, EngineeringForm[time, 3]];
- Throw[{time, out}, TimeAv]],
- {"MinTime", _?Positive}, test := time < method[[2]],
- {"MinNum", _?Positive}, test := count < method[[2]],
- _, Message[TimeAv::badopt, method, Method]; Throw[$Failed, TimeAv]];
- Switch[block,
- _Integer?Positive, Null,
- Scaled[s_ /; 0 < s <= 1], Switch[method[[1]],
- "MinTime", block = Ceiling[1.1 Abs[N @@ block] method[[2]]/Max[{time, 1*^-5}]],
- "MinNum", block = Ceiling[1.1 Abs[N @@ block] method[[2]]]],
- _, If[TrueQ[Chop[N[block]] > 0], block = Ceiling[Chop[N[block]]],
- Message[TimeAv::badopt, method, "BlockSize"];
- Throw[$Failed, TimeAv]]];
- (* Throw away test case if time spent on it is small and block size is large *)
- If[block > 1 && time < 1, time = count = squares = 0];
- (* Loop starts here *)
- While[test,
- If[csc, ClearSystemCache[]];
- sow[{time2, out2} = Timing[Do[func, {block - 1}]; func]];
- time += time2; count += block; squares += (time2/block)^2;
- If[Not[warn] && out != out2, warn = True; Message[TimeAv::chres]]]]]];
- mean = time/count;
- (* The outputs *)
- If[TrueQ[OptionValue["StoreAllTimings"]],
- Print[TableForm[alltimes[[2]], TableDirections -> Row]]];
- If[fullout,
- Print["Total wall time is ", walltime[[1]],
- ", total cpu time is ", walltime[[2, 1]],
- " and total time spent evaluating the expression is ", time];
- Print["The expression was evaluated ", count, " time",
- If[count == 1, "", "s"], ", ",
- Sequence @@
- If[block == 1, {"without any blocking of the runs."}, {"in blocks of ",
- block, " runs."}], " This yields a mean timing of ", mean,
- Sequence @@ Which[
- count/block == 1, { " with no statistics on the standard deviation"},
- block == 1, {" with a standard deviation of ", Sqrt[squares/count - mean^2]},
- True, {" with a blocked standard deviation of ", Sqrt[squares/(count/block) - mean^2]}], "."]];
- {mean(*{mean,count,block,time,squares}*), out}], TimeAv]
- Protect[TimeAv];
- (* Note that clearing the system cache is quite slow. *)
- (* So for the small, fast timings that TimeAv is made for, *)
- (* it's best to leave that option off. *)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement