LoginSignup
6
2

More than 5 years have passed since last update.

Numpy Arrayで作業する時に配列をcopyしているかを確認する簡単な方法

Last updated at Posted at 2018-04-06

データの処理をする時にnumpy arrayをいじる時が度々あります。
データ量が多くなるとデータ処理のパフォーマンスを考えざるを得なくなります。
色々パフォーマンスチューニングのポイントがありますが、
その中で影響の大きい一つが、numpyのデータをcopyしてるかどうかになります。

例えば、下記の例を見ましょう。

a = np.zeros(10000000)

# 1. copyせずに元データを書き換え
a *= 2

# 2. 元データをcopyし作業
b = a * 2

2 は implicit copy が行われているので、1 より何倍も遅くなります。
実際に速度を測ってみると、

%%timeit a = np.zeros(10000000)
a *= 2
# 結果
# 100 loops, best of 3: 5.86 ms per loop

%%timeit a = np.zeros(10000000)
b = a * 2
# 結果
# 10 loops, best of 3: 22.4 ms per loop

ご覧の通り、約3~4倍遅くなります。
この copy しているかどうかを判断するためには、そのnumpy arrayの base arrayを確認する必要があります。

下記は私がよく使う関数です。

def get_data_base(arr):
    # 与えられた numpy arrayの実データになる base array を返す
    base = arr
    while isinstance(base.base, np.ndarray):
        base = base.base
    return base


def arrays_share_data(x, y):
    # 二つの numpy array が同じベースなのかを判別する
    return get_data_base(x) is get_data_base(y)

http://ipython-books.github.io/45-understanding-the-internals-of-numpy-to-avoid-unnecessary-array-copying/

上記の関数を使うと、二つのarrayが同じベースを持っているのかを確認できます。
例えば、下記のように同じ処理に見えますが、パフォーマンスの差が出る処理を確認できます。

a = np.arange(3)
# array([0, 1, 2])

b = a.flatten()
# array([0, 1, 2])

c = a.ravel()
# array([0, 1, 2])

arrays_share_data(a, b)
# False
arrays_share_data(a, c)
# True

他の例として、全然違う形に見えてもベースが同じの場合もあります。

a = np.arange(3)
# array([0, 1, 2])

b = a[1:]
# array([1, 2])

arrays_share_data(a, b)
# True

データが増えれば増えるほど、こんな小さいことが大きく影響が出てきます。
特に機械学習のモデルを学習してる時に loop処理のたびに numpy arrayを
transposeしたり、flattenしたりすると限りなく遅くなる場合が多いです。気をつけましょう。

もっと詳しい情報が知りたい方は、初心者にも分かりやすいこの本をおすすめします。
http://ipython-books.github.io/

6
2
0

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
2