【问题标题】:Invalid Argument in cudaMemcpycudaMemcpy 中的参数无效
【发布时间】:2015-02-12 16:53:30
【问题描述】:

我在追踪 cudaMemcpy 调用的无效参数的来源时遇到了问题,以下是相关代码:

在 gpu_memory.cu 中,我为设备指针声明并分配内存:

#define cudaErrorCheck(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);
    }
}
...
__device__ double* conc;
...
__global__ void pointer_set_kernel(..., double* conc_in...) {
...
   conc = conc_in;
...
}

double* d_conc;
...
//memory initialization
void initialize_gpu_memory(int NUM, int block_size, int grid_size) {
    ...
    cudaErrorCheck(cudaMalloc((void**)&d_conc, NUM * 53 * sizeof(double)));
    ...
    pointer_set_kernel<<<1, 1>>>(...d_conc...);
    cudaErrorCheck( cudaPeekAtLastError() ); // Checks for launch error
    cudaErrorCheck( cudaThreadSynchronize() ); // Checks for execution error
}

接下来在另一个文件 (mechanism.cu) 中,我将设备指针声明为外部数据以将数据复制到它:

extern __device__ double* conc;
void write_jacobian_and_rates_output(int NUM, int block_size, int grid_size) {
    ...
    initialize_gpu_memory(NUM, block_size, grid_size);
    ...
    //get address of conc
    double* d_conc;
    cudaErrorCheck(cudaGetSymbolAddress((void **)&d_conc, conc));
    //populate the concentrations on the host
    double conc_host[NSP];
    double* conc_host_full = (double*)malloc(NUM * NSP * sizeof(double));
    //populate the concentrations
    get_concentrations(1.01325e6, y_host, conc_host);
    for (int i = 0; i < NUM; ++i) {
        for (int j = 0; j < NSP; ++j) {
           conc_host_full[i + j * NUM] = conc_host[j];
        }
    }
    //check for errors, and copy over
    cudaErrorCheck( cudaPeekAtLastError() ); // Checks for launch error
    cudaErrorCheck( cudaThreadSynchronize() ); // Checks for execution error
    cudaErrorCheck(cudaMemcpy(d_conc, conc_host_full, NUM * 53 * sizeof(double), cudaMemcpyHostToDevice));
    ...
}

我在最后一行(Memcpy)上得到了错误。看来initialize_gpu_memory函数工作正常,这是malloc和pointer_set_kernel之后的cuda-gdb检查:

p d_conc 
$1 = (double *) 0x1b03236000
p conc
$2 = (@generic double * @global) 0x1b03236000

在 write_jacobian_and_rates 函数中:

p d_conc
$3 = (double *) 0x1b02e20600
p conc
$4 = (@generic double * @global) 0x1b03236000

我不知道为什么写函数中的 d_conc 在 cudaGetSymbolAddress 调用之后指向不同的内存位置,或者为什么我在 memcpy 上得到一个无效的参数。我确定我在做一些愚蠢的事情,但对于我的生活,我看不到它。非常感谢您帮助追踪其来源,谢谢!

【问题讨论】:

    标签: c cuda


    【解决方案1】:

    在您的代码 sn-p 中没有任何内容表明您具有 d_concextern 范围,因此,d_conc 的两个实例在两个不同的文件中是完全不同的对象。所以,
    在这种情况下:(mechanism.cu)

    double* d_conc;  //you create a new variable in this context
    cudaErrorCheck(cudaGetSymbolAddress((void **)&d_conc, conc));
    //populate the concentrations on the host
    double conc_host[NSP];
    double* conc_host_full = (double*)malloc(NUM * NSP * sizeof(double));  
    

    没有分配内存d_conc

    我看到你已经在gpu_memory.cu 的上下文中分配了内存,因为它是同名的变量,但不是在发生错误的地方。

    这似乎也解决了您的问题:我不知道为什么写函数中的 d_conc 在 cudaGetSymbolAddress 调用之后指向不同的内存位置

    【讨论】:

    • 好的,为 d_conc 做 extern 解决了这个问题。但是,我想我不清楚 cudaGetSymbolAddress 的意义是什么?我想我可以使用它来获取 extern _device_ double* conc 的地址,并以这种方式将其复制到它,而不是让 d_conc 指针被外部化。我想这样做与我尝试过的方式无关,我只是好奇
    • @arghdos - 在一组文件中提供一个变量 extern 范围就足以访问和更改同一个变量(其中范围内)。在您的代码示例中,您有两个完全不同的变量,它们只共享相同的符号名称 - d_conc。 (见下一条评论)
    • 一旦将该变量的单个实例带入extern 范围,就可以正确使用cudaGetSymbolAddress。下面是 an example 说明使用 cudaGetSymbolAddress 提供优势的原因。您做对了几件事,只是错过了 extern 范围的事情。
    猜你喜欢
    • 2011-08-02
    • 1970-01-01
    • 2021-10-09
    • 2017-03-28
    • 2021-01-25
    • 2014-07-06
    • 2016-07-07
    相关资源
    最近更新 更多