【问题标题】:Multiplying very large 2D-array in Python在 Python 中乘以非常大的二维数组
【发布时间】:2014-08-20 20:41:24
【问题描述】:

我必须在 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 脚本只使用一个核心。此外,在 3h25m 之后,只进行了 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,我只收到{},没有任何警告或错误。

【问题讨论】:

  • 有没有什么办法可以将数组拆分成多个子数组并在多个线程或进程上运行?
  • “很长时间”是什么意思?
  • 数据从何而来?您是否应该为此使用稀疏矩阵?
  • 根据@ali_m 的问题,这一切都归结为您使用的是什么 BLAS。在 Haswell i7 上使用线程化英特尔 MKL 大约需要 5 分钟 您的里程可能会有所不同,但这应该是一个合理的下限。
  • 好的,祝你好运 - 你可能会发现 this guide 很有帮助。

标签: python arrays performance numpy matrix


【解决方案1】:

正如 ali_m 所建议的,使用 BLAS 库可以加快操作速度。但是,我系统中的问题是 numpy 的错误配置。这是解决方案:

1) 确保拥有所有必需的库(您可以使用 ATLAS、OpenBLAS 等)。自从 Ubuntu 直接支持以来,我就选择了 ATLAS。

sudo apt-get install libatlas3gf-base libatlas-base-dev libatlas-dev

2) 删除任何以前的 numpy 安装,例如,pypm uninstall numpy(如果您使用 ActivePython 安装它)

3) 使用 pip 再次安装 numpy:pip install numpy

4) 确保您的图集正确链接:

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

【讨论】:

  • 您可能有兴趣知道 OpenBLAS 也作为软件包提供在 Ubuntu 存储库 (libopenblas-base / libopenblas-dev) 中。根据我的经验,OpenBLAS 比 ATLAS 快很多,但这可能取决于您的 CPU 型号。
  • 是的,我知道了,再次感谢您。它们确实在存储库中,但由于我已经拥有 ATLAS,突触警告我安装这些库可能会破坏其他库。我什至在/opt/OpenBLAS 中安装了一个独立的OpenBLAS,但如果pip 安装了numpy,我认为我无法利用它。仅当从源代码(例如 github 存储库)安装 numpy 时,它才应该可以链接到不同的库,对吧?
  • 如果您更喜欢使用 pip 而不是从 git 存储库构建 numpy,您仍然可以通过在主目录中创建 .numpy-site.cfg 文件来使其尊重特定配置( see here)
  • 嘿,只是更新。我不得不按照 ali_m 的建议切换到 OpenBLAS,因为 ATLAS 没有利用多线程。现在我的脚本利用了所有 12 个内核,并且操作速度要快得多。
【解决方案2】:

矩阵乘法总是很昂贵,特别是在 O(n3) 左右。在 Numpy 中执行此操作可能是处理它的最快方法,而不是在“更接近金属”的已编译程序(如 C)中编写自己的矩阵乘法器......这可能仍然会更慢。我认为您正在以最佳方式执行此操作,但您必须意识到 32000x32000 矩阵非常大,无法执行任何操作,更不用说矩阵乘法了。

这是个坏消息,但这是个好消息。我不知道您正在使用什么类型的数据,但可能存在并且经常存在相关矩阵的对称性,这可以大大简化计算。如果您的数据不是完全随机的,可能会有希望,但您必须查看您正在使用的矩阵的实际结构。我建议阅读一些“特殊矩阵”,看看您的数据是否属于这些类别之一。您在数据类别中找到的任何信息也应该讨论或引用有效的算法来管理昂贵的操作。

【讨论】:

  • 感谢您的贡献。请阅读我的帖子中的所有其他 cmets。您的问题有答案。
  • 对不起。我确定我是短视的,但我仍然不清楚矩阵中数据的来源是什么......如果你为我拼写出来,也许我会更有帮助。
  • 这是数据集:snap.stanford.edu/data/as-caida.html。我构建了一个有向图(使用 networkx),然后将其转换为右随机图(goo.gl/dAZT8G)。最后,我将该图转换为一个完全随机的 numpy 二维数组以执行我的乘法运算。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 2019-01-13
  • 1970-01-01
  • 2019-01-30
  • 2017-02-24
  • 2010-09-08
相关资源
最近更新 更多