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

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

105 statements  

1import numpy as np 

2import bottleneck as bn 

3from .autotimeit import autotimeit 

4 

5__all__ = ["bench"] 

6 

7 

8def bench( 

9 shapes=[(100,), (1000, 1000), (1000, 1000), (1000, 1000), (1000, 1000)], 

10 axes=[0, 0, 0, 1, 1], 

11 nans=[False, False, True, False, True], 

12 dtype="float64", 

13 order="C", 

14 functions=None, 

15): 

16 """ 

17 Bottleneck benchmark. 

18 

19 Parameters 

20 ---------- 

21 shapes : list, optional 

22 A list of tuple shapes of input arrays to use in the benchmark. 

23 axes : list, optional 

24 List of axes along which to perform the calculations that are being 

25 benchmarked. 

26 nans : list, optional 

27 A list of the bools (True or False), one for each tuple in the 

28 `shapes` list, that tells whether the input arrays should be randomly 

29 filled with one-fifth NaNs. 

30 dtype : str, optional 

31 Data type string such as 'float64', which is the default. 

32 order : {'C', 'F'}, optional 

33 Whether to store multidimensional data in C- or Fortran-contiguous 

34 (row- or column-wise) order in memory. 

35 functions : {list, None}, optional 

36 A list of strings specifying which functions to include in the 

37 benchmark. By default (None) all functions are included in the 

38 benchmark. 

39 

40 Returns 

41 ------- 

42 A benchmark report is printed to stdout. 

43 

44 """ 

45 

46 if len(shapes) != len(nans): 

47 raise ValueError("`shapes` and `nans` must have the same length") 

48 if len(shapes) != len(axes): 

49 raise ValueError("`shapes` and `axes` must have the same length") 

50 

51 # Header 

52 print("Bottleneck performance benchmark") 

53 print(" Bottleneck %s; Numpy %s" % (bn.__version__, np.__version__)) 

54 print(" Speed is NumPy time divided by Bottleneck time") 

55 print(" NaN means approx one-fifth NaNs; %s used" % str(dtype)) 

56 

57 print("") 

58 header = [" " * 11] 

59 for nan in nans: 

60 if nan: 

61 header.append("NaN".center(11)) 

62 else: 

63 header.append("no NaN".center(11)) 

64 print("".join(header)) 

65 header = ["".join(str(shape).split(" ")).center(11) for shape in shapes] 

66 header = [" " * 12] + header 

67 print("".join(header)) 

68 header = ["".join(("axis=" + str(axis)).split(" ")).center(11) for axis in axes] 

69 header = [" " * 12] + header 

70 print("".join(header)) 

71 

72 suite = benchsuite(shapes, dtype, nans, axes, order, functions) 

73 for test in suite: 

74 name = test["name"].ljust(12) 

75 fmt = name + "%7.1f" + "%11.1f" * (len(shapes) - 1) 

76 speed = timer(test["statements"], test["setups"]) 

77 print(fmt % tuple(speed)) 

78 

79 

80def timer(statements, setups): 

81 speed = [] 

82 if len(statements) != 2: 

83 raise ValueError("Two statements needed.") 

84 for setup in setups: 

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

86 t0 = autotimeit(statements[0], setup) 

87 t1 = autotimeit(statements[1], setup) 

88 speed.append(t1 / t0) 

89 return speed 

90 

91 

92def getarray(shape, dtype, nans, order): 

93 a = np.arange(np.prod(shape), dtype=dtype) 

94 if nans and issubclass(a.dtype.type, np.inexact): 

95 a[::5] = np.nan 

96 rs = np.random.RandomState(shape) 

97 rs.shuffle(a) 

98 return np.array(a.reshape(*shape), order=order) 

99 

100 

101def benchsuite(shapes, dtype, nans, axes, order, functions): 

102 

103 suite = [] 

104 

105 def getsetups(setup, shapes, nans, axes, dtype, order): 

106 template = """ 

107 from bottleneck.benchmark.bench import getarray 

108 a = getarray(%s, '%s', %s, '%s') 

109 axis=%s 

110 %s""" 

111 setups = [] 

112 for shape, axis, nan in zip(shapes, axes, nans): 

113 s = template % ( 

114 str(shape), 

115 str(dtype), 

116 str(nan), 

117 str(order), 

118 str(axis), 

119 setup, 

120 ) 

121 s = "\n".join([line.strip() for line in s.split("\n")]) 

122 setups.append(s) 

123 return setups 

124 

125 # non-moving window functions 

126 funcs = bn.get_functions("reduce", as_string=True) 

127 funcs += ["rankdata", "nanrankdata"] 

128 for func in funcs: 

129 if functions is not None and func not in functions: 

130 continue 

131 run = {} 

132 run["name"] = func 

133 run["statements"] = ["bn_func(a, axis)", "sl_func(a, axis)"] 

134 setup = """ 

135 from bottleneck import %s as bn_func 

136 try: from numpy import %s as sl_func 

137 except ImportError: from bottleneck.slow import %s as sl_func 

138 if "%s" == "median": from bottleneck.slow import median as sl_func 

139 """ % ( 

140 func, 

141 func, 

142 func, 

143 func, 

144 ) 

145 run["setups"] = getsetups(setup, shapes, nans, axes, dtype, order) 

146 suite.append(run) 

147 

148 # partition, argpartition 

149 funcs = ["partition", "argpartition"] 

150 for func in funcs: 

151 if functions is not None and func not in functions: 

152 continue 

153 run = {} 

154 run["name"] = func 

155 run["statements"] = ["bn_func(a, n, axis)", "sl_func(a, n, axis)"] 

156 setup = """ 

157 from bottleneck import %s as bn_func 

158 from bottleneck.slow import %s as sl_func 

159 if axis is None: n = a.size 

160 else: n = a.shape[axis] - 1 

161 n = max(n // 2, 0) 

162 """ % ( 

163 func, 

164 func, 

165 ) 

166 run["setups"] = getsetups(setup, shapes, nans, axes, dtype, order) 

167 suite.append(run) 

168 

169 # replace, push 

170 funcs = ["replace", "push"] 

171 for func in funcs: 

172 if functions is not None and func not in functions: 

173 continue 

174 run = {} 

175 run["name"] = func 

176 if func == "replace": 

177 run["statements"] = ["bn_func(a, nan, 0)", "slow_func(a, nan, 0)"] 

178 elif func == "push": 

179 run["statements"] = ["bn_func(a, 5, axis)", "slow_func(a, 5, axis)"] 

180 else: 

181 raise ValueError("Unknow function name") 

182 setup = """ 

183 from numpy import nan 

184 from bottleneck import %s as bn_func 

185 from bottleneck.slow import %s as slow_func 

186 """ % ( 

187 func, 

188 func, 

189 ) 

190 run["setups"] = getsetups(setup, shapes, nans, axes, dtype, order) 

191 suite.append(run) 

192 

193 # moving window functions 

194 funcs = bn.get_functions("move", as_string=True) 

195 for func in funcs: 

196 if functions is not None and func not in functions: 

197 continue 

198 run = {} 

199 run["name"] = func 

200 run["statements"] = ["bn_func(a, w, 1, axis)", "sw_func(a, w, 1, axis)"] 

201 setup = """ 

202 from bottleneck.slow.move import %s as sw_func 

203 from bottleneck import %s as bn_func 

204 w = a.shape[axis] // 5 

205 """ % ( 

206 func, 

207 func, 

208 ) 

209 run["setups"] = getsetups(setup, shapes, nans, axes, dtype, order) 

210 suite.append(run) 

211 

212 return suite