显卡内存冲突问题

不好意思,我是CUDA的初入门者。
最近编程中遇到个问题, 一直困扰了2个月。不知道怎么弄。

我写了一个CUDA 子程序,在 C 的主程序中循环调用。 同时把GPU内存的数据输出到CPU。
当循环数小于谋个数(譬如 N=15), 子程序调没问题,数据传递也没问题。
但当循环到大于15时, 数据传递出了问题
显示以下错误:
First-chance exception at 0x000007fefd34aa7d in cudaCubicRotate2D.exe: Microsoft C++ exception: cudaError_enum at memory location 0x0012f9a0…

跪求大虾帮助!!

主程序如下

I’m beginner of Cuda coding. I am being stacked by cudaError_enum at memory location xxxxx;

I deveoped a global cuda functionin, and try to called it in a loop (0=< k <= N), and transfter data out from GPU to CPU.
this function works when k<15. and I can transfter data out from GPU to CPU using cudaMemcpy. When K goes to 15, the cuda function still works. While, cudaMemcpy function does not work, it gives out the error:
“First-chance exception at 0x000007fefd34aa7d in cudaCubicRotate2D.exe: Microsoft C++ exception: cudaError_enum at memory location 0x0012f9a0.”

Could anyone please help me ? I has been stopped by this for couple months. Any help will be highly appreicated.

[codebox]
main code.

const dim3 blockSize(16, 16);
const dim3 gridSize(imageSize.x / blockSize.x, imageSize.y / blockSize.y);
for(k = 0; k < 100; k++){
warp_kernel<<<gridSize, blockSize>>>(output, voxel, coordX, coordY, coordZ, imageSize, k, threshold);
cudaMemcpy(OutImage, output, nrOfBytes, cudaMemcpyDeviceToHost);
for(j = 0; j < imageSize.y; j++){
for(i = 0; i < imageSize.x; i++){
OutputImage[k * slice + j * imageSize.x +i] = OutImage[j * imageSize.x + i];
}
}
}

function

///// Warp the refernece image into different phase ///////////
global void
warp_kernel(float* output, float* voxel, float* coordX, float* coordY, float* coordZ, uint3 imageSize, uint k, int threshold)
{

//long k = 0;
uint i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
uint j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
uint tt = __umul24(j, imageSize.x) + i;
long nx, ny, nz;
float temp, temp1, temp2, temp3, temp0;
float *p0, *px, *py, *pz, *px0, *py0, *pz0;
long ix, iy, iz, ixL, ixU, iyL, iyU, izL, izU;
long slice = imageSize.x * imageSize.y;
/////////////// warp the first slice ////////////////////
ixL = max(0, i - threshold);
ixU = min (imageSize.x - 1, i + threshold);
iyL = max(0, j - threshold);
iyU = min (imageSize.y - 1, j + threshold);
izL = max(0, k - threshold);
izU = min (imageSize.z - 1, k + threshold);
ix = (long)i;
iy = (long)j;
iz = (long)k;
temp1 = coordX[iz * slice + iy * imageSize.x + ix];
temp2 = coordY[iz * slice + iy * imageSize.x + ix];
temp3 = coordZ[iz * slice + iy * imageSize.x + ix];
temp = (temp1 - (float)i) * (temp1 - (float)i) + (temp2 - (float)j) * (temp2 - (float)j) + (temp3 - (float)k) * (temp3 - (float)k);

for (nz = izL; nz <= izU; nz++){
px = coordX + (ptrdiff_t)(nz * slice);
py = coordY + (ptrdiff_t)(nz * slice);
pz = coordZ + (ptrdiff_t)(nz * slice);
for (ny = iyL; ny <= iyU; ny++){
px0 = px + (ptrdiff_t)(ny * imageSize.x);
py0 = py + (ptrdiff_t)(ny * imageSize.x);
pz0 = pz + (ptrdiff_t)(ny * imageSize.x);
for (nx = ixL; nx <= ixU; nx++){
float temp11 = px0[nx];
float temp22 = py0[nx];
float temp33 = pz0[nx];
temp0 = (temp11 - i) * (temp11 - i) + (temp22 - j) * (temp22 - j) + (temp33 - k) * (temp33 - k);
if( temp0 < temp ){
ix = nx;
iy = ny;
iz = nz;
temp = temp0;
}
}
}
}
p0 = voxel + (ptrdiff_t)(iz * slice + iy * imageSize.x + ix);
output[tt] = p0[0];
}
';[/codebox]

[ 本帖最后由 tangql2010 于 2010-9-8 06:06 编辑 ]

const dim3 gridSize(imageSize.x / blockSize.x, imageSize.y / blockSize.y);
修改为
const dim3 gridSize((imageSize.x +blockSize.x-1)/ blockSize.x,( imageSize.y+blockSize.y-1 )/ blockSize.y);

非常感谢你的帮助!
我还有几点疑问想请教:

1。
(imageSize.x +blockSize.x-1)/ blockSize.x 这样gridSize就不是整数了? 这样做出于什么考虑?

2。我按你的意见修改了之后还是出老问题。

3。我发现如果 int threshold 减小, 也就是子程序中的3重循环都减小了循环次数, 这个
“First-chance exception at 0x000007fefd34aa7d in cudaCubicRotate2D.exe:”
错误就没有了,计算结果正常。

但我得程序需要较大的 int threshold ,来搜索比较大的3维区域。 从这个情况,您估计会是哪里出了问题。

下面我列出了简化版子程序,我认为可读性会好些。
非常感谢你能再次帮忙!

global void
warp_kernel(float* output, float* voxel, float* coordX, float* coordY, float* coordZ, uint3 imageSize, uint k, int threshold)
{

uint i = __umul24(blockIdx.x, blockDim.x) + threadIdx.x;
uint j = __umul24(blockIdx.y, blockDim.y) + threadIdx.y;
uint tt = __umul24(j, imageSize.x) + i;
long nx, ny, nz;
float temp, temp1, temp2, temp3, temp0;
long ix, iy, iz, ixL, ixU, iyL, iyU, izL, izU;
long slice = imageSize.x * imageSize.y;

ixL = max(0, i - threshold); ixU = min (imageSize.x - 1, i + threshold);
iyL = max(0, j - threshold); iyU = min (imageSize.y - 1, j + threshold);
izL = max(0, k - threshold); izU = min (imageSize.z - 1, k + threshold);

temp1 = coordX[ixL * slice + iyL * imageSize.x + ixL] - (float)i;
temp2 = coordY[izL * slice + iyL * imageSize.x + ixL] - (float)j;
temp3 = coordZ[izL * slice + iyL * imageSize.x + ixL] - (float)k;
temp = temp1 * temp1 + temp2 * temp2 + temp3 * temp3;

for (nz = izL; nz <= izU; nz++){
for (ny = iyL; ny <= iyU; ny++){
for (nx = ixL; nx <= ixU; nx++){
temp1 = coordX[nz * slice + ny * imageSize.x + nx] - (float)i;
temp2 = coordY[nz * slice + ny * imageSize.x + nx] - (float)j;
temp3 = coordZ[nz * slice + ny * imageSize.x + nx] - (float)k;
temp0 = temp1 * temp1 + temp2 * temp2 + temp3 * temp3;
if( temp0 < temp ){
ix = nx;
iy = ny;
iz = nz;
temp = temp0;
}
}
}
}
output[tt] = voxel[iz * slice + iy * imageSize.x + ix];
}

在内核函数中处理一下多余线程

你那个应该是显存越界了

谢谢!
能否更具体一点?我初学者,基本不了解 CUDA和GPU原理,只会照教程套。所以除了问题也不知道是啥问题。
在内核函数中处理一下多余线程? 怎么处理多余线程?不要意思这都是很低级的问题。
显存越界? 是说我的显存不够吗?

就是你分配的线程数可能大于真正要用到的,所以在内核中应该用if语句限制一下

是指循环数大于数组的维数? 还是那个blockDim, 和 threadIdx 的问题?
如果是前面一个的话,我觉得我已经用了max 和 min 函数限制了。估计不会有问题。
如果是后一个问题,
那个gridSize 和blockSize是在主程序中,按照数组维数大小赋值的。 什么情况下会使线程超了?
如果是超了? 那我该在哪里用if 限制?不好意思文这么愚蠢的问题。

譬如在我的cuda 子函数中限制一下 i,j 的取值?

非常感激

要不你模拟运行一下看看那个语句出错了,这样光眼看很难看到真正出错的地方!

我运行了程序。
那个子程序能调用, 不会报错。 但后面的 cudaMemcpy(OutImage, output, nrOfBytes, cudaMemcpyDeviceToHost);
会报错。
也就是调用完子程序(但不知道调用正确与否),不能从显卡内存中输出数据。 主程序别的命令都可以执行。

但是如果子程序循环次数少一些,就能正常调用和从显卡中输出数据。

[

/////

我现在升级了显卡驱动程序到 devdriver_3.2_winvista-win7_64_260.61_general.

程序不会出错,也就是在调用完cuda程序后,能从gpu中传数据到cpu, 但是传输速度很慢。

传输速度取决于cuda 子程序中,循环搜索区间大小。

搜索区间越大,传输越慢。 (不管搜索区间大小,每次传输的数据大小是相同的)。

这会是什么原因?
谢谢