2011-10-03 58 views
4

我有一個調用在一個.CU文件中定義這樣CUDA和模板:需要專業化聲明?

template<typename T, class M> 
__global__ void compute_kernel(T* input, T* output, n) { 
    M m; 
    // compute stuff using m 
}; 

template<typename T, class M> 
void compute(T* input, T* output, int n) { 
    // ... compute blocks, threads, etc. 
    compute_kernel<T,M> <<<dim_grid, dim_block>>>(input, output, n); 
    // ... 
}; 

和一個頭文件是內核(__global__)將被包括在主機代碼模板化包裝函數僅具有聲明

template<typename T, class M> 
void compute(T* input, T* output, int n); 

但是,從具有任意模板參數的主機調用compute()時,編譯失敗,並且undefined reference to 'void reduce(...)'並且僅當我在代碼編譯時向.cu文件的末尾添加專門化聲明:

template void 
compute<int, Method1<int> >(int* input, int* output, int n); 

template void 
compute<float, Method1<float> >(float* input, float* output, int n); 

template void 
compute<int, Method2<int> >(int* input, int* output, int n); 

template void 
compute<float, Method2<float> >(float* input, float* output, int n); 

那麼,是否有必要專門化每個模板化的函數以使其可以從主機調用? (這是一個很大的缺點)

感謝您的意見!

+2

與任何模板一樣,您必須確保整個模板定義在每個*實例化站點都可見(除非您故意提供明確的實例化)。 –

+0

@KerrekSB:我認爲你是對的,這是問題所在。但是,要分離主機和設備代碼(以及編譯),似乎無法將整個模板定義無處不在... – bbtrb

+0

我不確定問題出在哪裏。 CUDA編譯器不會自動分離這兩個代碼路徑嗎?所以,只需使用函數模板的模板定義創建一個普通的頭文件,並將其包含到任何地方 - 阻塞是什麼? –

回答

1

這是一個C++ FAQ,不限於CUDA。

如果您在.cpp或.cu文件中有模板實現,那麼當您編譯該翻譯單元時,編譯器不可能知道您將需要的模板參數的排列方式。因此,當你鏈接你會得到錯誤。

您可以將實現放在頭文件中(在這種情況下,您需要在.cu文件中實例化,因爲它包含CUDA),否則您將不得不顯式實例化所有需要的排列。如果你必須做很多這些,那麼你可以使用宏來實例化所有的排列。

+0

謝謝,這回答它。我從來沒有真正想過模板的非內聯實現,並始終將它們保存在標題中。所以,只要我只從* .cu文件中調用模板函數,我就可以在任何地方包含完整的定義,並且不需要顯式實例化。這已經非常有幫助,因爲(最終)只有我的單元測試會從宿主代碼中調用這些函數。 – bbtrb

+0

@Tom在CUDA中使用表達式模板怎麼樣?我已在此鏈接發佈了一個問題(http://stackoverflow.com/questions/15628470/unresolved-externals-in-cuda-expression-template-library-under-visual-studio-201),但我沒有收到回答。對於表達式模板,似乎不可能實例化所有可能的排列。你能爲此提出一個解決方案嗎? – JackOLantern