python / numpy中multithreading的blas

我正在尝试在Python中实现大量的matrix – matrix乘法。 最初,我认为NumPy会自动使用我的线程化BLAS库,因为我已经针对这些库构build了它。 但是,当我看到顶部或其他东西,似乎代码根本不使用线程。

任何想法什么是错的,或者我能做些什么来轻松使用BLAS的性能?

不是所有的Nu​​mPy都使用BLAS,只有一些函数 – 特别是dot()vdot()innerproduct()以及numpy.linalg模块中的几个函数。 还要注意,许多NumPy操作都受到大型数组内存带宽的限制,所以优化的实现不太可能有任何改进。 如果受限于内存带宽,multithreading是否可以提供更好的性能,这在很大程度上取决于您的硬件。

我已经在另一个线程中发布了这个,但是我认为它更适合这个:

更新(30.07.2014):

我重新运行我们新的HPC的基准。 硬件以及软件堆栈从原始答案中的设置改变了。

我把结果放在一个谷歌电子表格 (也包含原始答案的结果)。

硬件

我们的HPC有两个不同的节点,一个是英特尔Sandy Bridge CPU,一个是较新的Ivy Bridge CPU:

桑迪 (MKL,OpenBLAS,ATLAS):

  • CPU :2 x 16英特尔(R)至强(R)E2560 Sandy Bridge @ 2.00GHz(16核)
  • 内存 :64 GB

常春藤 (MKL,OpenBLAS,ATLAS):

  • CPU :2 x 20英特尔(R)Xeon E2680 V2 Ivy Bridge @ 2.80GHz(20核,HT = 40核)
  • 内存 :256 GB

软件

软件堆栈是两个节点的山姆。 使用OpenBLAS代替GotoBLAS2 ,并且还有一个multithreading的ATLAS BLAS被设置为8个线程(硬编码)。

  • OS :Suse
  • 英特尔编译器 :ictce-5.3.0
  • Numpy: 1.8.0
  • OpenBLAS: 0.2.6
  • ATLAS :3.8.4

点积产品基准

基准代码与以下相同。 但是,对于新机器,我还运行了matrix尺寸50008000的基准。
下表包括原始答案的基准结果(更名为:MKL – > Nehalem MKL,Netlib Blas – > Nehalem Netlib BLAS等)

矩阵乘法(大小= [1000,2000,3000,5000,8000])

单线程性能: 单线程性能

multithreading性能(8线程): 多线程(8线程)性能

线程与matrix大小(Ivy Bridge MKL)矩阵大小vs线程

基准套件

基准套件

单线程性能: 在这里输入图像描述

multithreading(8线程)性能: 在这里输入图像描述

结论

新的基准testing结果与原来的答案类似。 除特征值testing外, OpenBLASMKL在同一级别上执行。 特征值testing在单线程模式下仅在OpenBLAS上执行得相当好。 在multithreading模式下,性能更差。

“matrix大小vs线程图”还显示,虽然MKL和OpenBLAS一般都可以很好地扩展核心/线程数量,但它取决于matrix的大小。 对于小型matrix来说,增加更多内核不会提高性能。

Sandy BridgeIvy Bridge ,性能也会提高大约30%,这可能是由于更高的时钟速率(+ 0.8 Ghz)和/或更好的架构。


原答复(04.10.2011):

前一段时间,我不得不优化一些线性代数计算/algorithm,这些algorithm是使用numpy和BLAS编写的,所以我testing了不同的numpy / BLASconfiguration。

具体我testing了:

  • 与ATLAS的Numpy
  • 与GotoBlas2 (1.13)
  • 用MKL(11.1 / 073)
  • 加速框架的Numpy(Mac OS X)

我确实运行了两个不同的基准:

  1. 不同尺寸的matrix的简单点积
  2. 基准套件可以在这里find。

这是我的结果:

Linux (MKL,ATLAS,No-MKL,GotoBlas2):

  • 操作系统 :Ubuntu Lucid 10.4 64位。
  • CPU :2 x 4英特尔(R)至强(R)E5504 @ 2.00GHz(8核)
  • 内存 :24 GB
  • 英特尔编译器 :11.1 / 073
  • Scipy :0.8
  • Numpy :1.5

Mac Book Pro (加速框架):

  • 操作系统 :Mac OS X Snow Leopard(10.6)
  • CPU :1个Intel Core 2 Duo 2.93 Ghz(2核)
  • 内存 :4 GB
  • Scipy :0.7
  • Numpy :1.3

Mac服务器 (加速框架):

  • 操作系统 :Mac OS X雪豹服务器(10.6)
  • CPU :4 X Intel(R)Xeon(R)E5520 @ 2.26 Ghz(8核)
  • 内存 :4 GB
  • Scipy :0.8
  • Numpy :1.5.1

点产品基准

代码

 import numpy as np a = np.random.random_sample((size,size)) b = np.random.random_sample((size,size)) %timeit np.dot(a,b) 

结果

    系统|  size = 1000 |  size = 2000 |  size = 3000 |
 netlib BLAS |  1350 ms |  10900 ms |  39200 ms |    
 ATLAS(1个CPU)|  314 ms |  2560 ms |  8700 ms |     
 MKL(1个CPU)|  268 ms |  2110 ms |  7120 ms |
 MKL(2个CPU)|  -  |  -  |  3660 ms |
 MKL(8个CPU)|  39 ms |  319 ms |  1000 ms |
 GotoBlas2(1 CPU)|  266 ms |  2100 ms |  7280 ms |
 GotoBlas2(2个CPU)|  139 ms |  1009 ms |  3690 ms |
 GotoBlas2(8个CPU)|  54 ms |  389 ms |  1250 ms |
 Mac OS X(1个CPU)|  143 ms |  1060 ms |  3605 ms |
 Mac服务器(1个CPU)|  92 ms |  714 ms |  2130 ms |

点产品基准 - 图表

基准套件

代码
有关基准套件的更多信息,请参阅此处 。

结果

    系统| 特征值|  svd |  det |  inv | 点|
 netlib BLAS |  1688 ms |  13102 ms |  438 ms |  2155 ms |  3522 ms |
 ATLAS(1个CPU)|  1210 ms |  5897 ms |  170 ms |  560 ms |  893 ms |
 MKL(1个CPU)|  691 ms |  4475 ms |  141 ms |  450 ms |  736 ms |
 MKL(2个CPU)|  552 ms |  2718 ms |  96 ms |  267 ms |  423 ms |
 MKL(8个CPU)|  525 ms |  1679 ms |  60 ms |  137 ms |  197 ms |  
 GotoBlas2(1 CPU)|  2124 ms |  4636 ms |  147 ms |  456 ms |  743 ms |
 GotoBlas2(2个CPU)|  1560 ms |  3278 ms |  116 ms |  295 ms |  460 ms |
 GotoBlas2(8个CPU)|  741 ms |  2914 ms |  82 ms |  262 ms |  192 ms |
 Mac OS X(1个CPU)|  948 ms |  4339 ms |  151 ms |  318 ms |  566 ms |
 Mac服务器(1个CPU)|  1033 ms |  3645 ms |  99 ms |  232 ms |  342 ms |

基准套件 - 图表

安装

安装MKL包括安装完整的英特尔编译器套件,这非常简单。 然而,由于一些错误/问题configuration和编译与MKL支持numpy有点麻烦。

GotoBlas2是一个小软件包,可以很容易地编译为共享库。 然而,由于一个bug,你必须在创build共享库之后重新创build共享库,才能使用numpy。
除了这个build筑物,它为多个目标plattform没有工作的原因。 所以我不得不为每个平台创build一个.so文件,我想要一个优化的libgoto2.so文件。

如果您从Ubuntu的存储库安装numpy,它会自动安装并configurationnumpy以使用ATLAS 。 从源代码安装ATLAS可能需要一些时间,并需要一些额外的步骤(fortran等)。

如果你在Mac OS X机器上安装numpy,使用Fink或者Mac Ports,它可以configurationnumpy使用ATLAS或者Apple的Accelerate Framework 。 您可以通过在numpy.core._dotblas文件上运行ldd或调用numpy.show_config()来检查

结论

MKL的执行情况最好紧随GotoBlas2
特征值testing中,GotoBlas2的performance比预期的要差得多。 不知道为什么这样。
苹果公司的Accelerate Framework在单线程模式下性能非常好(与其他BLAS实现相比)。

GotoBlas2MKL可以通过线程数量很好地扩展。 所以如果你必须处理在multithreading上运行的大型matrix,将会有很大的帮助。

在任何情况下都不要使用默认的netlib blas实现,因为对于任何严重的计算工作来说,这太慢了。

在我们的集群上,我还安装了AMD的ACML ,性能类似于MKLGotoBlas2 。 我没有任何数字艰难。

我个人会build议使用GotoBlas2,因为它更容易安装,而且是免费的。

如果你想用C ++ / C编写代码,在一些情况下 ,也可以查看Eigen3 ,它的性能要优于MKL / GotoBlas2 ,而且使用起来也相当简单。

这可能是因为matrixxmatrix乘法是内存限制,在相同的存储器层次结构上添加额外的内核并不会给你太多。 当然,如果在切换到Fortran实现时看到实质性的加速,那么我可能是不正确的。

我的理解是适当的caching对于这些问题要比计算能力重要得多。 大概BLAS为你做这个。

对于一个简单的testing,你可以尝试安装Enthought的 python发行版进行比较。 他们链接英特尔的math核心图书馆 ,我相信,如果有的话可以利用多个核心。

你有没有听说过MAGMA? GPU和多核架构上的matrix代数http://icl.cs.utk.edu/magma/

MAGMA项目的目标是开发一个类似于LAPACK的密集线性代数库,但是针对异构/混合体系结构,从当前的“多核+ GPU”系统开始。