Я пытаюсь выполнить QR-факторизацию на GPU, используя библиотеку cusolver из CUDA.
Я свел свою проблему к примеру ниже.
В основном, несколько шагов:
cusolverDnCreate
cusolverDnDgeqrf_bufferSize
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();
}
Если вы обнаружите явную ошибку в моем коде, пожалуйста, дайте мне знать!
Большое спасибо.
Каждый раз, когда у вас возникают проблемы с кодом CUDA, вы всегда должны использовать правильная проверка ошибок cuda и запустить свой код с cuda-memcheck
, до просить помощи.
Вы также можете знать, что полностью проработанный пример факторизации QR приведен в соответствующий пример кода CUDA / Cusolver и есть также пример кода в документации.
При правильной проверке ошибок вы можете обнаружить:
это не правильно
cudaMalloc((void **)&devInfo, 1);
второй параметр — это размер в байтах, поэтому он должен быть sizeof(int)
, а не 1. Эта ошибка приводит к ошибке в cudaMemcpyAsync
операция внутри cusolverDnDgeqrf
вызов, который будет отображаться в cuda-memcheck
выход.
Это не правильно
cudaMemcpy((void*)devInfo, (void*)&hDevInfo, 1 * sizeof(int), cudaMemcpyDeviceToHost);
порядок параметров указателя — пункт назначения первый, с последующим источником. Таким образом, вы изменили эти параметры, и этот вызов выдаст ошибку API времени выполнения, которую вы могли бы наблюдать, если бы выполняли надлежащую проверку ошибок (или были видны в cuda-memcheck
выход).
Как только вы исправите эти ошибки, тогда вызов qrf вернет нулевой статус (без ошибок). Но мы еще не закончили (опять же, правильная проверка ошибок даст нам знать, что мы еще не закончили).
В дополнение к вышеперечисленным ошибкам, вы сделали несколько дополнительных ошибок в размере. Ваша матрица имеет размер 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.
Других решений пока нет …