【发布时间】:2016-06-03 19:03:22
【问题描述】:
我已经初始化了一个数组,我试图在内核调用的每个线程中使用它(每个线程使用数组的不同部分,因此没有依赖关系)。我使用cudaMalloc 创建数组并在设备上保存内存,然后使用cudaMemcpy 将数组从主机复制到设备。
我将cudaMalloc 返回的指针传递给内核调用以供每个线程使用。
int SIZE = 100;
int* data = new int[SIZE];
int* d_data = 0;
cutilSafeCall( cudaMalloc(&d_data, SIZE * sizeof(int)) );
for (int i = 0; i < SIZE; i++)
data[i] = i;
cutilSafeCall( cudaMemcpy(d_data, data, SIZE * sizeof(int), cudaMemcpyHostToDevice) );
此代码取自 here。 用于内核调用。
kernel<<<blocks, threads>>> (results, d_data);
我使用结构Result 跟踪每个线程的结果。下一个代码可以正常工作。
__global__ void mainKernel(Result res[], int* data){
int x = data[0];
}
但是当我将该值分配给res:
__global__ void mainKernel(Result res[], int* data){
int threadId = (blockIdx.x * blockDim.x) + threadIdx.x;
int x = data[0];
res[threadId].x = x;
}
出现错误:
文件中的 cudaSafeCall() 运行时 API 错误,第 355 行:遇到非法内存访问。
任何涉及使用该指针的操作都会出现相同的错误
__global__ void mainKernel(Result res[], int* data){
int threadId = (blockIdx.x * blockDim.x) + threadIdx.x;
int x = data[0];
if (x > 10)
res[threadId].x = 5;
}
res的定义没有问题。将任何其他值分配给 res[threadId].x 不会给我任何错误。
这是运行 cuda-memcheck 的输出:
========= 无效的 __global__ 读取大小为 4
========= 在 mainKernel 中的 0x00000150(结果*,int*)
========= 块 (49,0,0) 中的线程 (86,0,0)
========= 地址 0x13024c0000 超出范围
========= 在内核启动时将主机回溯保存到驱动程序入口点
========= 主机框架:/usr/lib/x86_64-linux-gnu/libcuda.so.1 (cuLaunchKernel + 0x2cd) [0x150d6d]
========= 主机帧:./out [0x2cc4b]
========= 主机帧:./out [0x46c23]
========= 主机帧:./out [0x3e37]
========= 主机帧:./out [0x3ca1]
========= 主机帧:./out [0x3cd6]
========= 主机帧:./out [0x39e9]
========= 主机框架:/lib/x86_64-linux-gnu/libc.so.6 (__libc_start_main + 0xf5) [0x21ec5]
========= 主机帧:./out [0x31b9]
编辑:
这是完整代码的示例:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <iostream>
#include <assert.h>
typedef struct
{
int x,y,z;
} Result;
__global__ void mainKernel(Result pResults[], int* dataimage)
{
int threadId = (blockIdx.x * blockDim.x) + threadIdx.x;
int xVal = dataimage[0];
if (xVal > 10)
pResults[threadId].x = 5;
}
int main (int argc, char** argv)
{
int NUM_THREADS = 5*5;
int SIZE = 100;
int* data = new int[SIZE];
int* d_data = 0;
cutilSafeCall( cudaMalloc(&d_data, SIZE * sizeof(int)) );
for (int i = 0; i < SIZE; i++)
data[i] = i;
cutilSafeCall( cudaMemcpy(d_data, data, SIZE * sizeof(int), cudaMemcpyHostToDevice) );
unsigned int GPU_ID = 1; // not actually :-)
// unsigned int GPU_ID = cutGetMaxGflopsDeviceId() ;
cudaSetDevice(GPU_ID);
Result * results_GPU = 0;
cutilSafeCall( cudaMalloc( &results_GPU, NUM_THREADS * sizeof(Result)) );
Result * results_CPU = 0;
cutilSafeCall( cudaMallocHost( &results_CPU, NUM_THREADS * sizeof(Result)) );
mainKernel<<<5,5>>> ( results_GPU, d_data );
cudaThreadSynchronize();
cutilSafeCall( cudaMemcpy(results_CPU, results_GPU, NUM_THREADS * sizeof(Result),cudaMemcpyDeviceToHost) );
cutilSafeCall(cudaFree(results_GPU));
cutilSafeCall(cudaFreeHost(results_CPU));
cudaThreadExit();
} // ()
【问题讨论】:
-
问题显然出在
results,但您已经设法完全省略了所有显示您如何定义和分配它的代码。您能否编辑您的问题以包含其他人可以编译和运行的简短、完整的代码?没有它,你的问题很难得到任何答案 -
要清楚,确切的代码会产生您发布的错误?你有多少个 CUDA GPU?
-
是的(您必须包括 CudaSafeCall)。我有两个 GPU。我删除了用于选择 GPU (cudaSetDevice) 的行,它不会引发任何错误。发生了什么事?