巨人の肩の上に登る

先人の積み重ねた発見に基づいて、なにかを発見しようとすることを指す。

Pythonにおける配列生成の速度比較

序論|配列生成における生成速度

n 個の x からなるベクトル,あるいは,連続する整数 x | 0, 1 .... , n に対して、f(x) の値から配列を生成したいというケースが多々発生する. このとき,内包表記,map関数,などどういう手法をとればよいのかを検討してみる.


1. n 個の定数から成る配列

方法

例えば,n個の 1 から成る配列を生成することを考える.
下記の4つの手法で配列を生成する計算時間を比較する.ただし,Numpy の出力結果は1行10000000列の行列である.

# 内包表記
a = [1 for _ in xrange(10000000)]

# append
b = []
    for _ in xrange(10000000):
        b.append(1)

# map関数
c = map(lambda _: 1, xrange(10000000))

# Numpy
np.ones((1, 10000000))

30回の試行を行った結果を下記に示す.

結果

# 内包表記
0.8121745±0.03523441

# append
1.984215±0.05489317 [s]

# map関数
1.457514±0.0431716 [s]

# Numpy
0.03261587±0.003949044 [s]

結論

予想通りCで実行されているNumpy が最も早い. 他の3種類の中では,内包表記が早いことが示された.mapは関数呼び出しに要する遅延であると考えられる.appendは配列の生成ではなく,要素の追加であるため,前述の2種とは異なり速度も遅い.


2. 関数の値を要素とする配列

方法

下記の関数の値からなる配列を生成する.

def double(x):
    return x*x
# 内包表記
a = [double(x) for x in xrange(10000000)]

# append
b = []
    for x in xrange(10000000):
        b.append(double(x))

# map関数
c = map(double, xrange(10000000))

同様に,30回の試行を行った結果を下記に示す.

結果

# 内包表記
3.416236±0.2539137 [s]

# append
4.974325±0.4619621 [s]

# map関数
2.10843±0.1802408 [s]

結論

map関数が最も早いことが示された.関数の値を要素とする場合,各手法において同様に遅延が発生する.この場合においては,map関数が最も高速配列を生成できることが示唆される.


総論

  • Numpy は早い
  • 関数呼び出し無し => 内包表記
  • 関数呼び出し有り => Map関数