我需要将两个大矩阵相乘并对它们的列进行排序。
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]
此过程需要大量时间和内存。有没有办法加快这个过程?如果不是,我如何计算执行此操作所需的 RAM?我目前有一个带有 4GB RAM 且没有交换空间的 EC2 盒子。
我想知道这个操作是否可以序列化,我不必将所有内容都存储在内存中。
最佳答案
为了加快速度,您可以做的一件事是使用优化的 BLAS 库编译 numpy,例如ATLAS、GOTO blas 或英特尔专有的 MKL。
要计算所需的内存,您需要监控 Python 的驻留集大小(“RSS”)。以下命令在 UNIX 系统(准确地说是 FreeBSD,在 64 位机器上)上运行。
> 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)
为了获取我运行的 RSS:
ps -xao comm,rss | grep python
[编辑:请参阅 ps
manual page有关选项的完整说明,但基本上这些 ps
选项使其仅显示所有进程的命令和驻留集大小。我相信 Linux 的 ps
的等效格式是 ps -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
如您所见,计算出的大小与默认数据类型 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
这还不算太糟糕。但是,点积会太大:
In [19]: 8*1000000*300000/1024**3
Out[19]: 2235.1741790771484
那是 2235 GiB!
你可以做的是将问题拆分,然后将 dot
操作分成几部分来执行;
- 加载
b
作为 ndarray - 将
a
中的每一行依次加载为ndarray
。 - 将行乘以
b
的每一列并将结果写入文件。 del()
该行并加载下一行。
这不会让它变得更快,但它会使用更少的内存!
编辑: 在这种情况下,我建议以二进制格式编写输出文件(例如使用 struct
或 ndarray.tofile
)。这将使从文件中读取列变得更加容易,例如一个 numpy.memmap
。
关于Python NUMPY HUGE 矩阵乘法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25046076/