基本示例中的 cudaMemcpyDeviceToHost 错误

标签 cuda

我最近开始学习 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/

相关文章:

cuda - 简单的 CUBLAS 矩阵乘法示例?

cuda - 使用 cc 更改 Rust 传递给 nvcc 的编译参数

c++ - Visual Studio 2017 msvc vs nvcc __cplusplus 宏不匹配

c++ - 计算 FLOPS(每秒浮点运算)

cuda - CUDA需要根访问权限吗?

cuda - 为什么需要第二个 CUDA 内核来计算单源最短路径?

c++ - 如何创建 thrust::device_vectors 的通用表

c - 如何使用 C 头文件和 CUDA 代码编译 C 代码?

c++ - 拦截 CUDA 调用

cuda - 同时使用动态分配和静态分配的共享内存