更好的选择是使用元组或numpy数组来存储坐标。

10

我正在将一个C++科学应用程序移植到Python,但由于我对Python不太熟悉,所以遇到了一些问题:

1) 我正在定义一个包含坐标(x,y)的类。这些值将被多次访问,但仅在类实例化后才能被读取。在内存和访问时间方面,使用元组还是Numpy数组更好?

2) 在某些情况下,这些坐标将用于构建一个复杂数,并在复杂函数上进行评估,将使用该函数的实部。假设无法分离该函数的实部和复部,且最终必须使用实部,也许直接使用复数来存储(x,y)会更好?在Python中,从复数到实数的转换开销有多大?在C++代码中,执行许多这些转换会导致速度变慢。

3) 还需要执行一些坐标变换,并且需要单独访问x和y值,进行变换并返回结果。坐标变换在复平面中定义,因此直接使用x和y分量是否仍然比依赖于复数变量更快?

谢谢


为什么不直接使用一个复数的numpy数组呢? - Gabe
这在算法意义上是最佳的方法,但根据我的测试,这也是可能的最慢组合。 - Ivan
2个回答

7
就内存消耗而言,numpy数组比Python元组更加紧凑。 numpy数组使用单个连续的内存块。numpy数组的所有元素都必须声明为特定类型(例如32位或64位浮点数)。Python元组不一定使用连续的内存块,元组的元素可以是任意的Python对象,这通常比numpy数值类型占用更多内存。
因此,对于numpy而言,这个问题是轻松解决的胜利。(如果数组的元素可以被存储为numpy数值类型,则如此。)
在速度问题上,我认为选择取决于一个问题:“你能将代码向量化吗?”
也就是说,您能否将计算表达为针对整个数组逐元素执行的操作。
如果代码可以被向量化,则numpy很可能比Python元组快。(唯一我能想象到的情况是,如果您有很多非常小的元组。在这种情况下,形成numpy数组和一次性导入numpy的开销可能会淹没向量化的好处。)
不能被向量化的代码示例可能涉及查看数组中的第一个复数z,对其进行计算以产生整数索引idx,然后检索z[idx],对该数字进行计算以产生下一个索引idx2,然后检索z[idx2]等。这种类型的计算可能无法向量化。在这种情况下,您可以使用Python元组,因为您将无法利用numpy的优势。
我不会担心访问复数的实部/虚部的速度问题。我的猜测是,向量化的问题很可能决定哪种方法更快。 (顺便说一句,numpy可以通过跨过复杂数组、跳过每个其他浮点数,并将结果视为浮点数,简单地将复数数组转换为其实部。此外,语法非常简单:如果z是一个复合numpy数组,则z.real表示实部作为浮点numpy数组。这应该比纯Python方法更快,后者使用属性查找的列表理解: [z.real for z in zlist]。)
只是出于好奇,您将C++代码移植到Python的原因是什么?

只是为了测试Python对象结构是否更适合我的应用程序,并尝试scipy例程。到目前为止,我仍然坚持使用C++ - 在我的测试中,至少快了2个数量级! - Ivan
此外,在 C++ 代码中访问数字的实部和虚部会导致很大的减速。 - Ivan
1
是的,使用Python有很多好处,比如可读性和快速代码开发,但我还没有遇到过任何将代码从C/C++移植到Python并获得加速的例子。通常当Python代码存在瓶颈时,人们建议将该函数重写为C/C++并从Python中调用它。 - unutbu

3
一维数组比元组更节省内存,并且至少和元组一样快!对于您的第三个问题,复数至少同样好甚至更好。顺便说一句,您可能已经注意到,在您之后提出的问题得到了大量回答的同时,您的问题却没有得到回应:部分原因无疑是因为在一个问题中提出了三个问题会让回答者感到厌烦。为什么不每个问题只问一个问题呢?毕竟,您并不需要为提问付费或者其他什么,您知道的...!-)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接