CUDA: cuSolver вызывает исключение

Я пытаюсь использовать библиотеку cusolver для решения ряда линейных уравнений, но вместо этого возникает очень странное исключение. код использует только одну функцию из библиотеки, а остальное — выделение памяти и копирование памяти. функция

cusolverSpScsrlsvcholHost(
   cusolverSpHandle_t handle, int m, int nnz,
   const cusparseMatDescr_t descrA, const float *csrVal,
   const int *csrRowPtr, const int *csrColInd, const float *b,
   float tol, int reorder, float *x, int *singularity); 

Я думаю, что моя проблема может быть в параметрах tol-reorder-singularity, так как остальное - это параметры матрицы, вот код:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"
#include <cuda.h>
#include <cusparse.h>
#include <cublas_v2.h>
#include <stdio.h>
#include <cusolverSp.h>

int main()
{
    //initialize our test cases
    const int size = 3;
    int nnz = 6 ;
    int sing = -1 ;

    //float values[] = {0,0,0,0} ;
    float values[] = {1,2,3,4,5,6} ;
    int colIdx[] = {0,0,1,0,1,2};
    int rowPtr[] = {0, 1,3,7};

    float x[] = {4,-6,7};
    float y[3]= {0,0,0} ;

    float *dev_values = 0 ;
    int *dev_rowPtr = 0 ;
    int *dev_colIdx = 0 ;
    float *dev_x = 0 ;
    float *dev_y = 0 ;

    cusolverSpHandle_t solver_handle ;
    cusolverSpCreate(&solver_handle) ;

    cusparseMatDescr_t descr = 0;

    cusparseCreateMatDescr(&descr);
    cusparseSetMatType(descr,CUSPARSE_MATRIX_TYPE_GENERAL);
    cusparseSetMatIndexBase(descr,CUSPARSE_INDEX_BASE_ZERO);

    // Choose which GPU to run on, change this on a multi-GPU system.
    cudaSetDevice(0);

    cudaEvent_t start, stop;
    float time;
    cudaEventCreate(&start);
    cudaEventCreate(&stop);
    cudaEventRecord(start, 0);

    // Allocate GPU buffers for three vectors (two input, one output)    .
    cudaMalloc((void**)&dev_x, size * sizeof(float));
    cudaMalloc((void**)&dev_y, size * sizeof(float));
    cudaMalloc((void**)&dev_values, nnz * sizeof(float));
    cudaMalloc((void**)&dev_rowPtr, (size + 1) * sizeof(int));
    cudaMalloc((void**)&dev_colIdx, nnz * sizeof(int));

    //Memcpy
    cudaMemcpyAsync(dev_x, x, size * sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpyAsync(dev_values, values, nnz * sizeof(float), cudaMemcpyHostToDevice);
    cudaMemcpyAsync(dev_rowPtr, rowPtr, (size + 1) * sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpyAsync(dev_colIdx, colIdx, nnz * sizeof(int), cudaMemcpyHostToDevice);
    cudaMemcpyAsync(dev_y, y, size * sizeof(float), cudaMemcpyHostToDevice);

    cusolverSpScsrlsvluHost(solver_handle, size, nnz, descr, dev_values, dev_rowPtr, dev_colIdx,     dev_y, 0,0, dev_x, &sing);


    cudaMemcpyAsync(y, dev_y, size*sizeof(float), cudaMemcpyDeviceToHost );

    cudaEventRecord(stop, 0);
    cudaEventSynchronize(stop);
    cudaEventElapsedTime(&time, start, stop);
    printf ("Time for the kernel: %f ms\n", time);

    printf("%f\n",y[0]);
    printf("%f\n",y[1]);
    printf("%f\n",y[2]);

    // cudaDeviceReset must be called before exiting in order for profiling and
    // tracing tools such as Nsight and Visual Profiler to show complete traces.

    cudaDeviceReset();
    cudaFree(dev_x);
    cudaFree(dev_y);
    cudaFree(dev_values);
    cudaFree(dev_rowPtr);
    cudaFree(dev_colIdx);
    return 1;
}

person Ehab AlBadawy    schedule 22.11.2015    source источник


Ответы (1)


В вашем коде есть как минимум 3 проблемы:

  1. Вы используете вариант Хост функции: cusolverSpScsrlsvluХост(). Если вы просмотрите документацию для cusolverSpScsrlsvluHost , вы обнаружите, что для Host MemSpace функция ожидает, что все аргументы и аргументы-указатели будут основаны на хосте. Но вы передаете указатели устройств на функцию. Вы получите segfaults, делая это. Для всех аргументов, таких как dev_values, вам нужно будет заменить их эквивалентными указателями данных хоста (например, values вместо dev_values).

  2. Неверное форматирование матрицы CSR. Эта строка:

    int rowPtr[] = {0, 1,3,7};
    

    должно быть так:

    int rowPtr[] = {0, 1,3,6};
    

    Правильный индекс указателя строки, указывающий на один элемент после последнего, равен 6, а не 7, поскольку 6 фактических элементов пронумерованы от 0 до 5. Эта проблема также может привести к segfaults.

  3. Вы передаете y и x неправильно (в обратном порядке) в cusolverSpScsrlsvluHost(). Поскольку вы поместили ненулевые значения в x, по-видимому, вы предполагаете, что это будет ваш вектор RHS. В документации этот вектор имеет имя b, и это первый передаваемый вектор. Тогда ваш вектор y предположительно является вектором решения, и это последний вектор, который нужно передать в порядке аргументов (и в документации он принимает имя x).

  4. Я предлагаю использовать правильную проверку ошибок.

Следующий код решает вышеуказанные проблемы и дает разумный результат:

$ cat t979.cu
#include <cusparse.h>
#include <stdio.h>
#include <cusolverSp.h>
#include <assert.h>

int main()
{
    //initialize our test cases
    const int size = 3;
    const int nnz = 6 ;
    int sing = 0;

    //float values[] = {0,0,0,0} ;
    float values[nnz] = {1,2,3,4,5,6} ;
    int colIdx[nnz] = {0,0,1,0,1,2};
    int rowPtr[size+1] = {0, 1,3,6};

    float x[size] = {4,-6,7};
    float y[size]= {0,0,0} ;
    cusolverStatus_t cso;
    cusolverSpHandle_t solver_handle ;
    cso = cusolverSpCreate(&solver_handle) ;
    assert(cso == CUSOLVER_STATUS_SUCCESS);
    cusparseStatus_t csp;
    cusparseMatDescr_t descr = 0;

    csp = cusparseCreateMatDescr(&descr);
    assert(csp == CUSPARSE_STATUS_SUCCESS);
    csp = cusparseSetMatType(descr,CUSPARSE_MATRIX_TYPE_GENERAL);
    assert(csp == CUSPARSE_STATUS_SUCCESS);
    csp = cusparseSetMatIndexBase(descr,CUSPARSE_INDEX_BASE_ZERO);
    assert(csp == CUSPARSE_STATUS_SUCCESS);
    cso = cusolverSpScsrlsvluHost(solver_handle, size, nnz, descr, values, rowPtr, colIdx, x, 0.0,0, y, &sing);
    assert(cso == CUSOLVER_STATUS_SUCCESS);
    printf("%f\n",y[0]);
    printf("%f\n",y[1]);
    printf("%f\n",y[2]);

    return 0;
}
$ nvcc -o t979 t979.cu -lcusolver -lcusparse
$ ./t979
4.000000
-4.666667
2.388889
$

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

person Robert Crovella    schedule 22.11.2015
comment
Я сделал это изменение и все еще получаю исключение. - person Ehab AlBadawy; 23.11.2015
comment
Форматирование вашей матрицы CSR также неверно. Ваши указатели строк должны быть такими: int rowPtr[] = {0, 1,3,6};. Наконец, у вас есть смысл x и y, перевернутый, когда вы передаете их функции cusolverSpScsrlsvluHost. Я обновил свой ответ, чтобы отразить и эти элементы. - person Robert Crovella; 23.11.2015