Python的deepcopy()的运行时复杂性是多少?

时间:2012-01-21 22:48:24

标签: python complexity-theory deep-copy

我正在努力提高算法的速度,在查看正在调用哪些操作之后,我很难确定哪些操作正在放慢速度。我想知道Python的deepcopy()是否可能是罪魁祸首,或者我是否应该进一步了解自己的代码。

3 个答案:

答案 0 :(得分:3)

查看代码(你也可以),它遍历引用对象树中的每个对象(例如dict的键和值,对象成员变量......)并为它们做两件事:

  1. 通过在id-indexed memo dict
  2. 中查看它是否已被复制
  3. 对象的副本(如果不是
  4. 对于简单对象,第二个是 O(1)。对于复合对象,相同的例程处理它们,因此对于树中的所有 n 对象, O(n)。第一部分,在字典中查找对象,是O(1) on average, but O(n) amortized worst case

    所以最多,平均来说,deepcopy是线性的。 memo中使用的密钥是id()值,即内存位置,因此它们不会随机分布在密钥空间("上面的平均值"部分),并且可能会更糟,直到 O(n ^ 2)最坏的情况。我确实观察到了实际使用中的一些性能下降,但在大多数情况下,它表现为线性。

    这是复杂性的一部分,但常数很大而且deepcopy is anything but cheap很可能导致你的问题。唯一确定的方法是使用分析器 - 这样做。 FWIW,我目前正在重写非常慢的代码,将其执行时间的98%花在deepcopy上。

答案 1 :(得分:1)

你在使用deepcopy做什么用途?顾名思义,deepcopy以递归方式复制对象和所有子对象,因此需要花费一定的时间与您要复制的对象的大小成比例。 (有一点处理循环引用的开销)

没有任何方法可以加快速度,如果要复制所有内容,则需要复制所有内容。

要问的一个问题是,您是否需要复制所有内容,或者只是复制部分结构。

答案 2 :(得分:0)

deepcopy()的复杂性取决于要复制的对象的大小(元素/子元素的数量)。

如果算法的输入不影响正在复制的对象的大小,那么为了确定复杂性,您应该将对deeopcopy()的调用视为O(1),因为每次调用都是执行时间相对静止。

(如果算法的输入确实对正在复制的对象的大小产生影响,则必须详细说明。然后可以评估算法的复杂性。)