最好使用元组或numpy数组来存储坐标

时间:2010-04-01 21:17:58

标签: python arrays numpy tuples complex-numbers

我正在将一个C ++科学应用程序移植到python,因为我是python的新手,我想到了一些问题:

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

2)在某些情况下,这些坐标将用于构建复数,在复杂函数上进行评估,并将使用此函数的实际部分。假设无法分离此函数的实部和复杂部分,并且最后必须使用实部,可能最好直接使用复数来存储(x,y)?在python中从复杂到真实的转换有多糟糕? c ++中的代码执行了很多这些转换,这在代码中是一个很大的减速。

3)还必须执行一些坐标转换,对于坐标,将分别访问x和y值,转换完成,并返回结果。坐标变换是在复平面中定义的,因此直接使用组件x和y比依赖复杂变量更快?

谢谢

2 个答案:

答案 0 :(得分:6)

就内存消耗而言,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可以简单地通过跨越复杂数组,跳过所有其他浮点数,并将结果视为浮点数来将一个复数数组转换为它们的实部。此外,语法很简单:If {{ 1}}是一个复杂的numpy数组,然后z是浮动numpy数组的真实部分。这应该比使用属性查找的列表理解的纯Python方法快得多:z.real。 )

出于好奇,您将C ++代码移植到Python的原因是什么?

答案 1 :(得分:3)

具有额外维度的numpy数组在内存使用方面更紧密,并且至少与numpy元组数组一样快!复数至少同样好或甚至更好,包括你的第三个问题。顺便说一句,你可能已经注意到了 - 虽然问题比你的问题要晚得多,但是你正在休息:部分原因无疑是在一个问题中询问三个问题会使响应者关闭。为什么不问每个问题一个问题呢?这不是因为你对问题或任何事情收费,你知道......! - )