Состояние: сбой выполнения при вызове cusolverDnDgeqrf из библиотеки CUDA

Я пытаюсь выполнить QR-факторизацию на GPU, используя библиотеку cusolver из CUDA.

Я свел свою проблему к примеру ниже.

В основном, несколько шагов:

  1. Я выделяю память и инициализирую матрицу [5×3] с 1 с на
    хозяин,
  2. Я выделяю память и копирую матрицу на устройство
  3. Я инициализирую обработчик решателя с cusolverDnCreate
  4. Я определяю размер необходимого рабочего пространства с помощью cusolverDnDgeqrf_bufferSize
  5. И, наконец, попробуйте сделать QR-факторизацию с cusolverDnDgeqrf

К сожалению, последняя команда систематически завершается ошибкой, возвращая CUSOLVER_STATUS_EXECUTION_FAILED (int value = 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();

}

Если вы обнаружите явную ошибку в моем коде, пожалуйста, дайте мне знать!
Большое спасибо.

0

Решение

Каждый раз, когда у вас возникают проблемы с кодом CUDA, вы всегда должны использовать правильная проверка ошибок cuda и запустить свой код с cuda-memcheck, до просить помощи.

Вы также можете знать, что полностью проработанный пример факторизации QR приведен в соответствующий пример кода CUDA / Cusolver и есть также пример кода в документации.

При правильной проверке ошибок вы можете обнаружить:

  1. это не правильно

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

    второй параметр — это размер в байтах, поэтому он должен быть sizeof(int), а не 1. Эта ошибка приводит к ошибке в cudaMemcpyAsync операция внутри cusolverDnDgeqrf вызов, который будет отображаться в 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));
    

    и вы не передаете столько элементов здесь:

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

    Так что в 3 случаях выше, если вы измените N*sizeof(double) в N*P*sizeof(double) Вы сможете исправить эти ошибки, и код будет работать без ошибок, о которых сообщает cuda-memcheck, а также никаких ошибок не возвращается ни от одного из вызовов API.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]