由于使用了对象类型声明,这种扩展类型在多大程度上可能效率低下



我被告知,由于使用DefaultDict需要Python对象类型声明,以下扩展类型可能不是很有效。有人能解释为什么会这样吗?DefaultDict是否仍然值得使用(而不是dict)?

cdef class CythonClass(object):
cdef int var1, var2
cdef object defaultdict
def __init__(self, a, b):
self.var1 = a
self.var2 = b
self.defaultdict = DefaultDict(DefaultDict([]))

我可能在另一个答案中夸大了效率部分。我的意思是:当你必须使用Python对象时,不要期望巨大的加速(超过1.5-2倍)。

你可以使用它们,而且不会比在python代码中使用它们慢(除了极少数情况)。然而,Cython的强大之处在于,您可以使用原生c类型和同构数据结构,如c数组(这可能比python列表甚至字典快得多),或者如果您使用c++,也可以使用vectorunordered_map等。

处理Python对象时需要记住的一点是,所有Python对象都是指向某些结构的指针,因此每个对象都添加了一层间接层-对于Pythonints也是如此。然而,Cythonint是一个没有间接层的C整数。这就是为什么Cython中的for-循环要快得多的主要原因之一。(然而,它们被限制在64位的范围内,而不是像Python中那样精度无限,这是一种权衡)。

另一点是,对python对象进行操作意味着您需要进行python查找、python操作等。然而,对于内置对象,cython可以使用python C API来避免基于python的查找,从而获得额外的速度(我猜DefaultDict不在其中),例如,对于声明的dicts,以下代码的编译方式不同:

def dumb_func(dict dct, str key):
return dct[key]   # translates to: __Pyx_PyDict_GetItem(__pyx_v_dct, __pyx_v_key)

def dumb_func(object dct, object key):  # different signature
return dct[key]   # translates to: PyObject_GetItem(__pyx_v_dct, __pyx_v_key)

您可能会猜测哪一个更快,是直接寻址dict的(__Pyx_PyDict_GetItem可能是PyDict_GetItemPyDict_GetItemString的复杂包装器),还是只使用PyObject_GetItem寻址python对象的(通过python查找)。这也不会是一个巨大的加速,但它是值得注意的。

最后,我要说的是,在Cython代码中,正常(和声明的)dicts显然比DefaultDict快(除了一些C或C++类)。

相关内容

最新更新