LoginSignup
4
4

More than 5 years have passed since last update.

コンピュータ言語を遅く使ってしまう方法2

Last updated at Posted at 2015-07-13

コンピュータ言語を遅く使ってしまう方法2

コンピュータを遅く使ってしまう方法はいろいろあるものです。
・部分配列を扱う際に不要なコピーを作らないこと。
 処理系の言語・ライブラリが、部分配列の簡潔な記法をサポートしているときには、部分配列からなるコピーを作る代わりに、部分配列自体を関数の引数にするなどして処理することです。
  

Pythonのnumpyの例を示してみます。
次のように
B=A[3:6] はコピーを作らず、部分配列に対する別名になっているにすぎません。
別名なので、Bの要素を変更すると、元の配列に対しても変更になっています。

C=A[3:6]+0  はコピーを作ります。そのため、コピーを変更しても元の配列は変更されません。
この違いを知っていないと、「コピーを変更したつもりが元の配列まで変わってしまっていた。」という
初心者にありがちなエラーを引き起こすことになります。

>>> import numpy as np
>>> A=np.arange(0,10,1)
>>> A
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> A[3:6]
array([3, 4, 5])
>>> B=A[3:6] #これはコピーを作らない
>>> B[0]=-3
>>> A
array([ 0, 1, 2, -3, 4, 5, 6, 7, 8, 9])
>>> C=A[3:6]+0 # これはコピーを作る
>>> C
array([-3, 4, 5])
>>> C[0]=-30
>>> A
array([ 0, 1, 2, -3, 4, 5, 6, 7, 8, 9])
>>>

また、代入をその場での代入に置き換えれば速くなります。
*=, +=, -= などの利用を考えてみましょう。

inplace.py
# -*- coding: utf-8 -*-
import cv2
import numpy as np
e0 = cv2.getTickCount()
a = np.ones((1024, 1024))
for i in range(20):
    a = a*2
print np.sum(a[:])

e1 = cv2.getTickCount()

a = np.ones((1024, 1024))
for i in range(20):
    a *= 2
print np.sum(a[:])
e2 = cv2.getTickCount()
print (e1 - e0) / cv2.getTickFrequency(), "# a = a*2"
print (e2 - e1) / cv2.getTickFrequency(), "# a *= 2"
print (e2 - e1) / (e1 - e0)

実行結果
1.09951162778e+12
1.09951162778e+12
0.116400550283 # a = a*2
0.0270198481919 # a *= 2
0.23212818261

処理時間が23%にまで削減(4倍の高速化)になっています。

まとめ
・部分配列にコピーを作らない
・"*="で十分なときには"="を使わない。

Pythonの場合については「ハイパフォーマンスPython」
を読むといいでしょう。

4
4
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
4
4