在输入数据中使用各种偏移量时,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