2015-12-18 83 views
0

我尝试使用CUDA中的cusolver库在GPU上执行QR分解。状态:执行失败时,从CUDA库调用cusolverDnDgeqrf

我将问题简化为下面的示例。

基本上,几个步骤是:

  1. 我分配内存和初始化的[5X3]矩阵与 主机上1S,
  2. 我分配内存和复制装置上的矩阵
  3. 我初始化cusolverDnCreate
  4. 解算处理我确定所需的工作空间的大小与cusolverDnDgeqrf_bufferSize
  5. 最后,尝试做QR分解与cusolverDnDgeqrf

不幸的是,最后的命令系统返回一个CUSOLVER_STATUS_EXECUTION_FAILED(int值= 6)失败,我想不出哪里出了问题!

下面是错误代码:

#include <cusolverDn.h> 
#include <cuda_runtime_api.h> 
int main(void) 
{ 

int N = 5, P = 3; 

double *hostData; 
cudaMallocHost((void **) &hostData, N * sizeof(double)); 
for (int i = 0; i < N * P; ++i) 
    hostData[i] = 1.; 

double *devData; 
cudaMalloc((void**)&devData, N * sizeof(double)); 

cudaMemcpy((void*)devData, (void*)hostData, N * sizeof(double), cudaMemcpyHostToDevice); 

cusolverStatus_t retVal; 
cusolverDnHandle_t solverHandle; 

retVal = cusolverDnCreate(&solverHandle); 
std::cout << "Handler creation : " << retVal << std::endl; 

double *devTau, *work; 
int szWork; 

cudaMalloc((void**)&devTau, P * sizeof(double)); 

retVal = cusolverDnDgeqrf_bufferSize(solverHandle, N, P, devData, N, &szWork); 
std::cout << "Work space sizing : " << retVal << std::endl; 

cudaMalloc((void**)&work, szWork * sizeof(double)); 

int *devInfo; 
cudaMalloc((void **)&devInfo, 1); 

retVal = cusolverDnDgeqrf(solverHandle, N, P, devData, N, devTau, work, szWork, devInfo); //CUSOLVER_STATUS_EXECUTION_FAILED 
std::cout << "QR factorization : " << retVal << std::endl; 

int hDevInfo = 0; 
cudaMemcpy((void*)devInfo, (void*)&hDevInfo, 1 * sizeof(int), cudaMemcpyDeviceToHost); 
std::cout << "Info device : " << hDevInfo << std::endl; 

cudaFree(devInfo); 
cudaFree(work); 
cudaFree(devTau); 
cudaFree(devData); 
cudaFreeHost(hostData); 

cudaDeviceReset(); 

} 

你会看到任何明显的错误在我的代码,请让我知道! 非常感谢。

回答

2

您有一个CUDA代码的麻烦任何时候,你应该总是使用proper cuda error checkingcuda-memcheck之前运行代码,寻求帮助。

您可能还想知道在relevant CUDA/cusolver sample code中给出了完整工作的QR分解示例,并且还有示例代码in the documentation

通过适当的错误检查,你可能已经发现:

  1. 这是不正确的:

    cudaMalloc((void **)&devInfo, 1); 
    

    第二个参数是字节大小,所以它应该是sizeof(int),而不是1 。该错误导致调用cusolverDnDgeqrf内部的cudaMemcpyAsync操作出现错误,该错误将显示在cuda-memcheck输出中。

  2. 这是不正确:

    cudaMemcpy((void*)devInfo, (void*)&hDevInfo, 1 * sizeof(int), cudaMemcpyDeviceToHost); 
    

    指针参数的顺序是目的地第一,随后源。因此,您将这些参数颠倒过来,并且此调用会抛出运行时API错误,您可以观察到是否正在进行适当的错误检查(或在cuda-memcheck输出中可见)。

一旦你修复了这些错误,那么qrf调用实际上会返回一个零状态(没有错误)。但是我们还没有完成(再次,适当的错误检查会让我们知道我们还没有完成。)

  1. 除了上述错误,您还做了一些额外的大小错误。你的矩阵是大小N*P的,所以它有N*P元素,你在这里初始化很多元素:

    for (int i = 0; i < N * P; ++i) 
        hostData[i] = 1.; 
    

    但你不是分配主机这里的许多元素:

    cudaMallocHost((void **) &hostData, N * sizeof(double)); 
    

    或设备在这里:

    cudaMalloc((void**)&devData, N * sizeof(double)); 
    

    ,你不会把很多ELEM已废除的位置:

    cudaMemcpy((void*)devData, (void*)hostData, N * sizeof(double), cudaMemcpyHostToDevice); 
    

    因此在上面的3例,如果你改变N*sizeof(double)N*P*sizeof(double)你将能够修复这些错误,并且代码然后没有通过cuda-memcheck报告的错误运行,也没有返回错误任何API调用。