如何使独立编译的cython程序包使用共享的随机数生成器?

时间:2019-08-07 12:13:14

标签: python c cython cythonize

我有一种实验性编程语言,其中的程序被编译为c。我编写了一个cython包装器,该包装器包装了已编译的c代码,并允许从python调用它。这样,您就可以在python内部将编译后的程序用作快速的低级函数。通常,我们想在同一个python程序中使用多个这样的程序。然后,用于生成和导入每个程序的管道为:

  1. 使用编译器将程序编译为c。
  2. 使用gcc将c代码编译为.so共享对象。
  3. 生成一个.pyx包装器,该包装器可以从python访问我们要使用的c函数。
  4. 使用cythonize编译.pyx包装器以生成.so。
  5. 使用python的导入功能导入.so共享库。

在实践中,实际上将步骤1-4合并为一个单独的外部调用以使用sys进行制作,并且生成的Makefile执行这四个步骤中的每个步骤。这使我们可以通过sys的外部调用来调用make,然后无需离开python即可导入编译的程序。

一个已编译的程序可能具有概率构造。特别地,分支决策由随机数控制。为此,将调用c的本机

rand()

功能。当用python导入包装的编译程序时,将对使用cythonize生成的生成的.so共享对象进行导入调用。到目前为止,我已经尝试致电

srand(<long int>time(NULL)
在包装每个已编译程序的.pyx文件中

。据我所知,每个导入的.so都将有效地使用其自己的随机数生成器。但是从文档中对我来说还不是很清楚。

最终,我希望不同的.so使用相同的随机数生成器,但是我不知道该如何处理。任何指导将不胜感激。许多代码太长了,无法在此处包含,但是如果您想查看任何摘录(例如,“如何做x组件?”),我会很乐意。

即使您所能提供的只是解释如何用cythonize生成的不同共享对象之间的rand()调用如何交互,也可能使我有足够的精力来解决问题。

谢谢!

1 个答案:

答案 0 :(得分:2)

我不确定在C规范中是否明确定义了随机种子是在.so文件之间共享还是由个人共享(也就是说-我还没有阅读C标准,因此我在这里稍作猜测)。因此,您看到的行为可能取决于您所使用的平台。

最简单的方法是编写一个小的Cython模块,其唯一目的是处理随机数生成:

# cy_rand.pxd
cpdef void srand(unsigned int)
cpdef int rand()

# cy_rand.pyx
from libc cimport stdlib

cpdef void srand(unsigned int seed):
    stdlib.srand(seed)

cpdef int rand():
    return stdlib.rand()

我已经制作了函数cpdef,以便您也可以从Python调用它们。如果您不希望这样做,只需将它们设为cdef

您需要以常规方式编译此模块。在其他模块中,您可以执行以下操作:

cimport cy_rand

cy_rand.srand(1) # some seed
rand_val = cy_rand.rand()

这样,您便知道随机数仅在一个.so文件中生成。这会增加一小部分间接,因此比直接调用它要慢一些。因此,最好添加辅助函数来批量生成随机数(以提高速度)。

请注意,其他库可能会自己调用srandrand,并且由于它可能是全局状态,因此可能会影响您-这就是C标准库随机数生成器是以下原因之一”非常强大...