python / numpy中multithreading的blas
我正在尝试在Python中实现大量的matrix – matrix乘法。 最初,我认为NumPy会自动使用我的线程化BLAS库,因为我已经针对这些库构build了它。 但是,当我看到顶部或其他东西,似乎代码根本不使用线程。
任何想法什么是错的,或者我能做些什么来轻松使用BLAS的性能?
不是所有的NumPy都使用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尺寸5000和8000的基准。
下表包括原始答案的基准结果(更名为:MKL – > Nehalem MKL,Netlib Blas – > Nehalem Netlib BLAS等)
单线程性能:
multithreading性能(8线程):
线程与matrix大小(Ivy Bridge MKL) :
基准套件
单线程性能:
multithreading(8线程)性能:
结论
新的基准testing结果与原来的答案类似。 除特征值testing外, OpenBLAS和MKL在同一级别上执行。 特征值testing在单线程模式下仅在OpenBLAS上执行得相当好。 在multithreading模式下,性能更差。
“matrix大小vs线程图”还显示,虽然MKL和OpenBLAS一般都可以很好地扩展核心/线程数量,但它取决于matrix的大小。 对于小型matrix来说,增加更多内核不会提高性能。
从Sandy Bridge到Ivy 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)
我确实运行了两个不同的基准:
- 不同尺寸的matrix的简单点积
- 基准套件可以在这里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实现相比)。
GotoBlas2和MKL都可以通过线程数量很好地扩展。 所以如果你必须处理在multithreading上运行的大型matrix,将会有很大的帮助。
在任何情况下都不要使用默认的netlib blas实现,因为对于任何严重的计算工作来说,这太慢了。
在我们的集群上,我还安装了AMD的ACML ,性能类似于MKL和GotoBlas2 。 我没有任何数字艰难。
我个人会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”系统开始。