我正在尝试沿着非常大的2D numpy数组的一维找到最小的数组索引。我发现这非常慢(已经尝试过瓶颈来加快速度,这只是最小的改进)。但是,采用直线最小值似乎要快一个数量级:

import numpy as np
import time

randvals = np.random.rand(3000,160000)
start = time.time()
minval = randvals.min(axis=0)
print "Took {0:.2f} seconds to compute min".format(time.time()-start)
start = time.time()
minindex = np.argmin(randvals,axis=0)
print "Took {0:.2f} seconds to compute argmin".format(time.time()-start)

在我的机器上,输出:
Took 0.83 seconds to compute min
Took 9.58 seconds to compute argmin

有什么理由使argmin这么慢?有什么方法可以将其加速到最小?

最佳答案

In [1]: import numpy as np

In [2]: a = np.random.rand(3000, 16000)

In [3]: %timeit a.min(axis=0)
1 loops, best of 3: 421 ms per loop

In [4]: %timeit a.argmin(axis=0)
1 loops, best of 3: 1.95 s per loop

In [5]: %timeit a.min(axis=1)
1 loops, best of 3: 302 ms per loop

In [6]: %timeit a.argmin(axis=1)
1 loops, best of 3: 303 ms per loop

In [7]: %timeit a.T.argmin(axis=1)
1 loops, best of 3: 1.78 s per loop

In [8]: %timeit np.asfortranarray(a).argmin(axis=0)
1 loops, best of 3: 1.97 s per loop

In [9]: b = np.asfortranarray(a)

In [10]: %timeit b.argmin(axis=0)
1 loops, best of 3: 329 ms per loop

也许min足够聪明,可以按顺序在阵列上完成其工作(因此具有高速缓存局部性),并且argmin在阵列上跳跃(导致很多高速缓存未命中)?

无论如何,如果您愿意从一开始就将randvals保留为按Fortran顺序排列的数组,则它会更快,尽管复制到按Fortran顺序排列无济于事。

08-20 04:01