ram*_*jan 37 c c++ python cython
我的问题:我发现使用原始C++使用STL映射和向量处理大型数据集通常可以比使用Cython更快(并且内存占用更少).
我认为这部分速度惩罚是由于使用Python列表和dicts,并且可能有一些技巧在Cython中使用较少的数据结构.例如,这个页面(http://wiki.cython.org/tutorials/numpy)展示了如何通过预定义ND数组的大小和类型,在Cython中非常快速地生成numpy数组.
问题:有没有办法用list/dicts做类似的事情,例如通过大致说明你希望在它们中有多少元素或(键,值)对?也就是说,在Cython中是否存在将列表/ dicts转换为(快速)数据结构的惯用方法?
如果不是,我想我只需要用C++编写它并包装在Cython导入中.
Sam*_*eld 33
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]
Run Code Online (Sandbox Code Playgroud)
Mik*_*ham 30
在Python中执行与在C++中类似的操作通常会更慢.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(或者就此而言,我存储在a中的东西list)变得太大,让我感觉不舒服存储在内存中.Python sqlite3在stdlib和驱动程序中提供了所有其他可用的主要数据库.
小智 9
C++很快,不仅仅是因为向量的静态声明和进入它的元素,但关键是因为使用模板/泛型,指定向量将只包含某种类型的元素,例如具有三元素元组的向量.Cython不能做到这一点,听起来很重要 - 它必须在编译时强制执行,不知何故(运行时的类型检查是Python已经做的).所以现在当你在Cython中从列表中弹出一些东西时,无法预先知道它是什么类型,并且将它放入一个类型变量只会增加一个类型检查,而不是速度.这意味着在这方面没有办法绕过Python解释器,在我看来,这是Cython用于非数字任务的最关键的缺点.
解决这个问题的手动方法是使用cdef类将python list/dict(或者可能是std :: vector)子类化为特定类型的元素或键值组合.这与模板生成的代码相同.只要在Cython代码中使用结果类,它就应该提供改进.
使用数据库或数组只解决了一个不同的问题,因为这是关于在容器中放置任意对象(但具有特定类型,最好是cdef类).
并且std :: map不应该与dict进行比较; std :: map按排序顺序维护键,因为它是一个平衡树,dict解决了另一个问题.更好的比较是dict和谷歌的哈希表.