1

大きなnumpy配列がある場合x、書き込みの代わりに、多くの反復操作を高速化できます

x[1:-1] = 5*x[1:-1]

使うことができます

x[1:-1] *= 5

最初の例とは対照的に、値を持つ追加の配列の不要な作成を回避するため、これは高速です5*x[1:-1]

ここに私の質問があります: 次のようなより一般的な反復を高速化することは可能ですか?

x[1:-1] = 5*x[1:-1] + x[:-2]

似たような方法で?これまでのところ、私は思いついただけです

x[1:-1] = x[:-2]
x[1:-1] += 5*x[2:]

しかし、これでもコピーが作成され、高速化する方法があるのではないかと思います。

4

1 に答える 1

1

一時的なアリアが必要なだけで、書き直すことができない場合があります

x[1:-1] += 5*x[2:]

ビューの操作として。

一時配列が必要な場合のインプレース計算に類似した方法は、いくつかの一時配列を作成し、計算の各段階でそれらを出力に使用することです。ポインター計算はまだ少しありますが、メモリ内にスペースを複数回作成する必要はありません。次に、上記の行を次のように書き換えることができます。

np.multiply(x[2:], 5, out=temp)
x[1:-1] += temp

ここでは、境界を扱うというこの一般的な問題に対して私が通常temp行っているサイズがあると仮定します。x[-1:1]

インプレース計算では、数が指数関数的に増加するため、正確な式を timeit で何度も実行することはできませんが、5x を 1x に置き換えたテストを次に示します。

import numpy as np
from timeit import timeit

N = 100000000
x = np.arange(N, dtype=np.int)
temp = np.zeros((N-2,), dtype=np.int)

def f0(x, temp):
    x[1:-1] += 1*x[2:]

def f1(x, temp):
    np.multiply(x[1:-1], 1, out=temp)
    x[1:-1] += temp

print timeit("f0(x, temp)", "from __main__ import f0, f1, x, temp", number=100)
print timeit("f1(x, temp)", "from __main__ import f0, f1, x, temp", number=100)

これは次を与えます:

71.543628931
44.719383955

# or, for N /= 100, and number *= 10
5.37844896317
4.50015997887

また、はるかに小さい配列の場合、out配列アプローチは遅くなる可能性があります。

于 2013-05-23T17:19:41.783 に答える