7

特定の軸で配列を合計する場合、専用の配列メソッドarray.sum(ax)は実際には for ループよりも遅くなる場合があります。

v = np.random.rand(3,1e4)

timeit v.sum(0)                             # vectorized method
1000 loops, best of 3: 183 us per loop

timeit for row in v[1:]: v[0] += row        # python loop
10000 loops, best of 3: 39.3 us per loop

ベクトル化されたメソッドは、通常の for ループよりも 4 倍以上遅くなります! ここで (wr)on(g) はどうなっていますか?

4

1 に答える 1

8

いいえ、できません。あなたの興味深い例が指摘しているnumpy.sumように、最適ではない可能性があり、明示的な for ループを介した操作のより良いレイアウトはより効率的です。

別の例を示しましょう。

>>> N, M = 10**4, 10**4
>>> v = np.random.randn(N,M)
>>> r = np.empty(M)
>>> timeit.timeit('v.sum(axis=0, out=r)', 'from __main__ import v,r', number=1)
1.2837879657745361
>>> r = np.empty(N)
>>> timeit.timeit('v.sum(axis=1, out=r)', 'from __main__ import v,r', number=1)
0.09213519096374512

ここでnumpy.sumは、高速実行インデックス ( vC 連続) で合計する場合は最適であり、低速実行軸で合計する場合は最適ではないことが明確にわかります。興味深いことに、forループには逆のパターンが当てはまります。

>>> r = np.zeros(M)
>>> timeit.timeit('for row in v[:]: r += row', 'from __main__ import v,r', number=1)
0.11945700645446777
>>> r = np.zeros(N)
>>> timeit.timeit('for row in v.T[:]: r += row', 'from __main__ import v,r', number=1)
1.2647287845611572

コードを調べる時間はありませんでしたnumpyが、違いを生んでいるのは、連続したメモリ アクセスまたはストライド アクセスであると思われます。

この例が示すように、数値アルゴリズムを実装する場合、正しいメモリ レイアウトは非常に重要です。ベクトル化されたコードがすべての問題を解決するとは限りません。

于 2013-01-28T23:18:46.970 に答える