LoginSignup
6
3

More than 5 years have passed since last update.

Pythonのa = a + 1とa += 1は厳密には等価ではない

Last updated at Posted at 2018-01-24

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ではaddiaddは要素の追加になる)。

使い分け

大きな配列に対して演算をおこなうときはin-place operatorのほうが良い。
ただしオブジェクトの内容が書き換わってもよいのであれば。

参考

6
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
3