在Cython中做列表/字典的习惯方法?

我的问题:我发现使用STL映射和向量处理大型数据集与原始C ++通常可以比使用Cython快得多(并且内存占用更less)。

我认为这部分的速度损失是由于使用了Python列表和字典,并且在Cython中可能会有一些技巧使用较less的devise数据结构。 例如,这个页面( http://wiki.cython.org/tutorials/numpy )展示了如何通过预定义ND数组的大小和types来在Cython中快速生成numpy数组。

问题:有没有办法像列表/字典那样做类似的事情,例如大致说明你期望在其中有多less个元素或(键,值)对? 也就是说,有没有一种习惯的方法来将列表/字典转换为Cython中的(快速)数据结构?

如果没有,我想我只需要用C ++编写它,并包装在一个Cython导入。

现在Cython具有模板支持,并附带一些STL容器的声明。

请参阅http://docs.cython.org/src/userguide/wrapping_CPlusPlus.html#standard-library

以下是他们给出的例子:

from libcpp.vector cimport vector cdef vector[int] vect cdef int i for i in range(10): vect.push_back(i) for i in range(10): print vect[i] 

在Python中执行类似于C ++的操作往往会比较慢。 listdict实际上实现得很好,但是使用Python对象会比C ++对象抽象得多,并且在运行时需要更多的查找。

顺便说一下, std::vector的实现方式与list非常类似。 但是, std::map实际上是以某种方式实现的,因为它的大小越来越大,许多操作都比dict慢。 对于每个dict适当大的例子, dict克服了比std::map慢的固定因素,并且实际上会更快地执行诸如查找,插入等操作。

如果你想使用std::mapstd::vector ,没有什么能阻止你。 如果你想把它们暴露给Python,你将不得不自己包装它们。 如果这个包装消耗了你希望保存的所有或大部分时间,不要感到震惊。 我不知道任何工具,使你自动自动。

有一些C API调用来控制对象的创build。 你可以说“用至less这么多的元素做一个列表”,但是这并不能改善你的列表创build和填充操作的整体复杂性。 当您尝试更改列表时,它肯定不会改变太多。

我的一般build议是

  • 如果你想要一个固定大小的数组(你可以指定一个列表的大小),你可能真的想要一个像numpy数组一样的东西。

  • 我怀疑你会得到任何加速,你想使用std::vector list中的一个普通replace代码。 如果你想在幕后使用它,它可能会给你一个满意的大小和空间的改善(我当然不知道没有测量,也不是)。

  • dict实际上做得很好。 我绝对不会尝试在基于std::map Python中引入一个新的通用types,这对于许多重要的操作来说具有更差的algorithm复杂性,并且至less在一些实现中至less给用户留下了一些优化dict已经有了。

    如果我确实想要更像std::map ,我可能会使用数据库。 这通常是我所做的事情,如果我想存储在一个dict (或者说,我存储在list东西)的东西太大,我觉得在内存中的存储感觉舒适。 Python在stdlib中有sqlite3 ,而其他所有主要数据库的驱动程序都是可用的。

C ++是快速的,不仅仅是因为向量的静态声明和进入它的元素,而且关键是因为使用模板/generics指定向量将包含特定types的元素,例如带有三个元素的元素的向量。 Cython不能做这最后一件事情,这听起来不平凡 – 它将不得不在编译时强制执行(在运行时types检查是Python已经做了什么)。 所以现在当你从Cython的某个列表中popup一些东西的时候,事先不知道它是什么types,把它放在一个typesvariables中只会增加一个types检查,而不是速度。 这意味着在这方面没有办法绕开Python解释器,而在我看来这是Cython对于非数值任务最重要的缺点。

解决这个问题的手动方法是用特定types的元素或键值组合的cdef类inheritancepython list / dict(或者std :: vector)。 这与模板生成的代码相同。 只要你在Cython代码中使用结果类,它应该提供一个改进。

使用数据库或数组只是解决了一个不同的问题,因为这是关于在容器中放置任意对象(但具有特定的types,最好是一个cdef类)。

而std :: map不应该与dict相比; std :: map维护按键sorting,因为它是一个平衡的树,字典解决了一个不同的问题。 更好的比较是dict和Google的哈希表。

如果这适合您的Cython设置,您可以看看Python的标准array模块。 我不确定,因为我从来没有使用过Cython。

没有办法让本地Python列表/字典达到C ++地图/vector的速度,甚至任何地方closures。 它与分配或types声明无关,而是支付解释器开销。 你提到的例子(numpy)是一个C扩展,并且正是用C编写的。