| 504 | //sparse matrix wrapper on device: CSC format |
| 505 | template <typename T> |
| 506 | class DeviceSpMatCSC { |
| 507 | public: |
| 508 | size_s gpu_id = 0; |
| 509 | size_s row_size = 0; |
| 510 | size_s col_size = 0; |
| 511 | size_l nnz = 0; |
| 512 | int* col_ptrs = nullptr; |
| 513 | int* row_ids = nullptr; |
| 514 | T* vals = nullptr; |
| 515 | cusparseSpMatDescr_t cusparse_descr = nullptr; |
| 516 | |
| 517 | DeviceSpMatCSC(){} |
| 518 | DeviceSpMatCSC(const size_s gpu_id, const size_s row_size, const size_s col_size, const size_l nnz): |
| 519 | gpu_id(gpu_id), row_size(row_size), col_size(col_size), nnz(nnz), |
| 520 | col_ptrs(nullptr), row_ids(nullptr), vals(nullptr), cusparse_descr(NULL) { |
| 521 | this->allocate(); |
| 522 | } |
| 523 | |
| 524 | inline void allocate() { |
| 525 | if (this->vals == nullptr) { |
| 526 | CHECK_CUDA( cudaSetDevice(this->gpu_id) ); |
| 527 | CHECK_CUDA( cudaMalloc((void**) &this->col_ptrs, sizeof(int) * (this->col_size + 1)) ); |
| 528 | CHECK_CUDA( cudaMalloc((void**) &this->row_ids, sizeof(int) * this->nnz) ); |
| 529 | CHECK_CUDA( cudaMalloc((void**) &this->vals, sizeof(T) * this->nnz) ); |
| 530 | CHECK_CUSPARSE( cusparseCreateCsc( |
| 531 | &this->cusparse_descr, this->row_size, this->col_size, this->nnz, |
| 532 | this->col_ptrs, this->row_ids, this->vals, |
| 533 | CUSPARSE_INDEX_32I, CUSPARSE_INDEX_32I, CUSPARSE_INDEX_BASE_ZERO, CudaTypeMapper<T>::value |
| 534 | ) ); |
| 535 | } |
| 536 | return; |
| 537 | } |
| 538 | |
| 539 | void SynchronizeHostToDevice(int* host_col_ptrs, int* host_row_ids, T* host_val){ |
| 540 | // always Synchronize to avoid read-write conflict |
| 541 | CHECK_CUDA(cudaDeviceSynchronize()); |
| 542 | CHECK_CUDA(cudaMemcpyAsync(col_ptrs, host_col_ptrs, sizeof(int) * (col_size + 1), cudaMemcpyHostToDevice)); |
| 543 | CHECK_CUDA(cudaMemcpyAsync(row_ids, host_row_ids, sizeof(int) * nnz, cudaMemcpyHostToDevice)); |
| 544 | CHECK_CUDA(cudaMemcpyAsync(vals, host_val, sizeof(T) * nnz, cudaMemcpyHostToDevice)); |
| 545 | CHECK_CUDA(cudaDeviceSynchronize()); |
| 546 | } |
| 547 | |
| 548 | inline double get_norm(const DeviceBlasHandle& cublas_H) { |
| 549 | double norm; |
| 550 | CHECK_CUDA( cudaSetDevice(this->gpu_id) ); |
| 551 | CHECK_CUBLAS( cublasDnrm2_v2( |
| 552 | cublas_H.cublas_handle, this->nnz, this->vals, 1, &norm |
| 553 | ) ); |
| 554 | return norm; |
| 555 | } |
| 556 | |
| 557 | ~DeviceSpMatCSC() { |
| 558 | CHECK_CUDA( cudaSetDevice(this->gpu_id) ); |
| 559 | if (this->col_ptrs != nullptr) { |
| 560 | CHECK_CUDA( cudaFree(this->col_ptrs) ); |
| 561 | this->col_ptrs = nullptr; |
| 562 | } |
| 563 | if (this->row_ids != nullptr) { |
nothing calls this directly
no outgoing calls
no test coverage detected