Похоже, что вы нашли проход C по ссылке идиома самостоятельно, и это прекрасно сработает для того, что вам, кажется, нужно сделать. Гораздо более элегантный и логичный способ сделать то же самое - определить структуру, содержащую указатели, которые вы выделяете в своей функции, и заставить функцию возвращать структуру по значению.
Таким образом, ваш код может быть изменен следующим образом:
#include <cusparse.h>
#include <cuda_runtime_api.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
cuComplex *csrVal;
int *csrRowPtr;
int *csrColInd;
} csr_struct;
csr_struct dense2Csr (int dim, cuComplex *dnMatr)
{
cusparseHandle_t cusparseH = NULL; // residual evaluation
cudaStream_t stream = NULL;
cusparseMatDescr_t descrA = NULL; // A is a base-0 general matrix
cusparseStatus_t cudaStat1 = CUSPARSE_STATUS_SUCCESS;
int nnZ;
//Input GPU Copy
cuComplex *d_dnMatr;
int *d_nnzRow;
//Output GPU Copy
cuComplex *d_csrVal;
int *d_csrRowPtr;
int *d_csrColInd;
// return value
csr_struct mat;
cusparseCreate(&cusparseH); //Create SparseStructure
cudaStreamCreate(&stream);
cusparseSetStream(cusparseH, stream);
cusparseCreateMatDescr(&descrA);
cusparseSetMatType(descrA, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatIndexBase(descrA, CUSPARSE_INDEX_BASE_ZERO); //Set First Element RowPtr eq. to zero
cudaMalloc((void **)&d_dnMatr , sizeof(cuComplex)*dim*dim);
cudaMalloc((void **)&d_nnzRow , sizeof(int)*dim);
cudaMemcpy(d_dnMatr , dnMatr , sizeof(cuComplex)*dim*dim , cudaMemcpyHostToDevice);
cusparseCnnz(cusparseH,
CUSPARSE_DIRECTION_ROW,
dim, dim, descrA, d_dnMatr, dim,
d_nnzRow, &nnZ);
cudaMalloc((void **)&d_csrRowPtr , sizeof(int)*(dim+1));
cudaMalloc((void **)&d_csrColInd , sizeof(int)*nnZ);
cudaMalloc((void **)&d_csrVal , sizeof(cuComplex)*nnZ);
cudaStat1 = cusparseCdense2csr(cusparseH,
dim, dim, descrA, d_dnMatr, dim, d_nnzRow,
d_csrVal, d_csrRowPtr, d_csrColInd);
assert(cudaStat1 == CUSPARSE_STATUS_SUCCESS);
cudaMallocHost((void **)&mat.csrRowPtr , sizeof(int)*(dim+1));
cudaMallocHost((void **)&mat.csrColInd , sizeof(int)*nnZ);
cudaMallocHost((void **)&mat.csrVal , sizeof(cuComplex)*nnZ);
cudaMemcpy(mat.csrVal, d_csrVal, sizeof(cuComplex)*nnZ, cudaMemcpyDeviceToHost);
cudaMemcpy(mat.csrRowPtr, d_csrRowPtr, sizeof(int)*(dim+1), cudaMemcpyDeviceToHost);
cudaMemcpy(mat.csrColInd, d_csrColInd, sizeof(int)*(nnZ), cudaMemcpyDeviceToHost);
if (d_csrVal) cudaFree(d_csrVal);
if (d_csrRowPtr) cudaFree(d_csrRowPtr);
if (d_csrColInd) cudaFree(d_csrColInd);
if (cusparseH ) cusparseDestroy(cusparseH);
if (stream ) cudaStreamDestroy(stream);
return mat;
}
int main()
{
const int dim = 1024;
const size_t sz = sizeof(cuComplex) * dim * dim;
cuComplex* dmat = malloc(sz);
memset(dmat, 0, sz);
const cuComplex ten_plus_nine_i = { 10.0, 9.0 };
for(int i=0; i<dim; i++)
dmat[i * (dim + 1)] = ten_plus_nine_i;
csr_struct smat = dense2Csr(dim, dmat);
for(int j=0; j<10; j++) {
cuComplex x = smat.csrVal[j];
printf("%d %d %f + %f i\n", smat.csrColInd[j], smat.csrRowPtr[j], x.x, x.y);
}
return 0;
}
, который, кажется, работает правильно (обратите внимание, что в этом примере требуется компилятор, совместимый с C99, даже если код возврата структуры не работает):
$ nvcc -Xcompiler="-std=c99" -o intialainen intialainen.c -lcudart -lcusparse
cc1plus: warning: command line option -std=c99 is valid for C/ObjC but not for C++ [enabled by default]
$ ./intialainen
0 0 10.000000 + 9.000000 i
1 1 10.000000 + 9.000000 i
2 2 10.000000 + 9.000000 i
3 3 10.000000 + 9.000000 i
4 4 10.000000 + 9.000000 i
5 5 10.000000 + 9.000000 i
6 6 10.000000 + 9.000000 i
7 7 10.000000 + 9.000000 i
8 8 10.000000 + 9.000000 i
9 9 10.000000 + 9.000000 i
или напрямую используя gcc:
$ gcc -std=c99 -o intialainen intialainen.c -I /opt/cuda-9.0/include -L /opt/cuda-9.0/lib64 -lcudart -lcusparse -lcuda
$ ./intialainen
0 0 10.000000 + 9.000000 i
1 1 10.000000 + 9.000000 i
2 2 10.000000 + 9.000000 i
3 3 10.000000 + 9.000000 i
4 4 10.000000 + 9.000000 i
5 5 10.000000 + 9.000000 i
6 6 10.000000 + 9.000000 i
7 7 10.000000 + 9.000000 i
8 8 10.000000 + 9.000000 i
9 9 10.000000 + 9.000000 i
Вызов функции csr_struct smat = dense2Csr(dim, dmat)
проще и понятнее, чем что-то вроде dense2Csr(dim, dmat, &p1, &p2, &p2)
, что может быть альтернативой, хотя это исключительно вопрос вкуса.