AnacondaのNumPyとPyPIのNumPyの速度を比較する


このエントリーをはてなブックマークに追加

Anaconda Pythonで提供されるNumPyはIntelのMKLを利用しているため高速だという話を聞いたことがあります。実際どの程度違いがあるのか試してみました。

環境構築

実験は、自作PCに入れたUbuntu 16.04で行いました。環境構築にはAnaconda Pythonが提供する仮想環境を用います。

Anaconda版のNumPy

以下のコマンドで環境を作成しました。Cythonは必要ないかもしれませんが、chainerをインストールするときにmkl-random 1.0.1 requires cython, which is not installed. mkl-fft 1.0.2 requires cython, which is not installed.という警告が表示されたので、一応入れています。

$ conda create -n py37_conda_numpy python=3.7 numpy
$ source activate py37_conda_numpy
$ conda install cython
$ pip install chainer

インストールされたパッケージは以下のとおりです。

$ pip freeze
certifi==2018.4.16
chainer==4.3.0
Cython==0.28.3
filelock==3.0.4
mkl-fft==1.0.2
mkl-random==1.0.1
numpy==1.14.5
protobuf==3.6.0
six==1.11.0

PyPI版のNumPy

以下のコマンドで環境を作成しました。

$ conda create -n py37_pip_numpy python=3.7       
$ source activate py37_pip_numpy
$ pip install numpy
$ pip install chainer

インストールされたパッケージは以下のとおりです。

$ pip freeze
certifi==2018.4.16
chainer==4.3.0
filelock==3.0.4
numpy==1.14.5
protobuf==3.6.0
six==1.11.0

実験1. 行列積

1024x1024の行列二つの行列積を100回計算する以下のコードを使って、処理時間を比較しました。

import timeit
import numpy as np

def main():
    HEIGHT = 1024
    WIDTH = 1024
    REPEAT = 100

    np.random.seed(0)
    result = np.zeros((HEIGHT, WIDTH), dtype=np.float32)
    for _ in range(REPEAT):
        a = np.random.rand(HEIGHT, WIDTH)
        b = np.random.rand(HEIGHT, WIDTH)
        result += a @ b
    print(result.sum())

s = timeit.default_timer()
main()
print("elapsed time: {:.2f} sec.".format(timeit.default_timer() - s))

以下に結果を示します。

  • Anaconda版NumPy: 3.35 秒
  • PyPI版NumPy: 8.93 秒

Anaconda版のNumpyがPyPIPythonの38%程度の時間で処理を終えており、大差がつきました。プログラム実行中のCPUの負荷をhtopコマンドで眺めると、PyPI版のNumPyは8コアを全消費するのに比べてAnaconda版のNumPyは4コアしか消費しておらず、余裕を感じました。

実験2. ニューラルネット

手書きの数字を0から9に分類する分類器の学習chainer/train_mnist.py at master · chainer/chainer · GitHubを題材に、処理時間を比較しました。この分類器にはCNNは使われておらず、全結合層のみです。以下は実験の詳細です。

  • ソースコードには実験1と同様の時間計測コードを追加した。
  • 学習はCPUのみを用いる。GPUは用いない。
  • 最初の実行時は実験用データセットをダウンロードする処理が走るので、それは処理時間に含めない。
  • 引数に--epoch 5を指定し、5エポックで処理を打ち切る。

以下に結果を示します。

  • Anaconda版NumPy: 54.51 秒
  • PyPI版NumPy: 100.49 秒

Anaconda版のNumpyがPyPIPythonの54%程度の時間で処理を終えました。実験1ほどではないですが、やはりAnaconda版のNumpyは高速です。

まとめ

NumPyの速度がボトルネックになっているのであれば、Anaconda版のNumPyの導入は一考の価値があります。