2014-01-28 23 views
0

我試圖使用(並從中學習)Mark Harris's optimized reduction kernel,通過將其源代碼複製到一個簡單的pycuda應用程序中下面列出了我的嘗試的來源)。PyCUDA無法在NVIDIA源代碼中找到函數或拋出「可能沒有外部」C「Linkage」錯誤

不幸的是,我遇到了以下兩個錯誤之一。

  1. 的CUDA內核不能編譯,拋出以下錯誤消息。

    kernel.cu(3): error: this declaration may not have extern "C" linkage 
    
  2. 如果包括我的論點no_extern_c=True成編譯內核行,以下引發錯誤:

    pycuda._driver.LogicError: cuModuleGetFunction failed: not found 
    

我自己也嘗試包裝modStr的內容extern "C" { [...] }與將no_extern_c變量設置爲True或False,但沒有任何成功。

問題看起來好像我評論的函數體出它仍然引起錯誤涉及線路template <unsigned int blockSize>。但是我對這個問題的理解不夠深入,無法解決問題。

任何意見/建議/幫助將非常感謝 - 提前致謝!

from pylab import * 

import pycuda.gpuarray as gpuarray 
import pycuda.autoinit 
import pycuda.driver as drv 
from pycuda.compiler import SourceModule 

modStr = """ 
template <unsigned int blockSize> 
__global__ void reduce6(int *g_idata, int *g_odata, unsigned int n) { 
    extern __shared__ int sdata[]; 
    unsigned int tid = threadIdx.x; 
    unsigned int i = blockIdx.x*(blockSize*2) + tid; 
    unsigned int gridSize = blockSize*2*gridDim.x; 
    sdata[tid] = 0; 
    while (i < n) { 
     sdata[tid] += g_idata[i] + g_idata[i+blockSize]; i += gridSize; 
    } 
    __syncthreads(); 
    if (blockSize >= 512) { if (tid < 256) { sdata[tid] += sdata[tid + 256]; } __syncthreads(); } 
    if (blockSize >= 256) { if (tid < 128) { sdata[tid] += sdata[tid + 128]; } __syncthreads(); } 
    if (blockSize >= 128) { if (tid < 64) { sdata[tid] += sdata[tid + 64]; } __syncthreads(); } 
    if (tid < 32) { 
     if (blockSize >= 64) sdata[tid] += sdata[tid + 32]; 
     if (blockSize >= 32) sdata[tid] += sdata[tid + 16]; 
     if (blockSize >= 16) sdata[tid] += sdata[tid + 8]; 
     if (blockSize >= 8) sdata[tid] += sdata[tid + 4]; 
     if (blockSize >= 4) sdata[tid] += sdata[tid + 2]; 
     if (blockSize >= 2) sdata[tid] += sdata[tid + 1]; 
    } 
    if (tid == 0) g_odata[blockIdx.x] = sdata[0]; 
} 
""" 

mod = SourceModule(modStr,no_extern_c=True) 
# With no_extern_c = True, the error is : 
# pycuda._driver.LogicError: cuModuleGetFunction failed: not found 
# With no_extern_c = False, the error is : 
# kernel.cu(3): error: this declaration may not have extern "C" linkage 


cuda_reduce_fn = mod.get_function("reduce6") 
iData = arange(32).astype(np.float32) 
oData = zeros_like(iData) 

cuda_reduce_fn(
    drv.In(iData), 
    drv.Out(oData), 
    np.int32(32), 
    block=(32,1,1), grid=(1,1)) 

print(iData) 
print(oData) 

回答

1

這是非法的模板,在C++中,這就是爲什麼你在第一種情況下得到的錯誤C鏈接功能。

在第二種情況下,你會得到一個未找到錯誤,因爲你沒有實際實例化模板的任何地方,我可以看到,所以編譯器將不會發出任何輸出。

當你添加一個實例,你會得到同樣的錯誤,因爲該設備的編譯代碼對象有一個mangled name。您需要在撥打電話get_function時使用錯位的名稱。矛盾的是,你可以不知道什麼時候JIT編譯源碼錯位的名字,因爲你需要查看編譯器的輸出,因此不知道先驗(任何編譯器的消息,PTX,的cubin或目標文件會給你重整名稱)。

如果你想在PyCUDA中使用模板化的內核,我建議用工具鏈將它們編譯爲cubin,然後從PyCUDA中的cubin加載,從模塊中獲取已知的mangled名稱。

相關問題