Blas似乎非常缓慢

6

我正在比较计算机上的矩阵乘法,似乎C++ BLAS非常慢。它需要大约4秒钟才能将一个1000x1000矩阵相乘,而在Python中所需的时间约为1.5秒钟。我认为可能存在链接问题,但我真的不知道如何修复这些问题。以下是C++代码:

    #include <stdio.h>
#include <iostream>
#include <time.h>
#include <gsl/gsl_blas.h>
#include <gsl/gsl_sf_bessel.h>
using namespace std;


double diffclock(clock_t clock1,clock_t clock2) { double diffticks=clock1-clock2; double diffms=(diffticks*1000)/CLOCKS_PER_SEC; return diffms; }




int
main (void)
{
  double* a=new double[1000*1000];

  double* b=new double[1000*1000];

  double* c=new double[1000*1000];

  for (int i=0;i<1000*1000;i++){
  a[i]=i;
  b[i]=i/5+i*i/100;}

  gsl_matrix_view A = gsl_matrix_view_array(a, 1000, 1000);
  gsl_matrix_view B = gsl_matrix_view_array(b, 1000, 1000);
  gsl_matrix_view C = gsl_matrix_view_array(c, 1000, 1000);

  /* Compute C = A B */
  cout<<"start"<<endl;
  clock_t begin=clock();

  gsl_blas_dgemm (CblasNoTrans, CblasNoTrans,
                  1.0, &A.matrix, &B.matrix,
                  0.0, &C.matrix);
  clock_t end=clock();
  cout<<double(diffclock(end,begin))<<endl;

  return 0;  
}

我正在使用以下命令编译: //g++ -o program mm.cpp -I/home/gsl/include -lm -L/home/gsl/lib -lgsl -lgslcblas
这是Python代码:
    import time
import numpy as np



n=1000
a=np.zeros((n,n))
b=np.zeros((n,n))
for i in range(0,n):
    for j in range(0,n):
        a[i,j]=i*n+j
        b[i,j]=(i*n+j)/5+(n*i+j)**2/5
print "start"
start=time.time()
c=np.dot(a,b)
end=time.time()
print end-start

感谢您的帮助!

3
或许 GSL 使用的是“标准”实现,而 NumPy 则使用了优化过的实现(如 Intel MKL 或类似)? - user1220978
我在我的电脑上测试了你的代码。使用相同的编译标志,C++程序运行时间为3.3秒,Python代码运行时间为6.0秒...然而,我使用的是Ubuntu自带的vanilla gsl,而你似乎在使用一个安装在/home目录下的gsl...你是自己编译的吗?如果是,你是如何编译的? - dsign
也许吧,但我如何检查/修复它?有什么快速解决方案吗?当涉及到链接/编译/安装库时,我真的是个新手。 - Jonathan Lindgren
将优化标志添加到我的程序中是什么意思? - Jonathan Lindgren
2
使用4核线程mkl BLAS运行您的DGEMM仅需要41微秒。@arbautjc:请注意,除非在编译时指定BLAS或某些预编译二进制文件也包含此内容,否则numpy不会使用BLAS。 - Daniel
显示剩余5条评论
1个回答

3
BLAS中的子程序是事实上的标准,存在许多经过优化和供应商特定的库来实现该界面。numpy和gsl都可以链接到各种不同的BLAS(或在某些情况下使用自己的实现),但从这个角度来看,numpy和gsl基本上只是包装器——您获得的性能基本上仅取决于它们链接到的BLAS。
对于GSL来说,相对容易链接到替代的BLAS。这里有一些说明:http://www.gnu.org/software/gsl/manual/html_node/Linking-with-an-alternative-BLAS-library.html 英特尔的MKL是一种通常非常快速的BLAS(至少如果您没有AMD CPU),但众所周知很难链接。他们甚至有一个网络应用程序来帮助您编写链接行:http://software.intel.com/en-us/articles/intel-mkl-link-line-advisor。我在i7-3770K CPU上使用OpenBLAS(http://www.openblas.net/)运行得相当好,性能与MKL相比仅高出1或2%。OpenBLAS也相当容易编译;比ATLAS少得多的头痛。
一旦您获得了OpenBLAS,无论是从源代码编译还是从* nix下载,您修改后的编译行就基本上是:
g++ -o program mm.cpp -I/home/gsl/include -lm -L/home/gsl/lib -lgsl -lcblas -lopenblas 

你有没有关于在MSVC上将GSL与MKL链接的建议? - Siav Josep

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接