cudaMemset在__device__变量上失败

时间:2012-04-03 15:31:38

标签: cuda

我在设备变量上使用cudaMemset时遇到问题。是否可以使用cudaMemset的设备变量的引用,或者只是缺少编译器标志或库..我正在使用cuda 4.1和

  

NVRM版本:NVIDIA UNIX x86_64内核模块285.05.33 1月19日星期四   太平洋标准时间2012年14:07:02

这是我的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

// device variable and kernel
__device__ float d_test;

int main() {

  if (cudaMemset(&d_test,0,sizeof(float)) !=cudaSuccess)
        printf("Error!\n");
}

输出:

Error!

2 个答案:

答案 0 :(得分:5)

您的问题是d_test(因为它出现在主机符号表中)不是有效的设备地址,运行时无法直接访问它。解决方案是使用cudaGetSymbolAddress API函数在运行时从上下文中读取设备符号的地址。以下是您的演示案例的略微扩展版本,它应该可以正常工作:

#include <stdio.h>
#include <stdlib.h>
#include <cuda_runtime.h>

// device variable and kernel
__device__ float d_test;

inline void gpuAssert(cudaError_t code, 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);
    }       
}

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }

int main()
{

    float * _d_test;

    gpuErrchk( cudaFree(0) );
    gpuErrchk( cudaGetSymbolAddress((void **)&_d_test, "d_test") );
    gpuErrchk( cudaMemset(_d_test,0,sizeof(float)) );

    gpuErrchk( cudaThreadExit() );

    return 0;
}

在这里,我们从上下文中读取设备符号d_test的地址到主机指针_d_test。然后,可以将其传递给主机端API函数,如cudaMemsetcudaMemcpy


编辑注意,此答案中显示的cudaGetSymbolAddress形式已被弃用,并已从CUDA运行时API中删除。对于现代CUDA,呼叫将是:

gpuErrchk( cudaGetSymbolAddress((void **)&_d_test, d_test) );

答案 1 :(得分:0)

我相信你也可以使用cudaMemcpyFromSymbol: 函数(例如以下内核)可以更改在全局内存中声明的变量的值(在main函数之外)

__global__ void kernel1() { d_test = 1.0; }

在main中,您可以使用cudaMemcpyFromSymbol

获取值
cudaMemcpyFromSymbol(&h_test,"d_test",sizeof(float),0,cudaMemcpyDeviceToHost);

当然,还有cudaMemcpyToSymbol来改变全局变量的值。

这个想法来自这里:Having problem assigning a device variable in CUDA