numpy.ndarray
In [1]: import numpy as np
In [2]: N = 100000000
In [3]: def add_one(a):
...: for i in range(10):
...: a = a + 1
...:
In [4]: def iadd_one(a):
...: for i in range(10):
...: a += 1
...:
In [5]: x = np.random.randn(N)
In [6]: x[0:5]
Out[6]: array([-1.7480884 , 0.09139608, 1.38484079, -0.1584492 , 2.48426822])
In [7]: %time add_one(x)
CPU times: user 2.68 s, sys: 5.08 s, total: 7.76 s
Wall time: 9.59 s
In [8]: x[0:5]
Out[8]: array([-1.7480884 , 0.09139608, 1.38484079, -0.1584492 , 2.48426822])
In [9]: %time iadd_one(x)
CPU times: user 1.19 s, sys: 163 ms, total: 1.35 s
Wall time: 1.38 s
In [10]: x[0:5]
Out[10]: array([ 8.2519116 , 10.09139608, 11.38484079, 9.8415508 , 12.48426822])
+
を使用した場合(add_one関数)と+=
を使用した場合(iadd_one関数)で速度を比較すると、+=
を使用した場合のほうが圧倒的に速い。
これは、+
operatorはオブジェクトの__add__
メソッドを呼び出し、演算のたびに新しいオブジェクトをメモリ上に確保するのに対し、
+=
operatorは__iadd__
メソッドを呼び出し、in-placeに演算がおこなわれるためである。
+
operatorを使用するとsysの時間が伸びているが、これはメモリ確保的なsystem callが呼ばれているためと考えられる。
+=
はin-place演算なので元のオブジェクトが書き換えられることに注意。
list
In [1]: import numpy as np
In [2]: N = 10000000
In [3]: def add_one(a):
...: for i in range(10):
...: a = a + [1]
...:
In [4]: def iadd_one(a):
...: for i in range(10):
...: a += [1]
...:
In [5]: x = np.random.randn(N).tolist()
In [6]: %time add_one(x)
CPU times: user 1 s, sys: 178 ms, total: 1.18 s
Wall time: 1.22 s
In [7]: len(x)
Out[7]: 10000000
In [8]: %time iadd_one(x)
CPU times: user 34 µs, sys: 710 µs, total: 744 µs
Wall time: 752 µs
In [9]: len(x)
Out[9]: 10000010
listの場合も同様に+=
のほうが速い(listではadd
とiadd
は要素の追加になる)。
使い分け
大きな配列に対して演算をおこなうときはin-place operatorのほうが良い。
ただしオブジェクトの内容が書き換わってもよいのであれば。