2011-06-14 47 views
7

時,我一直在試圖創建模板的內核,但我已經遇到了一些麻煩稱他們在我的計劃。我有一個Matrix<T>模板類,和裏面定義的一些方法問題調用模板CUDA內核

Matrix.h:

template <typename T> class Matrix { 
    ... 
    void sum(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum); 
    ... 
} 

#include "Matrix.cu" 

Matrix.cu:

#include "MatrixKernel.h" 

template<typename T> void Matrix<T>::sum(const Matrix<T>& m, Matrix<T>& sum) { 
    ... 
    sumKernel<T><<<dimGrid, dimBlock>>>(Matrix<T> m1, Matrix<T> m2, Matrix<T> sum) 
    ... 
} 

MatrixKernel.h:

template<typename T> __global__ void sumKernel(const Matrix<T> m1, const Matrix<T> m2, Matrix<T> sum) { 
... 
} 

問題是,當我從sum中調用sumKernel時,編譯器給了我下面的錯誤:

error C2059: syntax error : '<' 

有人知道發生了什麼嗎?在包含sumKernel調用之前,代碼就可以正常編譯了。

謝謝。

+0

我不知道你可以使用CUDA和C++(!)。瑣碎的建議:嘗試在''和'<<<'之間放置一個空格,以防將它們放在一起導致解析問題。 – Rup 2011-06-14 10:43:33

+0

編譯器是否告訴你哪一行出錯?在cuda模板代碼中有很多 2011-06-14 10:45:34

+0

@Rup:是的,你可以。您甚至可以將對象作爲參數傳遞給內核(只要您將感興趣的數據複製到設備內存)。我也會嘗試你的建議。 @Bomadeno:錯誤在執行內核調用的線上。 – Renan 2011-06-14 15:42:24

回答

6

所以,看來你確實有一個奇怪的#include,導致代碼過得去錯誤編譯器編譯。通過爲cuda頭文件使用.cu.h來區分gpu頭文件和cpu頭文件。確保只有 NVCC編譯.cu.cu.h文件。 Cuda文件不應該包含在cpp文件中。內核和內核調用應該在.cu.cu.h文件,這些文件不應該在任何地方CPPS包括。

由於您的.cu正在包含在由主機編譯器編譯的頭文件中,主編譯器最終會碰到令牌<<< - 它無法識別。它可能確實理解了令牌<<,因此它會消耗此功能,從而產生意外的<

這裏做的事情應該工作的另一種方式(沒有嘗試過,但它類似於我們使用的代碼)

(注意,這可能會奏效,但它也可能不是解決問題的正確方法。我的老闆不喜歡它作爲解決方案,並且傾向於爲每個變體添加實現)

底層問題似乎是主機和設備代碼之間缺乏區別。我要離開的細節,並且在我的解決方案 - 比如複製結果,並從設備,和實施等

我試圖解決的是,給定一個結構的問題,你怎麼能模板它在主機和設備上都使用?

我會在這兩個類型和實現細節模板Matrix.h

template <typename T, typename Implementation<T> > class Matrix { 
    void sum(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum) 
    { 
     Implementation.sumImp(m1, m2, sum); 
    } 
} 

主機實現,HostMatrixSum.h會做的事情上的CPU:

#include "Matrix.h" 

template <typename T> struct HostMatrixSum 
{ 
    void sumImp(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum) 
    { 
     ... 
    } 
} 

雖然GpuMatrixSum.cu.h將上傳矩陣,做之和恢復的結果:

#include "Matrix.h" 

template <typename T> struct GpuMatrixSum 
{ 
    template<typename T> __global__ void sumKernel(const Matrix<T> m1, const Matrix<T> m2, Matrix<T> sum) 
    { 
     ... 
    } 

    void sumImp(Matrix<T>& m1, Matrix<T>& m2, Matrix<T>& sum) 
    { 
     ... 
     sumKernel<T> <<< dimGrid, dimBlock >>> (m1,m2); 
     ... 
    } 
} 

然後當我們從主機代碼中使用Matrix時,我們在主機總和實現上進行模板化,並且從不需要查看任何cuda細節:

#include "Matrix.h" 
#include "HostMatrixSum.h" 

Matrix<int, HostMatrixSum> m1 = Matrix<int>(...); 
Matrix<int, HostMatrixSum> m2 = Matrix<int>(...); 
Matrix<int, HostMatrixSum> result; 
Matrix.sum(m1,m2,result); 

如果我們在GPU上的合作,我們可以使用GPU加速實施總和:

#include "Matrix.h" 
#include "GpuMatrixSum.cu.h" 

Matrix<int, GpuMatrixSum> m1 = Matrix<int>(...); 
Matrix<int, GpuMatrixSum> m2 = Matrix<int>(...); 
Matrix<int, GpuMatrixSum> result; 
Matrix.sum(m1,m2,result); 

希望對你有用!

+0

我要試一試。但同時在MatrixKernel.h中,例如編譯器不會抱怨__global__關鍵字(它只能表示NVCC正在編譯它,對吧?) 另一件事:如果你說實話是問題,我會在哪裏實施總和方法?如果我沒有在「Matrix.h」中寫入'#include'Matrix.cu「',將會出現鏈接錯誤,因爲模板必須在同一個文件中聲明和定義... – Renan 2011-06-14 15:53:09

+0

我認爲你是對的,我不得不忘記將Matrix作爲模板類來實現,因爲我無法以這種方式實現它。如果我在頭文件中包含一個.cu文件,那麼包含Matrix頭文件的其他所有文件都將包含.cu,甚至是.cpp文件,這將不可避免地導致編譯錯誤。使用模板內核是可以的,但是由於我剛剛解釋的內容,使得稱爲模板的C++方法也不可行。畢竟它有點纏繞...... – Renan 2011-06-15 06:53:49

+0

因爲MatrixKernel.h只包含在一個cu文件中,所以只有nvcc才包含它。如果您將MatrixKernel.h包含在主機cpp文件中,我懷疑它會崩潰。我將cuda命名爲特定頭文件.cu.h,以澄清它僅適用於.cu文件。我正在回答'如何去做'問題的一部分 - 試圖找出一個優雅的解決方案:) – 2011-06-15 10:16:40