3

私はm x n配列を持っています: a、整数m > 1E6、およびn <= 5.

関数FGがあり、これらは次のように構成されています: F ( u , G ( u , t))。u1 x n配列、t はスカラー、FGは配列を返し1 x nます。

Fでそれぞれを評価しrowa前に評価した行を次の評価のu配列として使用する必要があります。そういう評価をする必要があります。m

これは非常に高速でなければなりません。以前、配列全体の評価に感銘を受けましscitools.std StringFunctionたが、この問題では、前に計算された配列を次の計算の引数として使用する必要があります。StringFunction がこれを実行できるかどうかはわかりません。

例えば:

a = zeros((1000000, 4))
a[0] = asarray([1.,69.,3.,4.1])

# A is a float defined elsewhere, h is a function which accepts a float as its argument and returns an arbitrary float. h is defined elsewhere.

def G(u, t):
  return asarray([u[0], u[1]*A, cos(u[2]), t*h(u[3])])

def F(u, t):
  return u + G(u, t)


dt = 1E-6

for i in range(1, 1000000):
  a[i] = F(a[i-1], i*dt)
  i += 1

上記のコードの問題は、非常に遅いことです。これらの計算を数ミリ秒単位で実行する必要があります。

どうすればやりたいことができますか?

ありがとうございました。

敬具、

マリウス

4

2 に答える 2

1

この種のことは、numpy で行うのは非常に困難です。これを列ごとに見ると、いくつかのより単純なソリューションが表示されます。

a[:,0]とても簡単です:

col0 = np.ones((1000))*2
col0[0] = 1                  #Or whatever start value.
np.cumprod(col0, out=col0)

np.allclose(col0, a[:1000,0])
True

前述のように、これは非常に迅速にオーバーフローします。a[:,1]同じ線に沿って多くのことを行うことができます。

次の 2 つの列を numpy だけですばやく実行する方法があるとは思いません。これには numba を使用できます。

from numba import auotojit

def python_loop(start, count):
     out = np.zeros((count), dtype=np.double)
     out[0] = start
     for x in xrange(count-1):
         out[x+1] = out[x] + np.cos(out[x+1])
     return out

numba_loop = autojit(python_loop)

np.allclose(numba_loop(3,1000),a[:1000,2])
True

%timeit python_loop(3,1000000)
1 loops, best of 3: 4.14 s per loop

%timeit numba_loop(3,1000000)
1 loops, best of 3: 42.5 ms per loop

pi/2これは非常に迅速に収束することを指摘する価値はありますが、任意の開始値に対して約 20 の値を超えるこの再帰を計算することにはほとんど意味がありません。これは、2 倍精度に対してまったく同じ答えを返します。カットオフを見つけるのは面倒ではありませんでしたが、50 よりはるかに小さいです。

%timeit tmp = np.empty((1000000)); 
        tmp[:50] = numba_loop(3,50);
        tmp[50:] = np.pi/2
100 loops, best of 3: 2.25 ms per loop

4 番目の列でも同様のことができます。もちろんautojit、すべての関数を使用できますが、numba の使用法に応じていくつかの異なるオプションを試すことができます。

  1. 最初の 2 列に cumprod を使用する
  2. 最初の数回の反復のみが計算される列 3 (および可能な 4) の近似を使用します。
  3. を使用して numba に列 3 と 4 を実装します。autojit
  4. すべてを autojit ループ内にラップする (最適なオプション)
  5. 〜200を超えるすべての行をこれを提示した方法は、またはのいずれかになりnp.infますnp.pi/2。これを悪用します。
于 2013-12-17T22:17:28.147 に答える
0

少し速くなります。最初の列は基本的に 2^n です。1000000 までの n に対して 2^n を計算するとオーバーフローします.2 番目の列はさらに悪いです。

def calc(arr, t0=1E-6):
    u = arr[0]
    dt = 1E-6
    h = lambda x: np.random.random(1)*50.0

    def firstColGen(uStart):
        u = uStart
        while True:
            u += u
            yield u

    def secondColGen(uStart, A):
        u = uStart
        while True:
            u += u*A
            yield u

    def thirdColGen(uStart):
        u = uStart
        while True:
            u += np.cos(u)
            yield u

    def fourthColGen(uStart, h, t0, dt):
        u = uStart
        t = t0
        while True:
            u += h(u) * dt
            t += dt
            yield u

    first = firstColGen(u[0])
    second = secondColGen(u[1], A)
    third = thirdColGen(u[2])
    fourth = fourthColGen(u[3], h, t0, dt)

    for i in xrange(1, len(arr)):
        arr[i] = [first.next(), second.next(), third.next(), fourth.next()]
于 2013-12-17T19:31:35.283 に答える