我有一个m x n
数组:a
,其中整数为m > 1E6
,n <= 5
。
我的功能 F 和 G ,其组成如下: F (你, G (你,t))。 你是1 x n
数组,t是标量, F 和 G 返回1 x n
数组。
我需要评估 F 中row
的每个a
,并使用以前评估的行作为 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
上面代码的问题在于它很慢。我需要通过numpy毫秒来完成这些计算。
我怎样才能做我想做的事?
感谢您抽出时间。
亲切的问候,
的Marius
答案 0 :(得分: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]
可以沿着相同的路线完成。
我不相信有一种方法可以快速地单独使用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个值几乎没有意义。这会给双点精度返回完全相同的答案 - 我没有找到截止值,但它远小于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
您可以使用第四列执行类似操作。当然你可以autojit
所有的功能,但是根据numba的使用情况,这会给你几种不同的选择:
autojit
np.inf
或np.pi/2
。利用它。答案 1 :(得分:0)
稍快一些。你的第一列基本上是2n。计算n ^到1000000的2 ^ n会溢出。第二列甚至更糟。
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()]