【问题标题】:How do I make independently compiled cython packages use a shared random number generator?如何使独立编译的 cython 包使用共享随机数生成器?
【发布时间】:2019-08-07 12:13:14
【问题描述】:

我有一种实验性的编程语言,程序被编译成 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 实际上被合并为一个外部调用 make 使用 sys,生成的 Makefile 执行这 4 个步骤中的每一个。这让我们可以通过外部调用 sys 来调用 make,然后在不离开 python 的情况下导入编译的程序。

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

rand()

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

srand(<long int>time(NULL)

来自包装每个已编译程序的 .pyx 文件。据我所知,每个导入的 .so 都将有效地使用自己的随机数生成器。但是从文档中我根本不清楚是否是这种情况。

最终我希望不同的 .so 使用相同的随机数生成器,但我不知道该怎么做。任何指导将不胜感激。大部分代码太长,无法包含在此处,但如果您想查看任何 sn-ps(例如,“你如何做 x 组件?”)我会很乐意提供。

即使您所能提供的只是对 rand() 的调用如何在 cythonize 生成的不同共享对象之间进行交互的解释,这也可能足以让我找到解决方案。

提前致谢!

【问题讨论】:

  • 你可以通过nm my_extension.so | grep rand查看,如果rand@@GLIB_XXX有属性U(很可能),那么它将由libc.so提供,并且状态在所有模块之间共享。

标签: python c cython cythonize


【解决方案1】:

我不确定 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 标准库随机数生成器不是非常健壮的原因之一。 ..

【讨论】:

  • 我认为 rand 是否在共享库中不是由标准来决定的:当扩展被链接时,它可以链接到 libc 的共享版本或静态版本(这很不寻常但可能)。
  • 这是一个非常中肯的建议,以后可以通过 c++11 的随机生成器轻松替换 rand/srand 对,或者推出手工制作的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多