基准(Python与C++使用BLAS)和(NUMPY)

我想写一个程序,广泛使用BLAS和LAPACK线性代数功能。由于性能是一个问题,我做了一些基准测试,想知道我采取的方法是否合法

可以说,我有三位参赛者,我想用一个简单的矩阵乘法来测试他们的表现。参赛者包括:

  1. Numpy,仅使用dot的功能
  2. Python,通过共享对象调用BLAS功能
  3. C++,通过共享对象调用BLAS功能

情景

我实现了不同维度的矩阵乘法Ii从5运行到500,增量为5,矩阵m1m2的设置如下:

m1=numpy.random.rand(i,i).astype(numpy.float32)
m2=numpy.random.rand(i,i).aType(numpy.float32)

一,。努比

使用的代码如下所示:

tNumpy=timeit.Timer(“numpy.dot(m1,m2)”,“导入numpy;从主导入m1,m2”)
rNumpy.append((i,tNumpy.repeat(20,1)))

二,。Python,通过共享对象调用BLAS

带函数

\u blaslib=ctypes.cdll.LoadLibrary(“libblas.so”)
def Mul(m1、m2、i、r):
无字符转换=c字符(“n”)
n=c_int(i)
一=c_浮动(1.0)
零=c_浮动(0.0)
_blaslib.sgemm_(byref(no_trans)、byref(no_trans)、byref(n)、byref(n)、byref(n),
byref(一),m1.ctypes.data_as(ctypes.c_void_p),byref(n),
m2.ctypes.data_as(ctypes.c_void_p),byref(n),byref(零),
r、 ctypes.data_as(ctypes.c_void_p),byref(n))

测试代码如下所示:

r=numpy.zero((i,i),numpy.float32)
tBlas=timeit.Timer(“Mul(m1,m2,i,r)”,“导入numpy;从主导入i,m1,m2,r,Mul”)
rBlas.append((i,tBlas.repeat(20,1)))

三,。C++,通过共享对象

调用BLAS
现在C++代码自然会更长一点,所以我把信息减少到最小。
我用

void*handle=dlopen(“libblas.so”,RTLD\u LAZY);
void*Func=dlsym(手柄,“sgemm”);

我用gettimeofday测量时间,如下所示:

gettimeofday(&start,NULL);
f(&no_trans,&no_trans,&dim,&dim,&one,A,&dim,B,&dim,&zero,Return,&dim);
gettimeofday(&end,NULL);
dTimes[j]=计算时间(开始、结束);

其中j是运行20次的循环。我计算着时间的流逝

双计算时间(timeval开始,timeval结束)
{
双因子=1000000;
返回(((双)端.tv_-sec)*因子+((双)端.tv_-usec)-((双)启动.tv_-sec)*因子+((双)启动.tv_-usec))/factor;
}

结果

结果如下图所示:

问题

  1. 你认为我的方法公平吗,或者我可以避免一些不必要的开销吗
  2. LI>你会期待结果会显示C++和Python方法之间的巨大差异吗?两者都使用共享对象进行计算

  3. 既然我更愿意在程序中使用python,那么在调用BLAS或LAPACK例程时,我可以做些什么来提高性能呢

下载

完整的基准可以在这里下载。(J.F.塞巴斯蒂安使这种联系成为可能)

更新(30.07.2014):

我在新HPC上重新运行了基准测试。
硬件和软件堆栈都与原始答案中的设置不同

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

硬件

我们的HPC有两个不同的节点,一个使用Intel Sandy Bridge CPU,另一个使用较新的Ivy Bridge CPU:

桑迪(MKL、OpenBLAS、阿特拉斯):

  • CPU:2 x 16英特尔(R)至强(R)E2560沙桥@2.00GHz(16核)
  • RAM:64 GB

常春藤(MKL、OpenBLAS、ATLAS):

  • CPU:2 x 20英特尔(R)至强(R)E2680 V2常春藤网桥@2.80GHz(20核,HT=40核)
  • RAM:256 GB

软件

多线程的也被用于BLAS strong的多线程堆栈中

  • 操作系统:Suse
  • 英特尔编译器:ictce-5.3.0
  • Numpy:1.8.0
  • OpenBLAS:0.2.6
  • 图集::3.8.4

Dot产品基准

基准代码如下所示。然而,对于新机器,我还运行了矩阵大小50008000的基准测试
下表包括原始答案的基准测试结果(重命名为:MKL–>Nehalem MKL、Netlib Blas–>Nehalem Netlib Blas等)

单线程性能:

多线程性能(8线程):

螺纹与基体尺寸(常春藤桥MKL)

基准测试套件

单线程性能:

多线程(8线程)性能:

结论

新的基准测试结果与原始答案中的结果相似OpenBLASMKL在同一水平上执行,但特征值测试除外。
特征值测试仅在单线程模式下的OpenBLAS上运行良好。
在多线程模式下,性能更差

“矩阵大小与线程图表”还显示,尽管MKL和OpenBLAS通常能很好地随内核/线程的数量扩展,但这取决于矩阵的大小。对于较小的矩阵,添加更多的内核并不会大大提高性能

从沙桥到常春藤桥的性能也有大约30%的提高,这可能是由于更高的时钟频率(+0.8 Ghz)和/或更好的体系结构


原始答复(2011年10月4日):

不久前,我不得不优化一些使用numpy和BLAS用python编写的线性代数计算/算法,因此我对不同的numpy/BLAS配置进行了基准测试/测试

我特别测试了:

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

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

  1. 不同尺寸矩阵的简单点积
  2. 可以在这里找到基准测试套件

以下是我的结果:

机器

Linux(MKL,ATLAS,无MKL,GotoBlas2):

  • OS:Ubuntu Lucid 10.4 64位
  • CPU:2 x 4英特尔(R)至强(R)[email protected](8核)
  • 内存:24 GB
  • 英特尔编译器:11.1/073
  • Scipy:0.8
  • Numpy:1.5

Mac Book Pro(加速框架):

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

Mac服务器(加速框架):

  • OS:Mac OS X雪豹服务器(10.6)
  • CPU:4 X Intel(R)Xeon(R)[email protected] Ghz(8核)
  • 内存:4 GB
  • Scipy:0.8
  • Numpy:1.5.1

Dot产品基准

代码

将numpy导入为np
a=np.随机.随机样本((大小,大小))
b=np.随机.随机样本((大小,大小))
%timeit np.dot(a,b)

结果

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

基准测试套件

代码
有关基准测试套件的更多信息,请参见此处

结果

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

装置

仪表

发表评论