【问题标题】:Some standard C library math operations don't play nice with noGIL一些标准 C 库数学运算不能与 noGIL 配合使用
【发布时间】:2018-07-26 18:18:00
【问题描述】:

我有一个包含以下代码的 pyx 文件:

cimport cython
from libc.math cimport sqrt, abs
from libc.stdio cimport printf
from cython.parallel import prange

cdef double my_abs(double a):
    return sqrt(a*a)

cpdef loop(int a):
    cdef int i
    cdef int sum = 0
    for i in prange(a, nogil=True):
        printf("%s %i %s %f\n", "The square root of ", i, " is ", sqrt(i))
        #printf("%s %i %s %f\n", "The absolute value of ", i, " is ", abs(i))
        #printf("%s %i %s %f\n", "The absolute value of ", i, " is ", my_abs(i))
    return

当我取消注释循环中的两行中的任何一行时,编译失败。

  1. 为什么 libc.math abs 函数不能与 nogil 配合得很好,而 sqrt、pow 等其他函数似乎可以?
  2. 我必须在我的函数(和 .pxd 文件)中添加什么才能使它成为 nog​​il?我已尝试在此页面后添加https://lbolla.info/python-threads-cython-gil,但仍然无法编译。

这个问题类似于:

提前致谢!

【问题讨论】:

    标签: cython gil


    【解决方案1】:

    abs isn't in the C standard library math.h:

    这些便利的 abs 重载不包括 C++。在 C 中,abs 仅在 in 中声明(并对 int 值进行操作)。

    我有点惊讶 Cython 没有抱怨你 cimporting 一些不存在的东西,但它将使用 Python abs builtin(或可能稍微优化的 Cython 等效项)。

    你想要fabs

    【讨论】:

    • 这当然可以解释!谢谢!关于第二部分的任何想法?我对此进行了一些研究,但无法弄清楚语法。
    • 如果是my_abs,你想做nogil你就写cdef double my_abs(double x) nogil:
    【解决方案2】:

    正如@DawidW 已经指出的那样,您应该使用math.h 中的fabs

    我想详细说明一下原因(据我了解):

    1. 这可能是一个错误:他们可以从任何地方cimportabscythonnumpy 等等。或者根本不导入它 - 这仍然是内置的 abs
    2. Cython 尝试通过 C 对应的内置函数替换 Python 功能,整个列表 is here。根据输入的类型使用Python-abs、C-absfabsfabsf等。

    例如:

    %%cython 
    from numpy cimport abs  # just for fun, "cimport" abs from numpy!     
    cdef do_abs(object o, int i, double d):
        print(abs(o))  
        print(abs(i))
        print(abs(d))
    

    在这里,自动:

    1. abs(o) 被翻译成__Pyx_PyNumber_Absolute(Python 的功能)
    2. abs(i)stdlib.h 翻译成abs
    3. abs(d)math.h 转换为 fabs

    在 2. 和 3. gil 的情况下不需要,但是从 Cython 的角度来看,Python-abs 正在使用中(即使它被映射到不同的函数),它没有被定义为“nogil”和因此需要 gil。

    如果我们真的 cimport abs from clib.stdlib 会发生什么?

    %%cython 
    from libc.stdlib cimport abs
    cdef do_abs(object o, int i, double d):
        print(abs(o))
        print(abs(i))
        print(abs(d))
    

    我们得到:

    1. Cython 尝试将 o 强制转换为 C 整数(在运行时可能会失败)并在其结果上调用 C-abs
    2. 使用 C-abs 表示整数 i
    3. 无法编译,因为 Cython 阻止将 double 值用作整数(这是一件好事,因为 C 编译器只是将双精度值转换为整数(如果幸运的话,会发出警告))。

    主要区别:使用 abs 作为整数参数现在允许 nogil。


    您的代码中有些无关的 cmets:

    A.定义 cdef double my_abs(double a) nogil 以便能够将其用作 nogil 部分。

    B.我不确定,当您将 python 对象作为 varargin 传递时,Cython 是否正确理解所有内容,因为它应该如何推断 Python 对象应该被强制转换为的正确类型?最好通过显式强制转换来帮助它,例如:

    printf("%d %s", abs(i), <char *>"\n")
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 1970-01-01
      • 2017-08-05
      • 2013-07-12
      • 1970-01-01
      • 2011-06-16
      • 1970-01-01
      相关资源
      最近更新 更多