在输入数据中使用各种偏移量时,CUDA内核启动失败
我的代码给出了一条错误消息,我正试图找出它的原因。为了更容易发现问题,我去掉了显然与导致错误消息无关的代码。如果您能告诉我为什么以下简单代码会产生错误消息,那么我认为我应该能够修复我的原始代码:在输入数据中使用各种偏移量时,CUDA内核启动失败,cuda,memory-alignment,Cuda,Memory Alignment,我的代码给出了一条错误消息,我正试图找出它的原因。为了更容易发现问题,我去掉了显然与导致错误消息无关的代码。如果您能告诉我为什么以下简单代码会产生错误消息,那么我认为我应该能够修复我的原始代码: #include "cuComplex.h" #include <cutil.h> __device__ void compute_energy(void *data, int isample, int nsamples) { cuDoubleComplex * const nminu
#include "cuComplex.h"
#include <cutil.h>
__device__ void compute_energy(void *data, int isample, int nsamples) {
cuDoubleComplex * const nminusarray = (cuDoubleComplex*)data;
cuDoubleComplex * const f = (cuDoubleComplex*)(nminusarray+101);
double * const abs_est_errorrow_all = (double*)(f+3);
double * const rel_est_errorrow_all = (double*)(abs_est_errorrow_all+nsamples*51);
int * const iid_all = (int*)(rel_est_errorrow_all+nsamples*51);
int * const iiu_all = (int*)(iid_all+nsamples*21);
int * const piv_all = (int*)(iiu_all+nsamples*21);
cuDoubleComplex * const energyrow_all = (cuDoubleComplex*)(piv_all+nsamples*12);
cuDoubleComplex * const refinedenergyrow_all = (cuDoubleComplex*)(energyrow_all+nsamples*51);
cuDoubleComplex * const btplus_all = (cuDoubleComplex*)(refinedenergyrow_all+nsamples*51);
cuDoubleComplex * const btplus = btplus_all+isample*21021;
btplus[0] = make_cuDoubleComplex(0.0, 0.0);
}
__global__ void computeLamHeight(void *data, int nlambda) {
compute_energy(data, blockIdx.x, nlambda);
}
int main(int argc, char *argv[]) {
void *device_data;
CUT_DEVICE_INIT(argc, argv);
CUDA_SAFE_CALL(cudaMalloc(&device_data, 184465640));
computeLamHeight<<<dim3(101, 1, 1), dim3(512, 1, 1), 45000>>>(device_data, 101);
CUDA_SAFE_CALL(cudaThreadSynchronize());
}
输出为:
Using device 0: GeForce GTX 480
Cuda error in file 'Main.cu' in line 31 : unspecified launch failure.
编辑:我现在进一步简化了代码。以下较简单的代码仍会生成错误消息:
#include <cutil.h>
__global__ void compute_energy(void *data) {
*(double*)((int*)data+101) = 0.0;
}
int main(int argc, char *argv[]) {
void *device_data;
CUT_DEVICE_INIT(argc, argv);
CUDA_SAFE_CALL(cudaMalloc(&device_data, 101*sizeof(int)+sizeof(double)));
compute_energy<<<dim3(1, 1, 1), dim3(1, 1, 1)>>>(device_data);
CUDA_SAFE_CALL(cudaThreadSynchronize());
}
我试图在互联网上搜索地址错位的含义,但没有找到解释。这是怎么回事?错误表明内存访问超出了限制,请检查偏移量值。使用所有这些神奇常量解析原始代码非常困难,但更新的复制案例使问题立即变得明显。GPU体系结构要求所有指针与字边界对齐。您的内核包含未正确对齐的指针访问。双精度是一种64位类型,并且您的寻址不与偶数64位边界对齐。这:
*(double*)((int*)data+100) = 0.0; // 50th double
或者这个:
*(double*)((int*)data+102) = 0.0; // 51st double
都是合法的。这:
*(double*)((int*)data+101) = 0.0; // not aligned to a 64 bit boundary
不是。工具箱中有一个名为cuda memcheck的实用程序,它将通过标记越界内存访问来准确显示问题发生的位置,这可能是此处的错误。谢谢您的建议。cuda memcheck表示地址未对齐。不幸的是,当我在互联网上搜索时,我找不到一个解释。我简化了我的代码,这样就可以清楚地看到内存访问不是越界的;显然,问题是另外一回事。请检查我对问题的编辑。你能解释一下吗?非常感谢。CUDA 4.2编程指南,第5.3.2.1节全局内存:全局内存驻留在设备内存中,通过32、64或128字节内存事务访问设备内存。这些内存事务必须自然对齐:只有与它们的大小对齐的32、64或128字节的设备内存段(即,其第一个地址是其大小的倍数)才能被内存事务读取或写入。这是我的问题-没有字对齐的结构。非常感谢。
*(double*)((int*)data+102) = 0.0; // 51st double
*(double*)((int*)data+101) = 0.0; // not aligned to a 64 bit boundary