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盒子.
我想知道这个操作是否可以序列化,我不必将所有内容存储在内存中.
你可以做的一件事就是加速编译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的等效格式ps
是ps -xao c,r
.
结果是;
a
:42200 kiBa
: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
为ndarraya
作为ndarray
反过来.b
并将结果写入文件.del()
行并加载下一行.这不会使它更快,但它会使它使用更少的内存!
编辑:在这种情况下,我建议以二进制格式编写输出文件(例如使用struct
或ndarray.tofile
).这样可以更容易地从文件中读取列,例如a numpy.memmap
.
DrV和Roland Smith所说的都是很好的答案;他们的意见应该得到倾听。我的回答只不过是提供一个使数据稀疏的选项,一个彻底的游戏规则改变者。
稀疏性可能非常强大。它将您的O(100 * 300000 * 1000000)
操作转换为O(k)
具有 k 个非零元素的操作(稀疏性仅意味着矩阵很大程度上为零)。我知道 DrV 提到过稀疏性,并认为它不适用而被忽略,但我猜它是适用的。
需要做的就是找到一个稀疏表示来计算这个变换(解释结果是另一回事)。简单(且快速)的方法包括傅里叶变换或小波变换(两者都依赖于矩阵元素之间的相似性),但这个问题可以通过几种不同的算法来推广。
有了解决此类问题的经验,这听起来像是一个相对常见的问题,通常可以通过一些巧妙的技巧来解决。在机器学习这样的领域,这些类型的问题被归类为“简单”,这种情况经常发生。
归档时间: |
|
查看次数: |
8002 次 |
最近记录: |