2017-03-16 144 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足夠快(因爲它的優化算法) –