2018年9月25日火曜日

開発環境

  • macOS High Sierra - Apple
  • Emacs (Text Editor)
  • Python 3.7 (プログラミング言語)
Pythonのfor文は遅い? - atsuoishimoto's diary

for/inのrange(len(a))の部分がちょっと気になったので、Pythonっぽい書き方に書き直してみた。

コード(Emacs)

Python 3

#!/usr/bin/env python3
import numpy as np
import timeit

a = np.ones(100000)
b = np.ones(100000)


def dot(a, b):    # zipを利用
    s = 0
    for a0, b0 in zip(a, b):
        s += a0 * b0
    return s


def dot1(a, b):  # zipが使えない場合。range(len(a))ではなくenumerateを利用
    s = 0
    for i, ai in enumerate(a):
        s += ai * b[i]

# 上記の二つでsumを利用


def dot2(a, b):
    s = sum([a0 * b0 for a0, b0 in zip(a, b)])
    return s


def dot3(a, b):
    s = sum([ai * b[i] for i, ai in enumerate(a)])


def dot4(a, b):  # 元の書き方
    s = 0
    for i in range(len(a)):
        s += a[i] + b[i]
    return s


num = 100
ts = [timeit.timeit(lambda: dot(a, b), number=num),
      timeit.timeit(lambda: dot1(a, b), number=num),
      timeit.timeit(lambda: dot2(a, b), number=num),
      timeit.timeit(lambda: dot3(a, b), number=num),
      timeit.timeit(lambda: dot4(a, b), number=num),
      timeit.timeit(lambda: np.dot(a, b), number=num)]

for i, t in enumerate(ts):
    print(f'{i}: {t}')

入出力結果(Terminal, Jupyter(IPython))

$ ./sample.py
0: 1.9701782140000001
1: 2.66699861
2: 2.2850130470000005
3: 3.0685505980000007
4: 3.1855504470000007
5: 0.001911685000001384
$

zip関数を使用したものが速いみたい。sum関数は読みやすくなるものの、この場合は使用すると遅くなる模様。range(len(a))とenumerate(a)に関しては、enumerate(a)の方がPythonistaっぽい書き方(?)かつ速度の面でもrange(len(a))より速いみたい。

何れにしても、当然ながら(?)NumPyのdotメソッドを使用したのが圧倒的に一番速い。

0 コメント:

コメントを投稿