Python NUMPY HUGE Matrices乘法

pg2*_*455 6 python performance numpy matrix-multiplication

我需要将两个大矩阵相乘并对其列进行排序.

 import numpy
 a= numpy.random.rand(1000000, 100)
 b= numpy.random.rand(300000,100)
 c= numpy.dot(b,a.T)
 sorted = [argsort(j)[:10] for j in c.T]
Run Code Online (Sandbox Code Playgroud)

这个过程需要大量的时间和内存.有没有办法加快这个过程?如果不是,我如何计算执行此操作所需的RAM?我目前有一个带有4GB RAM且没有交换的EC2盒子.

我想知道这个操作是否可以序列化,我不必将所有内容存储在内存中.

Rol*_*ith 8

你可以做的一件事就是加速编译numpy与优化的BLAS库,例如ATLAS,GOTO blas或英特尔专有的MKL.

要计算所需的内存,您需要监视Python的驻留集大小("RSS").以下命令在UNIX系统上运行(准确地说,在64位计算机上运行FreeBSD).

> ipython

In [1]: import numpy as np

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

In [3]: a.dtype
Out[3]: dtype('float64')

In [4]: del(a)
Run Code Online (Sandbox Code Playgroud)

要获得我运行的RSS:

ps -xao comm,rss | grep python
Run Code Online (Sandbox Code Playgroud)

[ 编辑:有关选项的完整说明,请参见ps手册页,但基本上这些ps选项使其仅显示所有进程的命令和驻留集大小.我相信,Linux的等效格式psps -xao c,r.

结果是;

  • 开始翻译后:24880 kiB
  • 导入numpy后:34364 kiB
  • 创建后a:42200 kiB
  • 删除后a:34368 kiB

计算大小;

In [4]: (42200 - 34364) * 1024
Out[4]: 8024064

In [5]: 8024064/(1000*1000)
Out[5]: 8.024064
Run Code Online (Sandbox Code Playgroud)

如您所见,计算出的大小float64非常适合默认数据类型的8个字节.不同之处在于内部开销.

MiB中原始阵列的大小约为;

In [11]: 8*1000000*100/1024**2
Out[11]: 762.939453125

In [12]: 8*300000*100/1024**2
Out[12]: 228.8818359375
Run Code Online (Sandbox Code Playgroud)

那不算太糟糕.但是,点积太大了:

In [19]: 8*1000000*300000/1024**3
Out[19]: 2235.1741790771484
Run Code Online (Sandbox Code Playgroud)

那是2235 GiB!

你能做的就是分解问题并将dot操作分成几部分;

  • 加载b为ndarray
  • 加载每一行从a作为ndarray反过来.
  • 将行乘以每列,b并将结果写入文件.
  • del() 行并加载下一行.

这不会使它更快,但它会使它使用更少的内存!

编辑:在这种情况下,我建议以二进制格式编写输出文件(例如使用structndarray.tofile).这样可以更容易地从文件中读取列,例如a numpy.memmap.


Sco*_*ott 5

DrV和Roland Smith所说的都是很好的答案;他们的意见应该得到倾听。我的回答只不过是提供一个使数据稀疏的选项,一个彻底的游戏规则改变者。

稀疏性可能非常强大。它将您的O(100 * 300000 * 1000000)操作转换为O(k)具有 k 个非零元素的操作(稀疏性仅意味着矩阵很大程度上为零)。我知道 DrV 提到过稀疏性,并认为它不适用而被忽略,但我猜它是适用的。

需要做的就是找到一个稀疏表示来计算这个变换(解释结果是另一回事)。简单(且快速)的方法包括傅里叶变换小波变换(两者都依赖于矩阵元素之间的相似性),但这个问题可以通过几种不同的算法来推广。

有了解决此类问题的经验,这听起来像是一个相对常见的问题,通常可以通过一些巧妙的技巧来解决。在机器学习这样的领域,这些类型的问题被归类为“简单”,这种情况经常发生。