Warnings killing my performance

Kylotan kylotan at hotmail.com
Fri Feb 6 12:33:17 EST 2004


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?

And my second is, is there a quick way of taking an integer, shifting
it left 13 bits (or multiplying by 2 ** 13, whatever), discarding any
excess bits, and which won't cause a warning?

Lastly, a suggestion; if 2.4 will introduce an automatic promotion to
a long as a result of this shift operation, will the standard library
provide a C implementation of the lossy shift operator for those of us
that would benefit from a quick version? I'm guessing that promoting
it to a long and then getting it back to a normal int is not exactly
the speediest operation.

-- 
Ben Sizer



More information about the Python-list mailing list