为什么 Cython 将 cdef 类视为 python 对象?

问题描述 投票:0回答:1

我一直在尝试通过使用 prange 并行调用代码段内的函数来优化代码段。这要求 prange 块内的所有函数都使用 nogil 运行,因此我正在调整它们以不使用 gil。然而,当尝试调整其中一个函数时,我遇到了有关 Python 局部变量/临时变量的问题。功能如下:

cdef float output(Branch self):
        cdef float output = 0.0
        cdef Dendrite dendrite   # This line is considered a python Local
        cdef Branch branch       # This line is considered a python Local
        cdef int index = 0
        while index < self.length:
            if self.isDendrite:
                dendrite = self.inputs[index]
                output += dendrite.output()
            else:
                branch = self.inputs[index]
                output += branch.output()

            index += 1
        return self.activation.eval(output) * self.weight

尝试将函数转换为运行 nogil 时,cython 返回以下错误消息:

Function declared nogil has Python locals or temporaries

指向函数头。

对于上下文,这些是 Branch 和 Dendrite 类拥有的字段(Node 是 Dendrite 引用的另一个 cdef 类):

cdef class Branch():
    cdef:
        np.ndarray inputs     # holds either Dendrite or Branch objects (but never both)
        float weight
        floatFunc activation
        bint isDendrite       # used to determine if Dendrites or Branches are held
        int length

cdef class Dendrite():
    cdef:
        float charge
        Node owner            # the class below
        float weight
        np.ndarray links      # holds objects that rely on Node and Dendrite
        floatFunc activation  # C-optimized class
        int length

cdef class Node:
    cdef:
        float charge
        float SOMInhibition
        np.ndarray senders         # holds objects that rely on Node and Dendrite
        int numSenders
        np.ndarray position        # holds ints
        NodeType type              # this is just an enum
        np.ndarray dendrites       # this holds Dendrite objects
        int numDendrites
        np.ndarray inputDendrites  # holds Dendrite objects
        int numInputDendrites
        np.ndarray inputBranches   # holds Branch objects
        int numInputBranches
        int ID
        floatFunc activation       # C-optimized class

我的猜测是,这与类将 numpy 数组作为字段这一事实有关,但 numpy 与 cython 兼容,并且不应该创建 python 对象(如果我理解正确的话)。

如果有人有任何建议如何使这些行不被算作 python 对象,我将不胜感激。谢谢!

python parallel-processing cython gil
1个回答
0
投票

Numpy 具有 Python 和 C API,您甚至可以这样做:

import numpy as np
cimport numpy as cnp

无论如何,一般来说,类和函数调用的开销非常小(我知道 Cython 将它们标记为深黄色,意味着昂贵,但通常它们会被调用几次来处理数百万个项目,至少如果您正确设计了系统的话)。

尝试在 Python 中定义类和不常见的函数,并将内存视图传递给 Cython 来完成大部分计算。这样你就可以释放 GIL,因为内存视图不是 Python 对象,你不必担心将所有内容转换为 C++(如果这是你的目标,为什么不先用 C++ 编写,然后编写一个 Cython 包装器来使用它)图书馆?)。

© www.soinside.com 2019 - 2024. All rights reserved.