我的问题:我发现,处理大的数据集与原始C ++使用STL图和载体可以经常是相当快(和较低的内存占用)比使用用Cython。
我估计这个速度点球的那部分是由于使用Python列表和类型的字典,并可能有一些技巧,在用Cython使用较少的担保数据结构。 例如,这个页( http://wiki.cython.org/tutorials/numpy )显示了如何通过预先在ND阵列的大小和类型,使numpy的阵列,用Cython非常快。
问:有没有办法做列表/类型的字典类似的东西,如说明你期望大概多少元素或(键,值)对有在其中? 也就是说,有没有列出/类型的字典转换为用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]
在C ++中做在Python类似的操作常常可以慢。 list
和dict
的实际执行得非常好,但是你获得大量的开销使用Python对象,这比C ++对象更抽象的,需要在运行时更大量的查找。
顺便说一句, std::vector
是一个非常相似的方式来实现的list
。 std::map
,虽然,实际上是在某种程度上,很多操作是慢实现dict
作为它的尺寸变大。 对于每一个的适当大的实施例中, dict
克服由它比更慢的恒定因子std::map
并且实际上会做动作像查找,插入等更快。
如果你想使用std::map
和std::vector
,没有什么能阻止你。 你必须自己包起来,如果你想将它们暴露到Python。 如果这个包装消耗了全部或大部分的你希望节省时间,不要感到震惊。 我不知道的,使这个自动为您任何工具。
有控制用一些细节来创建对象的C API调用。 你可以说“请使用至少这些元素列表”,但这并不能提高你的列表的创建和填充操作的整体复杂性。 这当然当你试图改变你的名单没有太大以后更改。
我一般的建议是
如果你想有一个固定大小的数组(您谈谈指定列表的大小),你实际上可能想要的东西就像一个numpy的阵列。
我怀疑你会得到你想要的使用的任何加速std::vector
过list
在你的代码一般更换。 如果你想用它在幕后,它可能会给你一个满意的尺寸和空间的改善(当然不知道没有测量的我,也不是你。))。
dict
实际上它的工作非常好。 我肯定基于不会试图引入新的通用类型在Python中使用std::map
,里面有更糟糕的算法的复杂性,及时为许多重要的操作和在至少一些实现,留下了一些优化技术给用户dict
已经有了。
如果我做了想要的东西,更多的工作有点像std::map
,我可能会使用一个数据库。 这通常是我做的,如果东西,我想在存储dict
(或为此事,我的东西存储在一个list
)变得太大,我感觉很舒服存储在内存中。 Python已经sqlite3
在STDLIB和驱动程序提供的所有其他主要的数据库。
C ++是快不是因为载体的静态声明并进入它的元素而已,但重要的是因为使用模板/泛型一个指定的载体将只包含某种类型,例如矢量有三个元素的元组的元素。 用Cython做不到这最后一件事,听起来平凡的 - 因为它必须在编译时强制执行,以某种方式(在运行时类型检查是什么的Python已经这样做)。 所以现在,当你在用Cython流行过的东西的清单也没有预先知道它是什么类型,并把它在一个类型变量的方式只是增加一个类型检测,而不是速度。 这意味着,没有在这方面绕过Python解释器的方式,而在我看来,它是用Cython的非数值任务最关键的缺点。
解决这个的手动方式是继承与CDEF类Python列表/字典(或可能的std ::向量)为特定类型的元件或关键值组合。 这等于同样的事情作为模板生成的代码。 只要您使用用Cython代码生成的类应该提供一个改进。
使用数据库或阵列只是解决了不同的问题,因为这是关于把任意对象(但具有特定的类型,并且优选为CDEF类)在容器中。
和std ::地图是不能相比与dict; 的std ::地图保持在按键排序顺序,因为它是一个平衡树,字典解决不同的问题。 一个更好的比较是字典和谷歌的哈希表。
你可以看看标准array
的Python模块,如果这是适合你用Cython设置。 我不知道,因为我从来没有使用用Cython。
有没有办法让本地Python列表/类型的字典到一个C ++地图/矢量甚至望其项背的速度。 它无关,与分配或类型声明,而是支付翻译费用。 你提到的(numpy的)这个例子是一个C扩展,并用C语言编写的正是这个道理。