#c #cuda #cusolver
#c #cuda #решатель
Вопрос:
Я хотел протестировать реализацию cuda xgels, поставляемую с CUDA 11.1, и, похоже, я не могу заставить ее работать должным образом. Например, этот код, кажется, работает просто отлично:
#include <armadillo>
#include <cusolverDn.h>
int main()
{
const int m = 1000;
const int n = 10;
const int nrhs = 2;
arma::mat A(m, n, arma::fill::randn);
arma::mat B(m, nrhs, arma::fill::randn);
A.col(0).fill(1.0);
B = 10.0;
const arma::mat refX = arma::solve(A, B);
cusolverDnHandle_t handle;
cusolverDnCreate(amp;handle);
cusolverStatus_t status;
const int lda = m;
const int ldb = std::max(m, n);
size_t l_work = 0;
status = cusolverDnDDgels_bufferSize(
handle,
m, n, nrhs,
NULL, lda,
NULL, ldb,
NULL, ldb,
NULL, amp;l_work);
std::cout <<"Workspace: " << l_work << "!***n";
//One if ok
std::cout << "Find Workspace - 1 if ok: "<<(status == CUSOLVER_STATUS_SUCCESS)<<"!***n";
double* d_work;
cudaMalloc(reinterpret_cast<void**>(amp;d_work), l_work);
int* d_info;
cudaMalloc(reinterpret_cast<void**>(amp;d_info), sizeof(int));
cudaMemset(d_info, 0, sizeof(int));
double* dA, *dB, *dX;
cudaMalloc(reinterpret_cast<void**>(amp;dA), A.n_elem* sizeof(double));
cudaMalloc(reinterpret_cast<void**>(amp;dB), B.n_elem* sizeof(double));
cudaMemcpy(dA,A.memptr(), A.n_elem * sizeof(double),cudaMemcpyHostToDevice);
cudaMemcpy(dB, B.memptr(), B.n_elem * sizeof(double), cudaMemcpyHostToDevice);
cudaMalloc(reinterpret_cast<void**>(amp;dX), refX.n_elem * sizeof(double));
cudaMemset(dX, 0, refX.n_elem * sizeof(double));
int iter = 0;
status = cusolverDnDDgels(handle,
m, n, nrhs,
dA, lda,
dB, ldb,
dX, ldb,
d_work, l_work,
amp;iter, d_info);
//One if ok
std::cout << "Solve status - 1 if ok: " << (status == CUSOLVER_STATUS_SUCCESS) << "!***n";
int h_info = -1;
cudaMemcpy(amp;h_info, d_info,sizeof(int),cudaMemcpyDeviceToHost);
std::cout << "Iter: " <<iter << "!n";
//0 if ok
std::cout << "Info - 0 if ok :" << h_info << "!n";
//Comparison of the results results
arma::mat cudaX(refX.n_rows, refX.n_cols);
cudaMemcpy(cudaX.memptr(), dX, cudaX.n_elem * sizeof(double), cudaMemcpyDeviceToHost);
std::cout << "Armadillo result:n" <<refX.t() <<"n";
std::cout << "cusolver result:n" << cudaX.t() << "n";
cudaFree(dA);
cudaFree(dB);
cudaFree(dX);
cudaFree(d_work);
cudaFree(d_info);
}
Результаты, к сожалению, неверны, так как только первый столбец кажется нормальным:
Рабочее место: 3653888!***
Найдите рабочее пространство — 1, если все в порядке: 1!***
Статус решения — 1, если все в порядке: 1!***
Iter: -51!
Информация — 0, если все в порядке: 0!
Результат броненосца:
9.9965 -0.0198 0.0290 -0.0317 0.0027 -0.0197 0.0377 -0.0379 -0.0172 0.0088
9.9774 0.0485 0.0089 -0.0233 0.0054 -0.0257 0.0130 0.0080 0.0149 -0.0335
результат cusolver:
9.9965 -0.0198 0.0290 -0.0317 0.0027 -0.0197 0.0377 -0.0379 -0.0172 0.0088
-0.8578 0.1884 0.5331 -0.8275 0.1992 -0.0587 1.0014 -0.0250 0.6571 -0.5516
Если я запускаю cuda-memcheck, первая ошибка, которую я получаю, это:
========= CUDA-MEMCHECK
========= Invalid __global__ write of size 8
========= at 0x00001aa0 in void copy_AtoB_kernel<double>(int, int, double const *, int, double*, int)
========= by thread (31,0,0) in block (15,0,0)
========= Address 0xb00e9b2f8 is out of bounds
========= Device Frame:void copy_AtoB_kernel<double>(int, int, double const *, int, double*, int) (void copy_AtoB_kernel<double>(int, int, double const *, int, double*, int) : 0x1aa0)
========= Saved host backtrace up to driver entry point at kernel launch time
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x751f4]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x75577]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x79cd9]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll (cuProfilerStop 0x11ce4a) [0x32e5ba]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x16cfe5]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll (cuProfilerStop 0xf1052) [0x3027c2]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x3841d]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x3890c]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll [0x38be4]
========= Host Frame:C:WINDOWSsystem32DriverStoreFileRepositorynv_dispi.inf_amd64_8e1b465b962975a0nvcuda64.dll (cuLaunchKernel 0x234) [0x201044]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll [0x4856]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll [0x22b4]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll (cusolverDnIRSParamsSetTolInner 0x2269) [0xda299]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll (cusolverDnIRSParamsSetTolInner 0x29f1) [0xdaa21]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll (cusolverDnIRSParamsSetTolInner 0xea66) [0xe6a96]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll (cusolverDnZZgesv_bufferSize 0x5b61) [0x103d41]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll (cusolverDnIRSXgels 0x4b6) [0x109cb6]
========= Host Frame:C:Program FilesNVIDIA GPU Computing ToolkitCUDAv11.1bincusolver64_11.dll (cusolverDnZZgesv_bufferSize 0x11e4) [0xff3c4]
========= Host Frame:C:sw_sourceSEM.MaevebuildReleasePerformanceTest.exe (main 0x36c) [0x292d08c]
========= Host Frame:C:sw_sourceSEM.MaevebuildReleasePerformanceTest.exe (__scrt_common_main_seh 0x10c) [0x2ce4378]
========= Host Frame:C:WINDOWSSystem32KERNEL32.DLL (BaseThreadInitThunk 0x14) [0x17c24]
========= Host Frame:C:WINDOWSSYSTEM32ntdll.dll (RtlUserThreadStart 0x21) [0x6d4d1]
Таким образом, кажется, что в коде есть ошибка памяти, но я не могу обнаружить никаких ошибок в моем использовании. Более того, если я закомментирую вызов cusolverDnDDgels, ошибка исчезнет.
Есть какие-нибудь подсказки о том, что приводит к сбою этого кода?
Я выполняю код на rtx 2080TI, и код компилируется с:
> nvcc --version
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2020 NVIDIA Corporation
Built on Tue_Sep_15_19:12:04_Pacific_Daylight_Time_2020
Cuda compilation tools, release 11.1, V11.1.74
Build cuda_11.1.relgpu_drvr455TC455_06.29069683_0
в VisualStudio для Windows, используя в качестве параметров:
compute_70,sm_70;compute_75,sm_75;
Комментарии:
1.
-51
итерация, по-видимому, указывает на то, что вы достигли максимума итерации, а не удовлетворяете условию сходимости. Что касаетсяcuda-memcheck
ошибки, я не смог воспроизвести эту ошибку. Было выпущено несколько версий CUDA 11.1, я использую CUDA 11.1, как указано вnvcc --version
11.1.74 (т.е. CUDA 11.1, а не CUDA 11.1 обновление 1). Это также может быть функцией используемого вами графического процессора, который вы не указали.2. Странно, что такая глупая проблема достигает пределов итерации. Я добавил больше информации о своей настройке в вопрос.
Ответ №1:
Согласно моему тестированию, если вы:
- Обновление до CUDA 11.1 Обновление 1 (чтобы
nvcc --version
отчеты11.1.105
) - Измените
lddx
параметр, чтобы он был равенn
:status = cusolverDnDDgels(handle, m, n, nrhs, dA, lda, dB, ldb, dX, n, //change here and in the buffersize function from ldb to n ...
затем я получаю совпадающие результаты между cusolver и armadillo.
Комментарии:
1. Я действительно работаю для примера выше. Но если я увеличу nrhs, это вернет неверные результаты. Вероятно, также nrhs должен быть частью расчета ldb / ldx.
2. Сообщил о forums.developer.nvidia.com/t /…