我最近开始学习 CUDA,并使用 Nsight 将 CUDA 集成到 MS Visual Studio 2010 中。我还获得了《CUDA by Examples》一书,我正在浏览所有示例并编译它们。但是我遇到了一个错误,我不明白。 该程序来自第 4 章,是 julia_gpu 示例。原始代码:
#include "../common/book.h"
#include "../common/cpu_bitmap.h"
#define DIM 1000
struct cuComplex {
float r;
float i;
cuComplex( float a, float b ) : r(a), i(b) {}
__device__ float magnitude2( void ) {
return r * r + i * i;
}
__device__ cuComplex operator*(const cuComplex& a) {
return cuComplex(r*a.r - i*a.i, i*a.r + r*a.i);
}
__device__ cuComplex operator+(const cuComplex& a) {
return cuComplex(r+a.r, i+a.i);
}
};
__device__ int julia( int x, int y ) {
const float scale = 1.5;
float jx = scale * (float)(DIM/2 - x)/(DIM/2);
float jy = scale * (float)(DIM/2 - y)/(DIM/2);
cuComplex c(-0.8, 0.156);
cuComplex a(jx, jy);
int i = 0;
for (i=0; i<200; i++) {
a = a * a + c;
if (a.magnitude2() > 1000)
return 0;
}
return 1;
}
__global__ void kernel( unsigned char *ptr ) {
// map from blockIdx to pixel position
int x = blockIdx.x;
int y = blockIdx.y;
int offset = x + y * gridDim.x;
// now calculate the value at that position
int juliaValue = julia( x, y );
ptr[offset*4 + 0] = 255 * juliaValue;
ptr[offset*4 + 1] = 0;
ptr[offset*4 + 2] = 0;
ptr[offset*4 + 3] = 255;
}
// globals needed by the update routine
struct DataBlock {
unsigned char *dev_bitmap;
};
int main( void ) {
DataBlock data;
CPUBitmap bitmap( DIM, DIM, &data );
unsigned char *dev_bitmap;
HANDLE_ERROR( cudaMalloc( (void**)&dev_bitmap, bitmap.image_size() ) );
data.dev_bitmap = dev_bitmap;
dim3 grid(DIM,DIM);
kernel<<<grid,1>>>( dev_bitmap );
HANDLE_ERROR( cudaMemcpy( bitmap.get_ptr(), dev_bitmap,
bitmap.image_size(),
cudaMemcpyDeviceToHost ) );
HANDLE_ERROR( cudaFree( dev_bitmap ) );
bitmap.display_and_exit();
}
然而,我的 Visual Studio 强制我将 cuComplex 构造函数修饰到设备,否则它将无法编译(它告诉我以后不能在 julia 函数中使用它),我认为这是公平的足够的。所以我有:
__device__ cuComplex( float a, float b ) : r(a), i(b) {}
但是当我运行该示例时(添加了通过 VS 运行所需的包含内容,即 cuda_runtime.h 和 device_launch_parameters.h,以及将 glut32.dll 复制到与 exe 相同的文件夹中)很快就失败了,杀死了我的设备驱动程序,并说这是由于第 94 行中的未知错误,即 main 中的 cudaMemcpy 调用。确切地说,它是包含调用“cudaDeviceToHost”的实际行。然而,坦率地说,我尝试逐行创建一些断点,并且驱动程序在内核调用时终止。
有人可以告诉我可能出了什么问题吗?我是 CUDA 的菜鸟,不知道为什么一个简单的例子会这样自杀。我可能做错了什么?因为坦白说,我什至不知道要调查什么。 我有 CUDA 4.1 工具包、NSight 2.1 和计算能力为 2.1 的 GeForce GT445M 以及 295 版本的驱动程序。
最佳答案
我还没有时间对此进行测试,但我认为就 Windows 而言,这可能是您的 GFX“超时”。
Windows 具有 Vista 中的默认行为,即告诉 gfx 驱动程序在 2 秒后恢复。如果你的工作需要更长的时间,那么你就会被解雇。您可以通过注册表增加或删除此功能。我认为您需要重新启动,因为我刚刚进行了更改,但它还没有工作。 详细请参阅此链接: http://msdn.microsoft.com/en-us/windows/hardware/gg487368.aspx
...
Timeout Detection and Recovery : Windows Vista attempts to detect these problematic hang situations and recover a responsive desktop dynamically. In this process, the Windows Display Driver Model (WDDM) driver is reinitialized and the GPU is reset. No reboot is necessary, which greatly enhances the user experience. The only visible artifact from the hang detection to the recovery is a screen flicker, which results from resetting some portions of the graphics stack, causing a screen redraw. Some older Microsoft DirectX applications may render to a black screen at the end of this recovery. The end user would have to restart these applications. The following is a brief overview of the TDR process: ....
显然,这就是为什么它是一个奇怪的错误,因为它会给你不同规模的内存复制错误,具体取决于他们的 gfx 的速度。
这是 CUDA 中的一个已知问题。
关于基本示例中的 cudaMemcpyDeviceToHost 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9807685/