2013-11-25 52 views
0

我有一個CUDA應用程序,它目前使用推力庫來完成GPU上矢量的總和和最大減少量。我發現對於某些向量長度來說,如果將向量發送回主機並計算C++中的總和和最大減少量,速度會更快。gcc-via-nvcc矢量化這些總和最大減少量嗎?

總和和最大減少量應在主機上進行矢量化。主機上的內存是線性/連續的,我使用的編譯器(GCC)支持它。鑑於我所看到的時機,似乎編譯器正在向量化代碼,但我如何確認?我沒有任何強制編譯器優化的經驗,但我知道有一些可以使用的編譯指示語句。 (雖然你會發現通過使用google搜索很少的信息。)另外,我寧願不去挖掘組裝來確認,因爲我不會理解它。是否有編譯器設置(在GCC或NVCC中),我可以用它來強制向主機上的矢量化或找到代碼被矢量化的確認?

我爲sum和max裁減編寫的函數如下。 nvcc編譯器最終編譯它,因爲函數包含CUDA代碼。

void calc_vector_max_host(double& maxval, double *const vec_h, const double *const vec_d, int len) 
{ 
    //copy device vector to host 
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost)); 

    //vectorized? max 
    maxval = *vec_h; 
    double* temp = vec_h; 
    for(int i = 1; i < len; i++, temp++) 
    { 
     if(*temp > maxval) 
     { 
      maxval = *temp; 
     } 
    } 
} 

void calc_vector_sum_host(double& sum, double *const vec_h, const double *const vec_d, int len) 
{ 
    //copy device vector to host 
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost)); 

    //vectorized? sum 
    sum = 0.0; 
    double* temp = vec_h; 
    for(int i = 0; i < len; i++, temp++) 
    { 
     sum += *temp; 
    } 
} 

編輯:以下包含gcc自動矢量化所需的更正。註釋中列出的編譯器選項也是需要的。

void calc_vector_max_host(double& maxval, double *const __restrict__ vec_h, const double *const __restrict__ vec_d, int len) 
{ 
    //copy device vector to host 
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost)); 

    //vectorized? max 
    double local_maxval = vec_h[0]; 
    for(int i = 1; i < len; i++) 
    { 
     double val = vec_h[i]; 
     if(val > local_maxval) 
     { 
      local_maxval = val; 
     } 
    } 
    maxval = local_maxval; 
} 

void calc_vector_sum_host(double& sum, double *const __restrict__ vec_h, const double *const vec_d, int len) 
{ 
    //copy device vector to host 
    gpuErrchk(cudaMemcpy(vec_h, vec_d, len*sizeof(double), cudaMemcpyDeviceToHost)); 

    //vectorized? sum 
    double local_sum = 0.0; 
    for(int i = 0; i < len; i++) 
    { 
     local_sum += vec_h[i]; 
    } 
    sum = local_sum; 
} 

回答

2

第一個也是最重要的一點是,nvcc不是編譯器。它是一個編譯器驅動程序 - 它只是將主編譯器與幾個自定義預處理工具組合起來進行編譯,這些工具將實際的GPU代碼分離出來並傳遞給GPU工具鏈。 GPU編譯器和彙編程序只會觸及一小部分典型程序。構建的其餘部分直接與主機編譯器和鏈接器完成。

所以你發佈的所有代碼都是由gcc編譯的(並且可以在不使用nvcc的情況下直接編譯)。 nvcc有一個選項-Xcompiler,它可以用來將你想要的任何選項傳遞給主機編譯軌跡。對於矢量化,你可以通過你所描述的gcc支持的任何選項here。你也可以直接使用SSE風格的內在函數來讓編譯器的工作更容易,如果你是這樣傾向的

要查看vectorisation是否已經在你的主機代碼中發生,只需使用類似objdump/otool的東西(取決於你是否使用Linux或OS X,你沒有說過)。您將能夠查看編譯器發出的代碼的反彙編,並且向量化指令的存在將立即回答您的問題。

最後,nvcc現在還不錯,documentation,你可以通過熟悉這個問題找到答案,可能還有其他關於nvcc的其他問題。

+0

有幾條評論,僅供參考。到gcc選項網頁的鏈接很有幫助。最初發布的代碼畢竟不是自動矢量化的。這是由於一些缺少的編譯器選項。具體來說,我必須使用-Xcompiler標誌來傳遞所有-ftree-vectorize -msse2和-ffast-math以獲取向量化代碼以及ftree-vectorize-verbose = 6以獲取自動向量化編譯器輸出。我使用Linux並嘗試使用objdump,但未發現程序集轉儲對此問題非常有用。這些功能還有一些問題已經被編輯。 –