Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/bottleneck/benchmark/bench_detailed.py: 12%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

67 statements  

1import numpy as np 

2import bottleneck as bn 

3from .autotimeit import autotimeit 

4 

5__all__ = ["bench_detailed"] 

6 

7 

8def bench_detailed(function="nansum", fraction_nan=0.0): 

9 """ 

10 Benchmark a single function in detail or, optionally, all functions. 

11 

12 Parameters 

13 ---------- 

14 function : str, optional 

15 Name of function, as a string, to benchmark. Default ('nansum') is 

16 to benchmark bn.nansum. If `function` is 'all' then detailed 

17 benchmarks are run on all bottleneck functions. 

18 fraction_nan : float, optional 

19 Fraction of array elements that should, on average, be NaN. The 

20 default (0.0) is not to set any elements to NaN. 

21 

22 Returns 

23 ------- 

24 A benchmark report is printed to stdout. 

25 

26 """ 

27 

28 if function == "all": 

29 # benchmark all bottleneck functions 

30 funcs = bn.get_functions("all", as_string=True) 

31 funcs.sort() 

32 for func in funcs: 

33 bench_detailed(func, fraction_nan) 

34 

35 if fraction_nan < 0 or fraction_nan > 1: 

36 raise ValueError("`fraction_nan` must be between 0 and 1, inclusive") 

37 

38 tab = " " 

39 

40 # Header 

41 print("%s benchmark" % function) 

42 print("%sBottleneck %s; Numpy %s" % (tab, bn.__version__, np.__version__)) 

43 print("%sSpeed is NumPy time divided by Bottleneck time" % tab) 

44 if fraction_nan == 0: 

45 print("%sNone of the array elements are NaN" % tab) 

46 else: 

47 print( 

48 "%s%.1f%% of the array elements are NaN (on average)" 

49 % (tab, fraction_nan * 100) 

50 ) 

51 print("") 

52 

53 print(" Speed Call Array") 

54 suite = benchsuite(function, fraction_nan) 

55 for test in suite: 

56 name = test["name"] 

57 speed = timer(test["statements"], test["setup"], test["repeat"]) 

58 print("%8.1f %s %s" % (speed, name[0].ljust(27), name[1])) 

59 

60 

61def timer(statements, setup, repeat): 

62 if len(statements) != 2: 

63 raise ValueError("Two statements needed.") 

64 with np.errstate(invalid="ignore"): 

65 t0 = autotimeit(statements[0], setup, repeat=repeat) 

66 t1 = autotimeit(statements[1], setup, repeat=repeat) 

67 speed = t1 / t0 

68 return speed 

69 

70 

71def benchsuite(function, fraction_nan): 

72 

73 # setup is called before each run of each function 

74 setup = """ 

75 from bottleneck import %s as bn_fn 

76 try: from numpy import %s as sl_fn 

77 except ImportError: from bottleneck.slow import %s as sl_fn 

78 

79 # avoid all-nan slice warnings from np.median and np.nanmedian 

80 if "%s" == "median": from bottleneck.slow import median as sl_fn 

81 if "%s" == "nanmedian": from bottleneck.slow import nanmedian as sl_fn 

82 

83 from numpy import array, nan 

84 from numpy.random import RandomState 

85 rand = RandomState(123).rand 

86 

87 a = %s 

88 if %s != 0: a[a < %s] = nan 

89 """ 

90 setup = "\n".join([s.strip() for s in setup.split("\n")]) 

91 

92 # what kind of function signature do we need to use? 

93 if function in bn.get_functions("reduce", as_string=True): 

94 index = 0 

95 elif function in ["rankdata", "nanrankdata"]: 

96 index = 0 

97 elif function in bn.get_functions("move", as_string=True): 

98 index = 1 

99 elif function in ["partition", "argpartition", "push"]: 

100 index = 2 

101 elif function == "replace": 

102 index = 3 

103 else: 

104 raise ValueError("`function` (%s) not recognized" % function) 

105 

106 # create benchmark suite 

107 instructions = get_instructions() 

108 f = function 

109 suite = [] 

110 for instruction in instructions: 

111 signature = instruction[index + 1] 

112 if signature is None: 

113 continue 

114 array = instruction[0] 

115 repeat = instruction[-1] 

116 run = {} 

117 run["name"] = [f + signature, array] 

118 run["statements"] = ["bn_fn" + signature, "sl_fn" + signature] 

119 run["setup"] = setup % (f, f, f, f, f, array, fraction_nan, fraction_nan) 

120 run["repeat"] = repeat 

121 suite.append(run) 

122 

123 return suite 

124 

125 

126def get_instructions(): 

127 

128 instructions = [ 

129 # 1d input array 

130 ( 

131 "rand(1)", 

132 "(a)", # reduce + (nan)rankdata 

133 "(a, 1)", # move 

134 "(a, 0)", # (arg)partition 

135 "(a, np.nan, 0)", # replace 

136 10, 

137 ), 

138 ("rand(10)", "(a)", "(a, 2)", "(a, 2)", "(a, np.nan, 0)", 10), 

139 ("rand(100)", "(a)", "(a, 20)", "(a, 20)", "(a, np.nan, 0)", 6), 

140 ("rand(1000)", "(a)", "(a, 200)", "(a, 200)", "(a, np.nan, 0)", 3), 

141 ("rand(1000000)", "(a)", "(a, 200)", "(a, 200)", "(a, np.nan, 0)", 2), 

142 # 2d input array 

143 ("rand(10, 10)", "(a)", "(a, 2)", "(a, 2)", "(a, np.nan, 0)", 6), 

144 ("rand(100, 100)", "(a)", "(a, 20)", "(a, 20)", "(a, np.nan, 0)", 3), 

145 ("rand(1000, 1000)", "(a)", "(a, 200)", "(a, 200)", "(a, np.nan, 0)", 2), 

146 ("rand(10, 10)", "(a, 1)", None, None, None, 6), 

147 ("rand(100, 100)", "(a, 1)", None, None, None, 3), 

148 ("rand(1000, 1000)", "(a, 1)", None, None, None, 2), 

149 ("rand(100000, 2)", "(a, 1)", "(a, 1)", "(a, 1)", None, 2), 

150 ("rand(10, 10)", "(a, 0)", None, None, None, 6), 

151 ("rand(100, 100)", "(a, 0)", "(a, 20, axis=0)", None, None, 3), 

152 ("rand(1000, 1000)", "(a, 0)", "(a, 200, axis=0)", None, None, 2), 

153 # 3d input array 

154 ( 

155 "rand(100, 100, 100)", 

156 "(a, 0)", 

157 "(a, 20, axis=0)", 

158 "(a, 20, axis=0)", 

159 None, 

160 2, 

161 ), 

162 ( 

163 "rand(100, 100, 100)", 

164 "(a, 1)", 

165 "(a, 20, axis=1)", 

166 "(a, 20, axis=1)", 

167 None, 

168 2, 

169 ), 

170 ( 

171 "rand(100, 100, 100)", 

172 "(a, 2)", 

173 "(a, 20, axis=2)", 

174 "(a, 20, axis=2)", 

175 "(a, np.nan, 0)", 

176 2, 

177 ), 

178 # 0d input array 

179 ("array(1.0)", "(a)", None, None, "(a, 0, 2)", 10), 

180 ] 

181 

182 return instructions