应该使用哪个运算符(+ vs + =)来提高性能?(就地Vs不到位)

Ano*_*arZ 11 python performance in-place

假设我在python中有这两段代码:

1 --------------------------
import numpy as np
x = np.array([1,2,3,4])
y = x
x = x + np.array([1,1,1,1])
print y

2 --------------------------
import numpy as np
x = np.array([1,2,3,4])
y = x
x += np.array([1,1,1,1])
print y
Run Code Online (Sandbox Code Playgroud)

我认为y两个例子中的结果都是相同的,因为y指出xx成为(2,3,4,5),事实并非如此

结果是(1,2,3,4) for 1(2,3,4,5) for 2.

经过一些研究,我发现在第一个例子中

#-First example---------------------------------------
x = np.array([1,2,3,4]) # create x --> [1,2,3,4] 
y = x                   # made y point to x
# unril now we have x --> [1,2,3,4]
#                          |
#                          y
x = x + np.array([1,1,1,1]) 
# however this operation **create a new array** [2,3,4,5] 
# and made x point to it instead of the first one
# so we have y --> [1,2,3,4] and x --> [2,3,4,5]

#-Second example--------------------------------------
x = np.array([1,2,3,4]) # create x --> [1,2,3,4] 
y = x                   # made y point to x
# unril now the same x --> [1,2,3,4]
#                            |
#                            y
x += np.array([1,1,1,1])
# this operation **Modify the existing array**
# so the result will be
# unril now the same x --> [2,3,4,5]
#                            |
#                            y
Run Code Online (Sandbox Code Playgroud)

您可以在此链接就地算法中找到有关此行为的更多信息(不仅适用于此示例)

我的问题是:意识到这种行为为什么我应该在性能方面使用就地算法?(执行时间更快?内存分配更少?..)

编辑:澄清

(+,= +)的例子只是为了解释那些不知道的人的就地算法..但问题一般是在这种情况下使用就地算法.

另一个更复杂的例子:在一个变量中加载一个CSV文件(只有1000万行),然后对结果进行排序,就地算法的想法就是在相同的内存空间中通过连续转换生成一个包含输入的输出数据直到输出产生? - 这样就无需使用两倍的存储空间 - 一个输入区域和一个大小相等的输出区域(使用最少量的RAM,硬盘......)

Eri*_*nil 6

x = x + 1 vs x + = 1

性能

看来你理解x += 1和之间的语义差异x = x + 1.

对于基准测试,您可以在IPython中使用timeit.

定义这些功能后:

import numpy as np
def in_place(n):
    x = np.arange(n)
    x += 1

def not_in_place(n):
    x = np.arange(n)
    x = x + 1

def in_place_no_broadcast(n):
    x = np.arange(n)
    x += np.ones(n, dtype=np.int)
Run Code Online (Sandbox Code Playgroud)

您只需使用%timeit语法来比较性能:

%timeit in_place(10**7)
20.3 ms ± 81.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit not_in_place(10**7)
30.4 ms ± 253 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit in_place_no_broadcast(10**7)
35.4 ms ± 101 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)

not_in_place慢了50%in_place.

请注意,广播也有很大的不同:numpy理解x += 1为添加1到每个元素x,而不必创建另一个数组.

警告

in_place应该是首选功能:它更快,使用更少的内存.但是,如果您在代码中的不同位置使用和改变此对象,则可能会遇到错误.典型的例子是:

x = np.arange(5)
y = [x, x]
y[0][0] = 10
y
# [array([10,  1,  2,  3,  4]), array([10,  1,  2,  3,  4])]
Run Code Online (Sandbox Code Playgroud)

排序

您对就地分拣的优势的理解是正确的.在对大型数据集进行排序时,它可以在内存需求方面产生巨大差异.

排序算法还有其他令人满意的特性(稳定,可接受的最坏情况复杂性......),看起来标准的Python算法(Timsort)有很多.

Timsort是一种混合算法.它的某些部分是就地的,有些需要额外的内存.它永远不会比使用更多n/2.