Warnings killing my performance

Peter Otten __peter__ at web.de
Sat Feb 7 15:56:53 CET 2004


Kylotan wrote:

> I have the following code:
> 
> def IntToRandFloat(x):
>     """Given a 32-bit integer, return a float in [-1.0, 1.0]"""
>     x = int(x)
>     x = int(x << 13) ^ x
>     return
>     (1.0-((x*(x*x*15731+789221)+1376312589)&0x7fffffff)/1073741824.0)
> 
> 
> Basically it's a function directly copied from a C implementation. Now
> it appears that the line with the left-shift causes the "losing bits
> or changing sign will return a long in Python 2.4 and up" warning. All
> well and good - I explicitly cast it back to an int so that the code
> won't break when I upgrade Python. I also disable the warning using
> warnings.filterwarnings(action = 'ignore', etc).
> 
> However when the time comes to profile my app, I see lines like these:
> 
>          11266617 function calls in 488.717 CPU seconds
>    ncalls  tottime  percall  cumtime  percall
> filename:lineno(function)
>   3145728  129.744    0.000  364.845    0.000
> terraingen.py:22(IntToRandFloat)
>   3142872  150.484    0.000  235.101    0.000 warnings.py:24(warn)
>   3142872   84.617    0.000   84.617    0.000
> warnings.py:59(warn_explicit)
> 
> Now I obviously can't afford to have almost half my program time
> consumed by warnings that I don't want to see.
> 
> It gets stranger. If I change the shift line to this:
> x = int(x * (2 ** 13)) ^ x
> x = int(x | 0xFFFF)
> 
> ...it's still calling 'warn' once for each time IntToRandFloat is
> called, but I see no warning appear, even when I don't import warnings
> and disable any. I have no other imports (that i can see) which might
> be disabling a warning behind the scenes.
> 
> So I have these problems: warnings are slow (even when disabled),
> sometimes warnings are being issued and I never see them, and given
> that I never see the warnings I don't know how to get around them.
> 
> So, my first question is to ask if there is a more efficient way of
> disabling warnings?

Have you tried brute force?

...> timeit.py -s"import profwarn" "profwarn.IntToRandFloat(99)"
10000 loops, best of 3: 27.3 usec per loop

...> timeit.py -s"import profwarn;profwarn.disableWarnings()"
"profwarn.IntToRandFloat(99)"
100000 loops, best of 3: 7.8 usec per loop

with IntToRandFloat() copied* from your post and the following to entirely
disable warnings:

def disableWarnings():
    def _theevilunwarner(*args):
        pass
    import warnings
    warnings.warn = _theevilunwarner
    warnings.warn_explicit = _theevilunwarner 

I think the last line isn't necessary, but it won't do any (additional)
harm.

Peter

(*) Your email client seems to replace normal space with evil lookalikes, so
I had to delete and reinsert the entire whitespace.



More information about the Python-list mailing list