2012-02-26 86 views
6

我有使用常量內存的設備/主機功能。它在設備上運行正常,但在主機上,似乎此內存仍未初始化。CUDA主機和使用相同的設備__constant__內存

#include <iostream> 
#include <stdio.h> 


const __constant__ double vals[2] = { 0.0, 1000.0 }; 

__device__ __host__ double f(size_t i) 
{ 
    return vals[i]; 
} 

__global__ void kern() 
{ 
    printf("vals[%d] = %lf\n", threadIdx.x, vals[threadIdx.x]); 
} 

int main() { 
    std::cerr << f(0) << " " << f(1) << std::endl; 
    kern<<<1, 2>>>(); 
    cudaThreadSynchronize(); 
} 

此打印(需要CC 2.0或以上)

0 0 
vals[0] = 0.000000 
vals[1] = 1000.000000 

這是什麼問題,我怎樣才能得到這兩個設備和主機內存常數初始化同步?

回答

11

由於CygnusX1誤解了我對MurphEngineer的回答的評論意思,也許我應該發表自己的回答。我意思是這樣的:

__constant__ double dc_vals[2] = { 0.0, 1000.0 }; 
     const double hc_vals[2] = { 0.0, 1000.0 }; 

__device__ __host__ double f(size_t i) 
{ 
#ifdef __CUDA_ARCH__ 
    return dc_vals[i]; 
#else 
    return hc_vals[i]; 
#endif 
} 

這有相同的結果天鵝,但它是在真正的代碼的臉更靈活:它可以讓你在不斷陣列具有運行時定義的值,例如,並允許您在__constant__陣列上使用CUDA API函數,如cudaMemcpyToSymbol/cudsaMemcpyFromSymbol

一個更現實的完整的例子:

#include <iostream> 
#include <stdio.h> 

__constant__ double dc_vals[2]; 
     const double hc_vals[2]; 

__device__ __host__ double f(size_t i) 
{ 
#ifdef __CUDA_ARCH__ 
    return dc_vals[i]; 
#else 
    return hc_vals[i]; 
#endif 
} 

__global__ void kern() 
{ 
    printf("vals[%d] = %lf\n", threadIdx.x, vals[threadIdx.x]); 
} 

int main() { 
    hc_vals[0] = 0.0; 
    hc_vals[1] = 1000.0; 

    cudaMemcpyToSymbol(dc_vals, hc_vals, 2 * sizeof(double), 0, cudaMemcpyHostToDevice); 

    std::cerr << f(0) << " " << f(1) << std::endl; 
    kern<<<1, 2>>>(); 
    cudaThreadSynchronize(); 
} 
+0

我自己找到了解決方案,並且完全匹配您的解決方案。謝謝! – davinchi 2012-02-28 15:40:20

+0

是的,這是更強大,我同意。但它也是更多類型;) – CygnusX1 2012-02-28 16:28:21

4

使用__constant__限定符顯式分配設備上的內存。無法從主機訪問該內存,即使使用新的CUDA Unified Addressing(僅適用於分配給cudaMalloc()及其朋友的內存)。用const限定變量只是說「這是一個指向(...)」的常量指針。

正確的做法是確實有兩個陣列:一個在主機上,另一個在設備上。初始化您的主機陣列,然後使用cudaMemcpyToSymbol()在運行時將數據複製到設備陣列。有關如何做到這一點的詳細信息,請參閱本主題:http://forums.nvidia.com/index.php?showtopic=69724

+4

這個答案是幾乎沒有...但@davinchi希望有一臺主機/設備功能使用他的常數表。爲此,他應該使用'#ifdef __CUDA_ARCH__'並在其中訪問__costant__數組,並在'#else'中訪問該數組的主機副本。 – harrism 2012-02-27 01:24:33

2

我覺得MurphEngineer很好地解釋爲什麼不起作用。

要迅速解決這個問題,你可以按照harrism的想法,這樣的事情:

#ifdef __CUDA_ARCH__ 
#define CONSTANT __constant__ 
#else 
#define CONSTANT 
#endif 

const CONSTANT double vals[2] = { 0.0, 1000.0 }; 

這樣主機編譯將創建一個普通的主機常量數組,而設備編譯將創建一個設備__constant__彙編。

請注意,如果您決定這樣做,使用CUDA API訪問具有像cudaMemcpyToSymbol()等功能的設備陣列可能會更困難。

相關問題