Bitshifts and "And" vs Floor-division and Modular
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Thu Sep 6 22:23:51 EDT 2012
On Thu, 06 Sep 2012 18:30:48 -0700, jimbo1qaz wrote:
> OK, I decided to change my code. Which raises a similar question: Which
> one is better for setting a bit of a byte: |= or +=, assuming each will
> only be run once? Intuitively, I think |=
Python (like most languages) doesn't have a "set this bit" operator, so
the closest match is a bitwise-or. So to set a bit of a byte, the
operation which most closely matches the programmer's intention is to use
the bitwise operator.
Even better would be to write a function called "setBit", and use that.
> but some timeits are inconclusive,
Timing results are usually inconclusive because the difference between
the results are much smaller than that average random noise on any
particular result.
All modern computers, say for the last 20 or 30 years, have used
multitasking operating systems. This means that at any time you could
have dozens, even hundreds, of programs running at once, with the
operating system switching between them faster than you can blink.
In addition, the time taken by an operation can depend on dozens of
external factors, such as whether the data is already in a CPU cache,
whether CPU prediction has pre-fetched the instructions needed,
pipelines, memory usage, latency when reading from disks, and many
others.
Consequently, timing results are very *noisy* -- the *exact* same
operation can take different amount of time from one run to the next.
Sometimes *large* differences.
So any time you time a piece of code, what you are *actually* getting is
not the amount of time that code takes to execute, but something slightly
more. (And, occasionally, something a lot more.) Note that it is always
slightly more -- by definition, it will never be less.
So if you want a better estimate of the actual time taken to execute the
code, you should repeat the measurement as many times as you can bear,
and pick the smallest value.
*Not* the average, since the errors are always positive. An average just
gives you the "true" time plus some unknown average error, which may not
be small. The minimum gives you the "true" time plus some unknown but
hopefully small error.
The smaller the amount of time you measure, the more likely that it will
be disrupted by some external factor. So timeit takes a code snippet and
runs it many times (by default, one million times), and returns the total
time used. Even if one or two of those runs were blown out significantly,
the total probably won't be. (Unless of course your anti-virus decided to
start running, and *everything* slows down for 10 minutes, or something
like that.)
But even that total time returned by timeit is almost certainly wrong. So
you should call the repeat method, with as many iterations as you can
bear to wait for, and take the minimum, which will still be wrong but it
will be less wrong.
And remember, the result you get is only valid for *your* computer,
running the specific version of Python you have, under the specific
operating system. On another computer with a different CPU or a different
OS, the results may be *completely* different.
Are you still sure you care about shaving off every last nanosecond?
> mainly because I don't know how it works.
The internal details of how timeit works are complicated, but it is worth
reading the comments and documentation, both in the Fine Manual and in
the source code:
http://docs.python.org/library/timeit.html
http://hg.python.org/cpython/file/2.7/Lib/timeit.py
--
Steven
More information about the Python-list
mailing list