在Python中乘以非常大的2D数组
我需要在Python中对非常大的二维数组进行大约100次的乘法运算。每个矩阵都有32000x32000
个元素。
我正在使用np.dot(X,Y)
,但是每次乘法运算都花费很长时间……下面是我的代码示例:
import numpy as np
X = None
for i in range(100)
multiplying = True
if X == None:
X = generate_large_2darray()
multiplying = False
else:
Y = generate_large_2darray()
if multiplying:
X = np.dot(X, Y)
有没有其他更快的方法呢?
更新
这里有一张截图,显示了htop界面。我的Python脚本只在使用一个核心。而且,经过3小时25分钟,只完成了4次乘法运算。
更新 2
我尝试执行:
import numpy.distutils.system_info as info
info.get_info('atlas')
但我收到了:
/home/francescof/.local/lib/python2.7/site-packages/numpy/distutils/system_info.py:564: UserWarning: Specified path /home/apy/atlas/lib is invalid. warnings.warn('Specified path %s is invalid.' % d) {}
所以,我觉得配置可能不太好。
相反,关于blas
我只收到了{}
,没有任何警告或错误。
2 个回答
矩阵乘法的计算量通常很大,复杂度大约是 O(n³)。在 Numpy 中进行这个操作可能是最快的方式,除非你自己写一个更底层的矩阵乘法程序(像 C 语言那样),但这样做可能还是会更慢。我觉得你现在的做法是最好的,但你要明白,32000x32000 的矩阵非常大,进行任何操作都很吃力,更不用说矩阵乘法了。
这就是坏消息,不过好消息是,我不知道你在处理什么类型的数据,但这些矩阵通常会有一些对称性,这可以大大简化计算。如果你的数据不是完全随机的,那就有希望了,但你需要仔细研究一下你正在处理的矩阵的实际结构。我建议你了解一些“特殊矩阵”,看看你的数据是否属于这些类别。你找到的关于你数据类别的信息,通常也会讨论或引用一些高效的算法来处理这些复杂的操作。
正如ali_m所建议的,使用BLAS库可以加快运算速度。不过,我系统中的问题是numpy配置不当。以下是解决方案:
1) 确保安装所有需要的库(你可以使用ATLAS、OpenBLAS等)。在我的情况下,我选择了ATLAS,因为它在Ubuntu中直接支持。
sudo apt-get install libatlas3gf-base libatlas-base-dev libatlas-dev
2) 删除之前安装的numpy,比如说,pypm uninstall numpy
(如果你是用ActivePython安装的)
3) 通过pip重新安装numpy:pip install numpy
4) 确保你的ATLAS库链接正确:
import numpy.distutils.system_info as info
info.get_info('atlas')
ATLAS version 3.8.4 built by buildd on Sat Sep 10 23:12:12 UTC 2011:
UNAME : Linux crested 2.6.24-29-server #1 SMP Wed Aug 10 15:58:57 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux
INSTFLG : -1 0 -a 1
ARCHDEFS : -DATL_OS_Linux -DATL_ARCH_HAMMER -DATL_CPUMHZ=1993 -DATL_USE64BITS -DATL_GAS_x8664
F2CDEFS : -DAdd_ -DF77_INTEGER=int -DStringSunStyle
CACHEEDGE: 393216
F77 : gfortran, version GNU Fortran (Ubuntu/Linaro 4.6.1-9ubuntu2) 4.6.1
F77FLAGS : -fomit-frame-pointer -mfpmath=387 -O2 -falign-loops=4 -Wa,--noexecstack -fPIC -m64
SMC : gcc, version gcc (Ubuntu/Linaro 4.6.1-9ubuntu2) 4.6.1
SMCFLAGS : -fomit-frame-pointer -mfpmath=387 -O2 -falign-loops=4 -Wa,--noexecstack -fPIC -m64
SKC : gcc, version gcc (Ubuntu/Linaro 4.6.1-9ubuntu2) 4.6.1
SKCFLAGS : -fomit-frame-pointer -mfpmath=387 -O2 -falign-loops=4 -Wa,--noexecstack -fPIC -m64
{'libraries': ['lapack', 'f77blas', 'cblas', 'atlas'], 'library_dirs': ['/usr/lib/atlas-base/atlas', '/usr/lib/atlas-base'], 'define_macros': [('ATLAS_INFO', '"\\"3.8.4\\""')], 'language': 'f77', 'include_dirs': ['/usr/include/atlas']}