状态:从CUDA库调用cusolverDnDgeqrf时执行失败

时间:2015-12-18 17:13:00

标签: c++ cuda gpu cusolver

我尝试使用CUDA的cusolver库在GPU上执行QR分解。

我将问题减少到下面的例子。

基本上,几个步骤是:

  1. 我分配内存并初始化一个[5x3]矩阵,其中包含1 主持人,
  2. 我在设备上分配内存并复制矩阵
  3. 我使用cusolverDnCreate
  4. 初始化解算器处理程序
  5. 我使用cusolverDnDgeqrf_bufferSize
  6. 确定所需工作空间的大小
  7. 最后,尝试使用cusolverDnDgeqrf
  8. 进行QR分解

    不幸的是,最后一个命令通过返回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();
    
    }
    

    您是否在我的代码中看到任何明显错误,请告诉我们! 非常感谢。

1 个答案:

答案 0 :(得分:2)

如果您在使用cuda代码时出现问题,则应始终使用proper cuda error checking并在寻求帮助之前使用cuda-memcheck运行代码。

您可能还想知道relevant CUDA/cusolver sample code中提供了完全有效的QR分解示例,并且还有示例代码in the documentation

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

  1. 这不正确:

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

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

  2. 这是不正确的:

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

    指针参数的顺序是目标 first ,后跟source。因此,您将这些参数反转,并且此调用将引发运行时API错误,如果您正在进行正确的错误检查(或在cuda-memcheck输出中可见),则可以观察到该错误。

  3. 修复这些错误后,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));
      

      并且你没有在这里转移那么多元素:

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

      因此,在上述3个案例中,如果您将N*sizeof(double)更改为N*P*sizeof(double),则可以修复这些错误,然后代码运行时cuda-memcheck报告没有错误,并且也没有任何API调用返回错误。