【问题标题】:CUDA constant memory issue: invalid device symbol with cudaGetSymbolAddressCUDA 常量内存问题:使用 cudaGetSymbolAddress 的设备符号无效
【发布时间】:2014-11-04 13:01:33
【问题描述】:

我正在尝试在启动需要这些值的内核之前在我的 GPU 的常量内存上设置常量值。

我的代码(简化):

__constant__ size_t con_N;

int main() 
{

    size_t N;
    size_t* dev_N = NULL;
    cudaError_t cudaStatus;

    //[...]

    cudaStatus = cudaGetSymbolAddress((void **)&dev_N, &con_N);
    if (cudaStatus != cudaSuccess) {
        cout<<"cudaGetSymbolAddress (dev_N) failed: "<<cudaGetErrorString(cudaStatus)<<endl;
    }

我打算之后cudaMemcpy我的Ndev_N

但是,此时我在代码中得到的只是:

cudaGetSymbolAddress (dev_N) failed: invalid device symbol

我正在使用 CUDA 6.5,所以这不是引用符号问题,因为它是我迄今为止检查的大部分问答中的问题。

我尝试用con_N[1] 替换con_N(并在cudaGetSymbolAddress 参数中删除con_N 之前的&amp;):结果相同。

由于这个函数的原型是cudaGetSymbolAddress(void **devPtr , const void* symbol ),我猜它想得到我的符号地址。但是,我尝试使用 cudaStatus = cudaGetSymbolAddress((void **)&amp;dev_N, (const void*) con_N); 并收到相同的消息。

当我删除 cudaGetSymbolAddress((void **)&amp;dev_N, &amp;con_N) 并直接使用 cudaMemcpyToSymbol(&amp;con_N, &amp;N, sizeof(size_t)) 时,我也会收到相同的错误消息。

恐怕我错过了一些重要的事情。任何帮助将不胜感激。

【问题讨论】:

    标签: memory-management cuda


    【解决方案1】:

    cudaGetSymbolAddress的正确用法是

    cudaGetSymbolAddress((void **)&dev_N, con_N)
    

    我将通过下面的简单示例来展示这一点。

    如文档所述,该符号应实际驻留在设备上。因此,在 API 调用中使用 &amp;con_N 似乎毫无意义,因为作为主机 API 的 cudaGetSymbolAddress,直接从主机访问驻留在设备上的某物的地址应该是不可能的。我不确定出现在 CUDA Runtime API 文档中的原型是否应该更好地阅读为 `

    template<class T>
    cudaError_t cudaGetSymbolAddress (void **devPtr, const T symbol)
    

    设备符号引用代替设备符号地址

    #include <stdio.h>
    
    __constant__ int const_symbol;
    
    /********************/
    /* CUDA ERROR CHECK */
    /********************/
    #define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
    inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true)
    {
       if (code != cudaSuccess) 
       {
          fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
          if (abort) exit(code);
       }
    }
    
    /***************/
    /* TEST KERNEL */
    /***************/
    __global__ void kernel() {
    
        printf("Address of symbol from device = %p\n", &const_symbol);
    
    }
    
    /********/
    /* MAIN */
    /********/
    int main() 
    {
        const int N = 16;
        int *pointer = NULL;
    
        gpuErrchk(cudaGetSymbolAddress((void**)&pointer, const_symbol));
    
        kernel<<<1,1>>>();
    
        printf("Address of symbol from host = %p\n", pointer);
    
        return 0;
    }
    

    【讨论】:

    • 谢谢,这完全有道理。我必须补充一点,我无法编译 cudaGetSymbolAddress((void **)&amp;dev_N, con_N) ,但这只是因为我正在谈论的所有代码都在 .cpp 文件而不是 .cu 文件中。包装我的电话解决了我的编译问题(感谢这个主题:stackoverflow.com/questions/20535683/…
    【解决方案2】:

    在我看来,你的一行代码应该像下面这样固定。

    cudaStatus = cudaGetSymbolAddress((void **)&dev_N, con_N);
    

    希望对你有所帮助。

    【讨论】:

    • 感谢您的回答!这个函数的原型是 cudaGetSymbolAddress(void * * devPtr , const void* symbol ) 所以我想它想得到我的符号地址。但是,我尝试了这个(我必须将 con_N 转换为 const void*),但我仍然遇到相同的错误消息。
    • 您不应将 con_N 转换为 const void*。这是错误的原因。此外,您不需要遵循处理 cudaGetSymbolAddress、cudaMemcpyToSymbol 等符号的函数的原型,因为它们可能会根据 cuda 环境而有所不同。
    • @Wang_Wang:好的,谢谢你的提示。但是,如果没有这个演员表,我的 IDE 就无法编译......(否则我会很高兴没有它)
    • @eyam,第一个给你答案的人是我。对了,你为什么不提名我?
    • @Wang_Wang,JackO 的回答提供了更多的细节和解释,因此我认为它与寻找答案的人更相关。不过,我很感谢您的回答(如果我有足够的声誉,请确保我也会投票支持它)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    相关资源
    最近更新 更多