我正在尝试沿着非常大的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顺序排列无济于事。