Similar to the way tables are set up in HTML.
Constructing buttons with command=func(args) will call the function too early, but
command=lambda: func(args) will not. See
Is more in keeping with the Python philosophy.
PySide can do it this way too, if you have to.
27
Improving speed
Contents
Running things faster
Parallelisation
Using the ‘
multiprocessing
’ module
Using data queues
Writing faster modules
Pure Python implementation
NumPy implementation
C implementation
Cython implementation
Speed comparison of implementations
The ‘
ctypes
’ module
Running things faster
This chapter is all about how to make Python programs run faster. We will discuss
optimising existing routines so that they take a shorter amount of time to run, above and
beyond the simple Python tips and tricks discussed earlier. Initially parallel computing,
where a job is split into parts and run concurrently on separate processors (or processing
cores), is discussed in a basic way. For this we use modules that are available from Python
2.6 and above, which allow programs to take account of multiple processing cores present
in a single computer. For the remainder of the chapter we will deal with improving the
performance of a single processing job.
At the end some timing results will be given so that the reader can see how much was
gained for the effort. For mathematical routines involving lots of loops it is not uncommon
to get speed improvements of better than tenfold. The fine details about the logic and
underlying algorithms of the examples used here will not be described; an example will be
taken from earlier in the book where such things are described fully. Also, which
particular example we have chosen is not especially important, other than the fact that it is
a computationally intensive one that takes a noticeable time to run. It should be noted that
this chapter comes with a ‘health warning’ for novice programmers, because the mainstay
of the optimisation will be to move away from Python. Some of the focus will be on the
low-level compiled language C, although it will be used in a way to provide a module that
can still be used directly inside Python programs. The details of the C language, and how
to compile it, will not be discussed and to actually learn
to program in C we recommend
further reading.
1
Nonetheless, if you have no experience with C we hope that we can
provide a basic appreciation of how it can help. We also consider Cython,
2
a C-like
extension to Python, which has made it possible to benefit from the speed of C without
having to necessarily deal with all the complexities of C. This is particularly powerful in
combination with using NumPy arrays.
Naturally, for an analysis of program speed we will be starting from something that is
already working correctly. Although with experience it is certainly possible to write
speedy code in the first instance, it is common to write a simple, slower pure Python
version of a program first and then optimise it afterwards: effectively making a working
prototype. Writing in regular Python is relatively efficient in terms of human effort, and
there is little point in optimising something that doesn’t do what is intended. Also, we
should be mindful that it may not be necessary to optimise at all; if a program takes only
0.1 seconds to run, the effort to improve speed may have no noticeable effect. Where a
program does take a while to run we generally do not need to optimise the speed of a
whole program. Usually there will be particular bottlenecks that can be optimised to good
effect, and optimising the remainder would make no significant difference. Commonly we
will find that regular Python is left unaltered to do the main program control, but that the
computationally intensive, more mathematical parts are optimised. Often this means
writing a separate fast module that is then embedded.
Parallelisation
Most computers these days have more than one central processing core. If we have a job
that can be split up into parts that can be run at the same time, we can exploit the multiple
processing capabilities and run things in parallel and so complete the overall task more
quickly.
3
Naturally this adds complexity to our code, but from Python version 2.6 there is
a convenient standard means of doing this using the multiprocessing module. When
considering running tasks with this module, we should consider how much
communication is needed between the parallel parts. In some cases, where a job frequently
needs to exchange information with other jobs, or is dependent on jobs being
synchronised, then we do not expect to get the full advantage of multiple processes, i.e.
using two cores does not always make things twice as fast. Thus the best speed gains come
(and are worth the extra coding effort) where a procedure can be easily split into fairly
discrete units.
Do'stlaringiz bilan baham: