从CUDA内核访问全局内存指针

时间:2014-05-31 14:00:22

标签: c++ cuda

我正在尝试分配设备内存并将指针存储为全局变量。但是,当我尝试从内核访问内存时,我从cudaDeviceSynchronize()收到此错误: cudaErrorIllegalAddress 。我检查了从cudaMalloc和cudaMemcpy返回的cudaStatus代码,它们都是成功的。

我希望以下示例能够直截了当地展示我想要做的事情。基本上,我有一大堆样本数据,我希望所有内核都能够读取,但我不想每次都将指针传递给内核调用。

我正在使用Windows 8 x64,使用Visual Studio 2012和nvcc(通过VS集成)编译代码。目标是x64 Debug可执行文件。我的设备是GTX 780。

#include "cuda_runtime.h"
#include <stdio.h>
#define SIZE (1024 * 1024 * 10)

__device__ int* cData;

void Init()
{
    int* data = new int[SIZE];
    cudaError_t cudaStatus;
    cudaStatus = cudaMalloc(&cData, SIZE * sizeof(int));
    for (int i = 0; i < SIZE; i++)
        data[i] = i;

    cudaStatus = cudaMemcpy(cData, data, SIZE * sizeof(int), cudaMemcpyHostToDevice);
    delete data;
}

__global__ void kernel(int i, int* output)
{
    *output = cData[i];
}

int main()
{
    cudaError_t cudaStatus = cudaSetDevice(0);
    cudaDeviceProp properties;
    int* result;
    cudaStatus = cudaMallocManaged(&result, sizeof(int));
    Init();

    kernel<<<1, 1>>>(1000, result); // invoke a single thread, expecting the value of *result to be 1000 afterwards
    cudaStatus = cudaGetLastError();
    cudaStatus = cudaDeviceSynchronize(); // returns cudaErrorIllegalAddress

    printf("Value is: %d", *result); // crashes the program, "In page error reading location 0x0000000D00000000"
    cudaFree(result);
    cudaStatus = cudaDeviceReset();
    return 0;
}

1 个答案:

答案 0 :(得分:5)

我们不会在cudaMalloc变量上使用cudaMemcpy__device__

阅读__device__ cudaMemcpyToSymbol(); cudaMemcpyFromSymbol(); 变量,其中列出了要使用的API调用:

cudaMalloc

如果要在动态分配的设备数组上使用__device__,但将返回的指针存储在void Init() { int* data = new int[SIZE]; int* d_data; cudaError_t cudaStatus; cudaStatus = cudaMalloc(&d_data, SIZE * sizeof(int)); for (int i = 0; i < SIZE; i++) data[i] = i; cudaStatus = cudaMemcpy(d_data, data, SIZE * sizeof(int), cudaMemcpyHostToDevice); cudaMemcpyToSymbol(cData, &d_data, sizeof(int *)); delete data; } 变量中,则必须执行以下操作:

nvcc

当我按原样编译代码时,我从CUDA 6 t411.cu(15): warning: a __device__ variable "cData" cannot be directly read in a host function 收到以下编译器警告:

SIZE

不应忽视这些警告。

如果在编译时知道__device__ int cData[SIZE]; void Init() { int* data = new int[SIZE]; cudaError_t cudaStatus; for (int i = 0; i < SIZE; i++) data[i] = i; cudaStatus = cudaMemcpyToSymbol(cData, data, SIZE * sizeof(int)); delete data; } ,就像在你的例子中那样,你也可以这样做:

{{1}}