2012-05-14 47 views
3

这里是我的代码:CUDA cudaMemcpy:无效的参数

struct S { 
    int a, b; 
    float c, d; 
}; 
class A { 
private: 
    S* d; 
    S h[3]; 
public: 
    A() { 
     cutilSafeCall(cudaMalloc((void**)&d, sizeof(S)*3)); 
    } 
void Init(); 
}; 

void A::Init() { 
    for (int i=0;i<3;i++) { 
     h[i].a = 0; 
     h[i].b = 1; 
     h[i].c = 2; 
     h[i].d = 3; 
    } 
    cutilSafeCall(cudaMemcpy(d, h, 3*sizeof(S), cudaMemcpyHostToDevice)); 
} 

A a; 

其实,这是一个复杂的程序,它包含CUDA和OpenGL。当我调试此程序时,它在运行cudaMemcpy时出错,并显示错误信息

cudaSafeCall()运行时API错误11:无效参数。

实际上,这个程序是从另一个可以正确运行的程序转换而来的。但在那个中,我在主函数中使用了两个变量S * d和S h [3],而不是在类中。更奇怪的是,我在一个小程序中实现了这个类A,它工作正常。 而我更新了我的驱动程序,错误仍然存​​在。

任何人都可以告诉我为什么会发生这种情况,以及如何解决它。谢谢。

+0

顺便说一句,cudaMemcpy会reture cudaErrorInvalidValue。 – TonyLic

+2

线路'A a;'在哪里?它是在一个函数内,还是全局的?如果它是全局的,那么在你有一个有效的设备上下文之前可能会调用构造函数(我不确定这一点,但这是可能的)。如果是这种情况,那么传递给cudaMemcpy的d指针将是无效的。 – harrism

+0

你可以发布你使用的CUDA配置吗?我无法用旧版GeForce 9400m和CUDA 5.0预览版重现您的错误。 – jopasserat

回答

3

由于CUDA中的内存操作是阻塞的,因此它们会生成一个同步点。所以如果不用cudaThreadSynchonize进行检查,其他错误在内存调用中看起来就像是错误。

因此,如果在内存操作上收到错误,请尝试在它之前放置一个cudaThreadSynchronize并检查结果。


确保第一个malloc语句正在执行。如果这是CUDA初始化的问题,就像@Harrism所指出的那样,那么它在这个声明中会失败?尝试放置printf语句,并查看正确的初始化。我认为通常会产生无效的参数错误,因为使用了未经初始化的内存区域。

  1. 写一个printf到你的构造显示cudaMalloc'ed内存区域的

    A() 
    { 
        d = NULL; 
        cutilSafeCall(cudaMalloc((void**)&d, sizeof(S)*3)); 
        printf("D: %p\n", d); 
    } 
    
  2. 尝试地址,以用于在本地分配的区域的存储器复制,即移动cudaMalloc到以上的cudaMemcopy(仅用于测试)。

    void A::Init() 
    { 
        for (int i=0;i<3;i++) 
        { 
         h[i].a = 0; 
         h[i].b = 1; 
         h[i].c = 2; 
         h[i].d = 3; 
        } 
        cutilSafeCall(cudaMalloc((void**)&d, sizeof(S)*3)); // here!.. 
        cutilSafeCall(cudaMemcpy(d, h, 3*sizeof(S), cudaMemcpyHostToDevice)); 
    } 
    

好运。