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

Status: execution failed, when invoking cusolverDnDgeqrf from CUDA library

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

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

基本上,几个步骤是:

  1. 我分配内存并初始化一个 [5x3] 矩阵,其中 1s 主持人,
  2. 我在设备上分配内存并复制矩阵
  3. 我用 cusolverDnCreate
  4. 初始化求解器处理程序
  5. 我用 cusolverDnDgeqrf_bufferSize
  6. 确定所需工作的大小 space
  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();

}

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

任何时候你在使用 cuda 代码时遇到问题,你应该总是使用 proper cuda error checking 和 运行 你的代码 cuda-memcheck, before 寻求帮助。

您可能还想知道 relevant CUDA/cusolver sample code and there is also sample code in the documentation.

中给出了完整的 QR 因式分解示例这一事实

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

  1. 这是不正确的:

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

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

  2. 这是不正确的:

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

    指针参数的顺序是目标,然后是源。所以你把这些参数颠倒了,这个调用会抛出一个 运行time API 错误,如果你进行了正确的错误检查(或者在 cuda-memcheck 输出中可见),你可以观察到这个错误。

修复这些错误后,qrf 调用实际上会 return 零状态(无错误)。但是我们还没有完全完成(同样,适当的错误检查会让我们知道我们还没有完全完成。)

  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),您将能够修复这些错误,然后代码 运行s 不会报告任何错误cuda-memcheck,并且 return 任何 API 调用都没有错误。