在Python中乘以非常大的2D数组

4 投票
2 回答
1326 浏览
提问于 2025-04-18 11:35

我需要在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 个回答

1

矩阵乘法的计算量通常很大,复杂度大约是 O(n³)。在 Numpy 中进行这个操作可能是最快的方式,除非你自己写一个更底层的矩阵乘法程序(像 C 语言那样),但这样做可能还是会更慢。我觉得你现在的做法是最好的,但你要明白,32000x32000 的矩阵非常大,进行任何操作都很吃力,更不用说矩阵乘法了。

这就是坏消息,不过好消息是,我不知道你在处理什么类型的数据,但这些矩阵通常会有一些对称性,这可以大大简化计算。如果你的数据不是完全随机的,那就有希望了,但你需要仔细研究一下你正在处理的矩阵的实际结构。我建议你了解一些“特殊矩阵”,看看你的数据是否属于这些类别。你找到的关于你数据类别的信息,通常也会讨论或引用一些高效的算法来处理这些复杂的操作。

2

正如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']}

撰写回答