我有一个密集的形状矩阵(1 000 000,100)。我想采取所有行的规范。目前我正在使用
import numpy
a = numpy.random.rand((1000000,100))
b = numpy.linalg.norm(a, axis =1) # this takes 2.78 seconds.
有没有办法可以减少这个时间来采取规范?
答案 0 :(得分:2)
使用较小的dtype
;
In [8]: a = numpy.random.rand(1000,1000)
In [9]: %timeit numpy.linalg.norm(a, axis=1)
100 loops, best of 3: 10.4 ms per loop
In [11]: b = numpy.asarray(a, numpy.float32)
In [12]: %timeit numpy.linalg.norm(b, axis=1)
100 loops, best of 3: 3.5 ms per loop
使用优化或并行化的LAPACK库可能也会有所帮助,具体取决于numpy版本。
在运行FreeBSD 10 amd64的Intel Core2 Quad(Q9300)上使用numpy和ATLAS我得到:
In [14]: a = numpy.random.rand(1000000,100)
In [15]: %timeit -n 10 numpy.linalg.norm(a, axis =1)
10 loops, best of 3: 1.08 s per loop
假设你有一台多核机器,还有另外一种方法可以加快思考速度;
multiprocessing.Pool.map()
在多个进程中运行此功能。map()
返回时,将结果列表求和并取该总和的平方根。加速应该大约等于可用内核的数量。
答案 1 :(得分:2)
简单规范是一个内存限制问题,对numpy来说效率不高。 改善它的唯一方法是进行一些阻止以避免多次遍历数据:
import numpy as np
a = np.random.rand(1000000,100)
print np.linalg.norm(a, axis =1).shape
def g(d, out=None):
bs = 2000
if out is None:
r = np.empty(d.shape[0])
else:
r = out
for i in range(0, d.shape[0], bs):
u = min(i + bs, d.shape[0])
r[i:u] = np.linalg.norm(d[i:u], axis=1)
return r
print (g(a) == numpy.linalg.norm(a, axis =1)).all()
print "blocked"
%timeit -n 10 g(a)
print "normal"
%timeit -n 10 numpy.linalg.norm(a, axis =1)
在我的机器(DDR2 ram)上使用numpy 1.9,这会带来适度的改善:
blocked
10 loops, best of 3: 294 ms per loop
normal
10 loops, best of 3: 561 ms per loop
使用线程添加另一层阻塞原则上应该可以提高性能,但是在我的机器上(glibc 2.19),由于glibc经常以线程模式修剪堆,导致页面出错,所以它不会实际上有所帮助。
strace -f -e madvise ipython test_threaded.ipy 2>&1 | grep MADV_DONTNEED -c
14228