2017-03-16 211 views
0

首先,这是一个请求,不要将这个问题标记为重复,因为一旦详细研究它就会清楚。为什么MEX代码比matlab代码慢得多?

我正在尝试实现正交匹配追踪算法。为此,我需要找到尺寸的两个矩阵的点积如下图所示

 clc,clear; 

     load('E'); 
     load('R'); 
     load('P'); 


     sparse=zeros(14596,2209); 

      dictionary=tem2; 

      atoms=zeros(size(dictionary,1),size(dictionary,2)); 
      coefs=zeros(size(dictionary,2),1); 
     tic 
      %Normalize the dictionary 
      for index=1:size(dictionary,2) 
       dictionary(:,index)=dictionary(:,index)./norm(dictionary(:,index)); 
      end 
      D=dictionary; 

     /* NOTE: I tried for ii=1:5 to check the difference in computational time*/ 

     for ii=1:2209 

      r=tem4(:,ii); 
      dictionary=D; 
      index=[]; 
      count=0; 
      t=5; 
      while(t>1e-15 && count~=144) 
    /***************Problem lies here**************/ 
     % inner_product=dictionary'*r; %Dot Product (Should be slow but is fast) 
     inner_product=dotProduct(dictionary',r); %(Should be fast but is very slow) 
/****************************************************/ 
       [m,ind]=max(abs(inner_product)); 

       index=[index ind]; 
       atoms(:,ind)=dictionary(:,ind); %Select atom which has maximum inner product 
       dictionary(:,ind)=0; 
       at=atoms(:,index); 
       x=(at'*at)\(at'*r); 
       coefs(index)=x; 
       r=r-at*x; 
       t=norm(r); 
       count=count+1; 
      end 
       sparse(:,ii)=coefs; 

     end 

     sig=D*sparse; 
     final=uint8((repmat((((max(tem4))-min(tem4))./((max(sig)-min(sig)))),size(tem4,1),1).*(sig-repmat(min(sig),size(tem4,1),1)))+repmat(min(tem4),size(tem4,1),1)); 

     toc 

144 * 14596和144 * 1,但我现在面临的问题是,它需要大量的时间(如看到探查器报告)在MATLAB中使用以下代码找出点积。

inner_product = dictionary'* r;

为了减少计算时间,我写的MEX代码如下所示找出点积:

/*********************************************************************** 
*Program to create a MEX-file to find the dot product of matrices  * 
*Created by: Navdeep Singh           * 
*@Copyright Reserved             * 
***********************************************************************/ 

#include "mex.h" 

void dot_prod(double *m1,double *m2, double *t,size_t M,size_t N, size_t M2,size_t N2) 
{ 
    int i,j,k; 
    double s; 

    for(i=0;i<M;i++) 
    { for(k=0;k<N2;k++) 
     { s=0; 
      for(j=0;j<N;j++) 
      { s=s+*((m1+i)+(M*j))*(*(m2+(j+M2*k))); 
      } 
      *((t+i)+(M*k))=s; 
     } 
    } 
} 

void mexFunction(int nlhs,mxArray *plhs[],int nrhs, const mxArray *prhs[]) 
{ double *mat1,*mat2,*out; 
    size_t rows_mat1,cols_mat1,rows_mat2,cols_mat2; 
    mat1=mxGetPr(prhs[0]); 
    mat2=mxGetPr(prhs[1]); 
    rows_mat1=mxGetM(prhs[0]); 
    cols_mat1=mxGetN(prhs[0]); 
    rows_mat2=mxGetM(prhs[1]); 
    cols_mat2=mxGetN(prhs[1]); 
    plhs[0]=mxCreateDoubleMatrix(rows_mat1,cols_mat2,mxREAL); 
    out=mxGetPr(plhs[0]); 
    dot_prod(mat1,mat2,out,rows_mat1,cols_mat1,rows_mat2,cols_mat2); 

} 

但让我吃惊,我发现,MEX解决方案是非常非常慢而不是MATLAB中使用的那个,这打破了MEX的最终目的。要知道,因为我搜索互联网上的很多,发现了一些有趣的事实,如:

Matlab: Does calling the same mex function repeatedly from a loop incur too much overhead?

Matlab mex-file with mexCallMATLAB is almost 300 times slower than the corresponding m-file

这些链接显示,开销应该不会有太大,如果有一些它始终是第一次调用,因为需要时间加载符号表等。 - 但与此相反,我发现在我的代码中产生了很多开销。

另外我发现参数的大小并不重要,虽然参数的数量可以影响计算时间,但它又是最小的。其中一个链接也表明动态分配的内存应该被释放(除了由matlab本身分配的内存之外),但我也没有任何这种类型的分配。

所以,请让我知道什么是落后

之所以MEX走的时候大量?

什么可以解决它?

您的帮助真的很感激。

各种文件可以在这里找到:

dictionary.m

dotProduct.c

Report MEX

E.mat

R.mat

P.mat

+4

它几乎不可能为你写点产品比MATLAB的一个更快的代码。你说它的速度很慢,是因为单次通话很慢,还是因为你说了很多次,而且总数很大?此外,mex文件速度很快,但在创建和传递变量时可能会听到 –

+0

我认为您还没有完全阅读该文章,并且您的答案尚不清楚。 – Navdeep

+3

你应该专注于使你的MATLAB代码更快,而不是写MEX代码。 MATLAB中的矩阵乘法和点乘积要比你自己写这个要快得多。我可以在你的MATLAB代码中看到几个可以进行矢量化的点。 – rayryeng

回答

2

MATLAB具有高度优化的代码来计算的,以矩阵点积,

你只写了一个嵌套循环来计算点积,所以你可以只用“类似嵌套的比较这墨西哥码循环”在MATLAB再决定MEX代码是否更快或MATLAB,

其实MATLAB不使用嵌套的for循环来计算矩阵的点积,

从MATLAB DOC:

MEX-文件有几个应用程序:

  • 调用大型预存从MATLAB C/C++和Fortran程序,而无需重写他们作为MATLAB功能

  • 用C代替性能关键的程序/ C++实现

MEX文件不适合所有应用程序。 MATLAB是一个高生产率的环境,其专长是消除像C或C++这样的编译语言中耗时,低级的编程。一般来说,在MATLAB中进行编程。除非您的应用程序需要,否则不要使用MEX文件。

EXAMPLE1

+0

谢谢。你能告诉我们在哪里可以使用MEX。我现在非常困惑。 – Navdeep

+0

@Navdeep你可以使用MEX文件为循环耗费大量时间,但是在像矩阵乘法那样的情况下matlab足够快(因为它的优化算法) –