~paparazzi-uav/paparazzi/v5.0-manual

« back to all changes in this revision

Viewing changes to sw/ext/opencv_bebop/opencv/doc/py_tutorials/py_core/py_optimization/py_optimization.markdown

  • Committer: Paparazzi buildbot
  • Date: 2016-05-18 15:00:29 UTC
  • Revision ID: felix.ruess+docbot@gmail.com-20160518150029-e8lgzi5kvb4p7un9
Manual import commit 4b8bbb730080dac23cf816b98908dacfabe2a8ec from v5.0 branch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
Performance Measurement and Improvement Techniques {#tutorial_py_optimization}
 
2
==================================================
 
3
 
 
4
Goal
 
5
----
 
6
 
 
7
In image processing, since you are dealing with large number of operations per second, it is
 
8
mandatory that your code is not only providing the correct solution, but also in the fastest manner.
 
9
So in this chapter, you will learn
 
10
 
 
11
-   To measure the performance of your code.
 
12
-   Some tips to improve the performance of your code.
 
13
-   You will see these functions : **cv2.getTickCount**, **cv2.getTickFrequency** etc.
 
14
 
 
15
Apart from OpenCV, Python also provides a module **time** which is helpful in measuring the time of
 
16
execution. Another module **profile** helps to get detailed report on the code, like how much time
 
17
each function in the code took, how many times the function was called etc. But, if you are using
 
18
IPython, all these features are integrated in an user-friendly manner. We will see some important
 
19
ones, and for more details, check links in **Additional Resouces** section.
 
20
 
 
21
Measuring Performance with OpenCV
 
22
---------------------------------
 
23
 
 
24
**cv2.getTickCount** function returns the number of clock-cycles after a reference event (like the
 
25
moment machine was switched ON) to the moment this function is called. So if you call it before and
 
26
after the function execution, you get number of clock-cycles used to execute a function.
 
27
 
 
28
**cv2.getTickFrequency** function returns the frequency of clock-cycles, or the number of
 
29
clock-cycles per second. So to find the time of execution in seconds, you can do following:
 
30
@code{.py}
 
31
e1 = cv2.getTickCount()
 
32
# your code execution
 
33
e2 = cv2.getTickCount()
 
34
time = (e2 - e1)/ cv2.getTickFrequency()
 
35
@endcode
 
36
We will demonstrate with following example. Following example apply median filtering with a kernel
 
37
of odd size ranging from 5 to 49. (Don't worry about what will the result look like, that is not our
 
38
goal):
 
39
@code{.py}
 
40
img1 = cv2.imread('messi5.jpg')
 
41
 
 
42
e1 = cv2.getTickCount()
 
43
for i in xrange(5,49,2):
 
44
    img1 = cv2.medianBlur(img1,i)
 
45
e2 = cv2.getTickCount()
 
46
t = (e2 - e1)/cv2.getTickFrequency()
 
47
print t
 
48
 
 
49
# Result I got is 0.521107655 seconds
 
50
@endcode
 
51
@note You can do the same with time module. Instead of cv2.getTickCount, use time.time() function.
 
52
Then take the difference of two times.
 
53
 
 
54
Default Optimization in OpenCV
 
55
------------------------------
 
56
 
 
57
Many of the OpenCV functions are optimized using SSE2, AVX etc. It contains unoptimized code also.
 
58
So if our system support these features, we should exploit them (almost all modern day processors
 
59
support them). It is enabled by default while compiling. So OpenCV runs the optimized code if it is
 
60
enabled, else it runs the unoptimized code. You can use **cv2.useOptimized()** to check if it is
 
61
enabled/disabled and **cv2.setUseOptimized()** to enable/disable it. Let's see a simple example.
 
62
@code{.py}
 
63
# check if optimization is enabled
 
64
In [5]: cv2.useOptimized()
 
65
Out[5]: True
 
66
 
 
67
In [6]: %timeit res = cv2.medianBlur(img,49)
 
68
10 loops, best of 3: 34.9 ms per loop
 
69
 
 
70
# Disable it
 
71
In [7]: cv2.setUseOptimized(False)
 
72
 
 
73
In [8]: cv2.useOptimized()
 
74
Out[8]: False
 
75
 
 
76
In [9]: %timeit res = cv2.medianBlur(img,49)
 
77
10 loops, best of 3: 64.1 ms per loop
 
78
@endcode
 
79
See, optimized median filtering is \~2x faster than unoptimized version. If you check its source,
 
80
you can see median filtering is SIMD optimized. So you can use this to enable optimization at the
 
81
top of your code (remember it is enabled by default).
 
82
 
 
83
Measuring Performance in IPython
 
84
--------------------------------
 
85
 
 
86
Sometimes you may need to compare the performance of two similar operations. IPython gives you a
 
87
magic command %timeit to perform this. It runs the code several times to get more accurate results.
 
88
Once again, they are suitable to measure single line codes.
 
89
 
 
90
For example, do you know which of the following addition operation is better, x = 5; y = x\*\*2,
 
91
x = 5; y = x\*x, x = np.uint8([5]); y = x\*x or y = np.square(x) ? We will find it with %timeit in
 
92
IPython shell.
 
93
@code{.py}
 
94
In [10]: x = 5
 
95
 
 
96
In [11]: %timeit y=x**2
 
97
10000000 loops, best of 3: 73 ns per loop
 
98
 
 
99
In [12]: %timeit y=x*x
 
100
10000000 loops, best of 3: 58.3 ns per loop
 
101
 
 
102
In [15]: z = np.uint8([5])
 
103
 
 
104
In [17]: %timeit y=z*z
 
105
1000000 loops, best of 3: 1.25 us per loop
 
106
 
 
107
In [19]: %timeit y=np.square(z)
 
108
1000000 loops, best of 3: 1.16 us per loop
 
109
@endcode
 
110
You can see that, x = 5 ; y = x\*x is fastest and it is around 20x faster compared to Numpy. If you
 
111
consider the array creation also, it may reach upto 100x faster. Cool, right? *(Numpy devs are
 
112
working on this issue)*
 
113
 
 
114
@note Python scalar operations are faster than Numpy scalar operations. So for operations including
 
115
one or two elements, Python scalar is better than Numpy arrays. Numpy takes advantage when size of
 
116
array is a little bit bigger.
 
117
 
 
118
We will try one more example. This time, we will compare the performance of **cv2.countNonZero()**
 
119
and **np.count_nonzero()** for same image.
 
120
 
 
121
@code{.py}
 
122
In [35]: %timeit z = cv2.countNonZero(img)
 
123
100000 loops, best of 3: 15.8 us per loop
 
124
 
 
125
In [36]: %timeit z = np.count_nonzero(img)
 
126
1000 loops, best of 3: 370 us per loop
 
127
@endcode
 
128
See, OpenCV function is nearly 25x faster than Numpy function.
 
129
 
 
130
@note Normally, OpenCV functions are faster than Numpy functions. So for same operation, OpenCV
 
131
functions are preferred. But, there can be exceptions, especially when Numpy works with views
 
132
instead of copies.
 
133
 
 
134
More IPython magic commands
 
135
---------------------------
 
136
 
 
137
There are several other magic commands to measure the performance, profiling, line profiling, memory
 
138
measurement etc. They all are well documented. So only links to those docs are provided here.
 
139
Interested readers are recommended to try them out.
 
140
 
 
141
Performance Optimization Techniques
 
142
-----------------------------------
 
143
 
 
144
There are several techniques and coding methods to exploit maximum performance of Python and Numpy.
 
145
Only relevant ones are noted here and links are given to important sources. The main thing to be
 
146
noted here is that, first try to implement the algorithm in a simple manner. Once it is working,
 
147
profile it, find the bottlenecks and optimize them.
 
148
 
 
149
-#  Avoid using loops in Python as far as possible, especially double/triple loops etc. They are
 
150
    inherently slow.
 
151
2.  Vectorize the algorithm/code to the maximum possible extent because Numpy and OpenCV are
 
152
    optimized for vector operations.
 
153
3.  Exploit the cache coherence.
 
154
4.  Never make copies of array unless it is needed. Try to use views instead. Array copying is a
 
155
    costly operation.
 
156
 
 
157
Even after doing all these operations, if your code is still slow, or use of large loops are
 
158
inevitable, use additional libraries like Cython to make it faster.
 
159
 
 
160
Additional Resources
 
161
--------------------
 
162
 
 
163
-#  [Python Optimization Techniques](http://wiki.python.org/moin/PythonSpeed/PerformanceTips)
 
164
2.  Scipy Lecture Notes - [Advanced
 
165
    Numpy](http://scipy-lectures.github.io/advanced/advanced_numpy/index.html#advanced-numpy)
 
166
3.  [Timing and Profiling in IPython](http://pynash.org/2013/03/06/timing-and-profiling.html)
 
167
 
 
168
Exercises
 
169
---------