![](/img/trans.png)
[英]cuda shared memory, no synchronisation in kernel, premature output from kernel
[英]accessing a global memory pointer from a CUDA kernel
我试图分配设备内存并将指针存储为全局变量。 但是,当我尝试从内核访问内存时,我从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;
}
我们不在__device__
变量上使用cudaMalloc
和cudaMemcpy
。
阅读__device__
变量的文档 ,其中说明了要使用的API调用:
cudaMemcpyToSymbol();
cudaMemcpyFromSymbol();
如果要在动态分配的设备数组上使用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;
}
当我按原样编译你的代码时,我从CUDA 6 nvcc
收到以下编译器警告:
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.