Python 3.x numpy实现自定义RNG
出于一致性原因,我正试图让numpy使用我自己的RNG in实现。根据我从numpy文档中找到的一些文档,我的理解是,我需要提供一个自定义的BitGenerator类,该类实现Python 3.x numpy实现自定义RNG,python-3.x,numpy,random,Python 3.x,Numpy,Random,出于一致性原因,我正试图让numpy使用我自己的RNG in实现。根据我从numpy文档中找到的一些文档,我的理解是,我需要提供一个自定义的BitGenerator类,该类实现random\u raw方法,然后使用np.random.Generator初始化,所以我尝试了以下方法: import numpy as np class TestBitGenerator(np.random.BitGenerator): def __init__(self): super().__init
random\u raw
方法,然后使用np.random.Generator
初始化,所以我尝试了以下方法:
import numpy as np
class TestBitGenerator(np.random.BitGenerator):
def __init__(self):
super().__init__(0)
self.counter = 0
def random_raw(self, size=None):
self.counter += 1
if size is None:
return self.counter
return np.full(n, self.counter)
mc_adapter = TestBitGenerator()
npgen = np.random.Generator(mc_adapter)
print(npgen.random())
这将导致一个segfault:
$ python bitgen.py
Segmentation fault (core dumped)
我假设我在这里遗漏了什么(来自TestBitGenerator?),有人能给我指出正确的方向吗
我尝试不将np.random.BitGenerator子类化,但得到了不同的错误:
对象没有属性“capsule”
我使用numpy 1.19.2和python 3.8.2进行了一些挖掘,生成器的构造函数如下所示:
def __init__(self, bit_generator):
self._bit_generator = bit_generator
capsule = bit_generator.capsule
cdef const char *name = "BitGenerator"
if not PyCapsule_IsValid(capsule, name):
raise ValueError("Invalid bit generator. The bit generator must "
"be instantiated.")
self._bitgen = (<bitgen_t *> PyCapsule_GetPointer(capsule, name))[0]
self.lock = bit_generator.lock
因此,据我所知,BitGenerator
的任何实现似乎都必须在cython中完成,任何试图在纯python(可能还有pybind11)中实现的尝试都不会奏效(?)
由于我不熟悉cython以及它是否/如何与pybind11共存,现在我只想确保我的每一个(并行)进程显式地调用np.random.Generator,并确定使用numpy RNG种子,这样它就独立于我自己的RNG蒸汽。实际上,如果使用库
RandomGen
包装它,您就可以用纯python完成它(这是当前np.random.Generator
的孵化器)。因此,有一个UserBitGenerator
只允许您使用python:
遗憾的是,这没有出现在
numpy
(或者如果是,我还没有找到它…。如果是出于一致性的原因,为什么不将种子设置为一致的值?这似乎与解释我的确切需求无关,因为它很复杂。我有一些C++代码(包括我的RNG),通过pybd11访问python,我在MPI上运行,我需要控制每个进程是如何被播种的,每个进程应该(理想地)使用一个从C++和Python层访问的单个随机流。如果你在代码中找到了限制,Nopy.Road。您可能希望在以下位置提交问题:。此外,NumPy文档中还提供了一个演示多线程随机生成工作原理的示例,以防您没有看到:
struct bitgen:
void *state
npy_uint64 (*next_uint64)(void *st) nogil
uint32_t (*next_uint32)(void *st) nogil
double (*next_double)(void *st) nogil
npy_uint64 (*next_raw)(void *st) nogil
ctypedef bitgen bitgen_t