Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2@file 

3@brief Measures speed. 

4""" 

5import sys 

6from timeit import Timer 

7 

8 

9def measure_time(stmt, context, repeat=10, number=50, div_by_number=False): 

10 """ 

11 Measures a statement and returns the results as a dictionary. 

12 

13 @param stmt string 

14 @param context variable to know in a dictionary 

15 @param repeat average over *repeat* experiment 

16 @param number number of executions in one row 

17 @param div_by_number divide by the number of executions 

18 @return dictionary 

19 

20 .. runpython:: 

21 :showcode: 

22 

23 from cpyquickhelper.numbers import measure_time 

24 from math import cos 

25 

26 res = measure_time("cos(x)", context=dict(cos=cos, x=5.)) 

27 print(res) 

28 

29 See `Timer.repeat <https://docs.python.org/3/library/timeit.html?timeit.Timer.repeat>`_ 

30 for a better understanding of parameter *repeat* and *number*. 

31 The function returns a duration corresponding to 

32 *number* times the execution of the main statement. 

33 """ 

34 import numpy # pylint: disable=C0415 

35 tim = Timer(stmt, globals=context) 

36 res = numpy.array(tim.repeat(repeat=repeat, number=number)) 

37 if div_by_number: 

38 res /= number 

39 mean = numpy.mean(res) 

40 dev = numpy.mean(res ** 2) 

41 dev = (dev - mean**2) ** 0.5 

42 mes = dict(average=mean, deviation=dev, min_exec=numpy.min(res), 

43 max_exec=numpy.max(res), repeat=repeat, number=number) 

44 if 'values' in context: 

45 if hasattr(context['values'], 'shape'): 

46 mes['size'] = context['values'].shape[0] 

47 else: 

48 mes['size'] = len(context['values']) # pragma: no cover 

49 else: 

50 mes['context_size'] = sys.getsizeof(context) 

51 return mes 

52 

53 

54def _fcts(): 

55 """ 

56 Returns functions to measure. 

57 """ 

58 import numpy # pylint: disable=C0415 

59 from .cbenchmark_dot import vector_dot_product # pylint: disable=E0611,C0415 

60 from .cbenchmark_dot import vector_dot_product16 # pylint: disable=E0611,C0415 

61 from .cbenchmark_dot import vector_dot_product16_nofcall # pylint: disable=E0611,C0415 

62 from .cbenchmark_dot import vector_dot_product16_sse # pylint: disable=E0611,C0415 

63 

64 def simple_dot(values): 

65 return numpy.dot(values, values) 

66 

67 def c11_dot(vect): 

68 return vector_dot_product(vect, vect) 

69 

70 def c11_dot16(vect): 

71 return vector_dot_product16(vect, vect) 

72 

73 def c11_dot16_nofcall(vect): 

74 return vector_dot_product16_nofcall(vect, vect) 

75 

76 def c11_dot16_sse(vect): 

77 return vector_dot_product16_sse(vect, vect) 

78 

79 return [simple_dot, c11_dot, c11_dot16, c11_dot16_nofcall, c11_dot16_sse] 

80 

81 

82def check_speed(dims=[100000], repeat=10, number=50, fLOG=print): # pylint: disable=W0102 

83 """ 

84 Prints out some information about speed computation 

85 of this laptop. See :ref:`cbenchmarkbranchingrst` to compare. 

86 

87 @param dims sets of dimensions to try 

88 @param repeat average over *repeat* experiment 

89 @param number number of execution in one row 

90 @param fLOG logging function 

91 @return iterator on results 

92 

93 :epkg:`numpy` is multithreaded. For an accurate comparison, 

94 this needs to be disabled. This can be done by setting environment variable 

95 ``MKL_NUM_THREADS=1`` or by running: 

96 

97 :: 

98 

99 import mkl 

100 mkl.set_num_threads(1) 

101 

102 .. index:: MKL_NUM_THREADS 

103 

104 One example of use: 

105 

106 .. runpython:: 

107 :showcode: 

108 

109 from cpyquickhelper.numbers import check_speed 

110 res = list(check_speed(dims=[100, 1000])) 

111 import pprint 

112 pprint.pprint(res) 

113 """ 

114 import numpy # pylint: disable=C0415 

115 fcts = _fcts() 

116 mx = max(dims) 

117 vect = numpy.ones((mx,)) 

118 for i in range(0, vect.shape[0]): 

119 vect[i] = i 

120 for i in dims: 

121 values = vect[:i].copy() 

122 for fct in fcts: 

123 ct = {fct.__name__: fct} 

124 ct['values'] = values 

125 t = measure_time("{0}(values)".format(fct.__name__), 

126 repeat=repeat, number=number, context=ct) 

127 t['name'] = fct.__name__ 

128 if fLOG: 

129 fLOG(t) 

130 yield t