numpyで明示的にループを書くと極端に遅くなる

  • 12
    いいね
  • 4
    コメント
この記事は最終更新日から1年以上が経過しています。

「コンピュータ言語を遅く使ってしまう方法」で述べたように
numpyで明示的にループを書くと極端に遅くなる。
以下は、初心者向けの話です。

それを実験するコードを書きました。

matmul.py
# -*- coding: utf-8 -*-
u"""
行列演算の速度比較
"""

def matmul1(a, b):
    lenI = a.shape[0]
    lenJ = a.shape[1]
    lenK = b.shape[1]
    c = np.zeros((lenI, lenJ))
    for i in range(lenI):
        for j in range(lenJ):
            for k in range(lenK):
                c[i, j] += a[i, k] * b[k, j]
    return c

def matmul2(a, b):
    lenI = a.shape[0]
    lenJ = a.shape[1]
    lenK = b.shape[1]
    c = np.zeros((lenI, lenJ))
    for i in range(lenI):
        for k in range(lenK):
            for j in range(lenJ):
                c[i, j] += a[i, k] * b[k, j]
    return c

import numpy as np
a = np.random.randn(200, 200)
b = np.random.randn(200, 200)
print a.shape

c2 = matmul2(a, b)
print c2

c = matmul1(a, b)
print c

c3 = np.dot(a, b)
print c3

IPythonのコンソールで
このコードを一度実行させて、関数定義を有効にしてから
%timeit を使って比較してみました。
20倍もの差を生じています。

%timeit c2 = matmul2(a, b)
1 loops, best of 3: 7.39 s per loop

%timeit c1 = matmul1(a, b)
1 loops, best of 3: 7.31 s per loop

%timeit c3 =np.dot(a, b)
1000 loops, best of 3: 321 µs per loop

まとめ
 numpyのように行列演算に最適化されたライブラリを使うときには
 行列の要素に個別にアクセスするようなfor文は基本書かないこと。
 numpyのドキュメントを読んで、呼び出すべき関数を調べてください。
 Spyder統合環境の場合[help][Installed Python Modules]から
 numpyのドキュメントが読めます。