您的初始假设是需要使用
reikna.cbrng.CBRNG
,这是正确的。它似乎提供了多种基于计数器的 RNG 的
伪随机源和
分布,这可能会让人感到困惑。它还提供了
快捷方式,用于创建具有给定分布的随机数生成器。请注意,文本中保留了 HTML 标签。
from reikna.core import Type
from reikna.cbrng import CBRNG
from reikna.cluda import any_api
import numpy as np
_api = any_api()
_thr = _api.Thread.create()
def reikna_norm_rng(seed, rows, cols, mean, std,
dtype=np.float32,
generators_dim=1):
"""
A do-all generator function for creating a new Computation
returning a stream of pseudorandom number arrays.
"""
randoms_arr = Type(dtype, (rows, cols))
rng = CBRNG.normal_bm(randoms_arr=randoms_arr,
generators_dim=generators_dim,
sampler_kwds=dict(mean=mean, std=std),
seed=abs(hash(seed)))
compiled_comp = rng.compile(_thr)
counters = _thr.to_device(rng.create_counters())
randoms = _thr.empty_like(compiled_comp.parameter.randoms)
while True:
compiled_comp(counters, randoms)
yield randoms.get()
要看到它的效果,请添加:
if __name__ == '__main__':
seed1 = '123'
seed2 = 'asd'
rows, cols = 100, 3
mu, sd = 0, 1
r1 = next(reikna_norm_rng(seed1, rows, cols, mu, sd))
r2 = next(reikna_norm_rng(seed2, rows, cols, mu, sd))
r3 = next(reikna_norm_rng(seed1, rows, cols, mu, sd))
r4 = next(reikna_norm_rng(seed2, rows, cols, mu, sd))
err1 = r1 - r3
err2 = r2 - r4
print("all(err1 == 0):", np.all(err1 == 0))
print("all(err2 == 0):", np.all(err2 == 0))
我也希望确保使用两个不同的种子生成的随机数没有相关性。
这取决于实现的质量。以下是使用种子0和1绘制出的2组数字的情况:
rng1 = reikna_norm_rng(0, 100, 10000, 0, 1)
rng2 = reikna_norm_rng(1, 100, 10000, 0, 1)
A = next(rng1)
B = next(rng2)
A_r = A.ravel()
B_r = B.ravel()
for i in range(0, A_r.size, 1000):
plot(A_r[i:i+1000], B_r[i:i+1000], 'b.')
![绘制(A, B)](https://istack.dev59.com/Ah9Q2.webp)
免责声明
这是我第一次使用reikna。上述代码可能无法及时释放资源和/或泄漏像筛子一样。它使用全局Thread
,这在较大的应用程序中可能不是您想要的。
附言
np.random.seed(seed)
np.random.normal(0, 1, (100, 3))
还可以生成形状为 (100, 3) 的正态分布随机数数组,尽管它不使用GPU。