在不到一秒的时间内采用HUGE矩阵的规范:NUMPY,PYTHON

时间:2014-08-01 17:54:13

标签: python numpy

我有一个密集的形状矩阵(1 000 000,100)。我想采取所有行的规范。目前我正在使用

import numpy
a =  numpy.random.rand((1000000,100))
b = numpy.linalg.norm(a, axis =1) # this takes 2.78 seconds.

有没有办法可以减少这个时间来采取规范?

2 个答案:

答案 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