Skip to content

Instantly share code, notes, and snippets.

@TransparentLC
Created March 12, 2021 16:26
Show Gist options
  • Save TransparentLC/e17eea3a82fd7590a717a6198d43dacd to your computer and use it in GitHub Desktop.
Save TransparentLC/e17eea3a82fd7590a717a6198d43dacd to your computer and use it in GitHub Desktop.
可播种的随机数生成器 xoshiro128**。如果只是为了生成随机 uint32 整数的话,Python 自带的 random.randint、random.randbytes 和 os.urandom 比它都快上不少。
import ctypes
class Xoshiro128ss:
def __init__(self, a: int, b: int, c: int, d: int):
self.s = tuple(ctypes.c_uint32(x) for x in (a, b, c, d))
self.t = ctypes.c_uint32()
self.r = ctypes.c_uint32()
def randInt(self) -> int:
s0, s1, s2, s3 = self.s
t = self.t
r = self.r
t.value = s1.value << 9
r.value = s1.value * 5
s2.value ^= s0.value
s3.value ^= s1.value
s1.value ^= s2.value
s0.value ^= s3.value
s2.value ^= t.value
s3.value = s3.value << 11 | s3.value >> 21
return ((r.value << 7 | r.value >> 25) * 9) & 0xFFFFFFFF
def randFloat(self) -> float:
return self.randInt() / 0xFFFFFFFF
if __name__ == '__main__':
import os
import random
import time
import typing
x = Xoshiro128ss(1, 2, 3, 4)
for i in range(10):
print(x.randInt())
for i in range(10):
print(x.randFloat())
def wrapperPerfCounter(fn: typing.Callable):
def wrapper(*args, **kwargs):
ts = time.perf_counter()
ret = fn(*args, **kwargs)
te = time.perf_counter()
print(fn.__name__, te - ts)
return ret
return wrapper
@wrapperPerfCounter
def benchXoshiro128ss(times: int):
x = Xoshiro128ss(
int(time.time()) ^ 0x67452301,
int(time.time()) ^ 0xEFCDAB89,
int(time.time()) ^ 0x98BADCFE,
int(time.time()) ^ 0x10325476,
)
for _ in range(times):
x.randInt()
@wrapperPerfCounter
def benchRandint(times: int):
for _ in range(times):
random.randint(0, 0xFFFFFFFF)
@wrapperPerfCounter
def benchRandbytes(times: int):
for _ in range(times):
int.from_bytes(random.randbytes(4), 'big')
@wrapperPerfCounter
def benchUrandom(times: int):
for _ in range(times):
int.from_bytes(os.urandom(4), 'big')
for bench in (
benchXoshiro128ss,
benchRandint,
benchRandbytes,
benchUrandom,
):
bench(10000000)
# Speed of generating random uint32
# xoshiro128ss: 1.0x (baseline)
# random.randint: 2.0x
# random.randbytes: 4.5x
# os.urandom: 6.1x
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment