Created
March 12, 2021 16:26
-
-
Save TransparentLC/e17eea3a82fd7590a717a6198d43dacd to your computer and use it in GitHub Desktop.
可播种的随机数生成器 xoshiro128**。如果只是为了生成随机 uint32 整数的话,Python 自带的 random.randint、random.randbytes 和 os.urandom 比它都快上不少。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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