lundi 30 mai 2016

Why are the "normal" methods for generating random integers so slow?

Not a maths major or a cs major, I just fool around with python (usually making scripts for simulations/theorycrafting on video games) and I discovered just how bad random.randint is performance wise. It's got me wondering why random.randint or random.randrange are used/made the way they are. I made a function that produces (for all intents and actual purposes) identical results to random.randint:

big_bleeping_float= (2**64 - 2)/(2**64 - 2)
def fastrandint(start, stop):
  return start + int(random.random() * (stop - start + big_bleeping_float))

There is a massive 180% speed boost using that to generate an integer in the range (inclusive) 0-65 compared to random.randrange(0, 66), the next fastest method.

>>> timeit.timeit('random.randint(0, 66)', setup='from numpy import random', number=10000)
0.03165552873121058

>>> timeit.timeit('random.randint(0, 65)', setup='import random', number=10000)
0.022374771118336412

>>> timeit.timeit('random.randrange(0, 66)', setup='import random', number=10000)
0.01937231027605435

>>> timeit.timeit('fastrandint(0, 65)', setup='import random; from fasterthanrandomrandom import fastrandint', number=10000)
0.0067909916844523755

Furthermore, the adaptation of this function as an alternative to random.choice is 75% faster, and I'm sure adding larger-than-one stepped ranges would be faster (although I didn't test that). For almost double the speed boost as using the fastrandint function you can simply write it inline:

>>> timeit.timeit('int(random.random() * (65 + big_bleeping_float))', setup='import random; big_bleeping_float= (2**64 - 2)/(2**64 - 2)', number=10000)
0.0037642723021917845

So in summary, why am I wrong that my function is a better, why is it faster if it is better, and is there a yet even faster way to do what I'm doing?




Aucun commentaire:

Enregistrer un commentaire