【cuda学习日记】8.1 GPU加速库 --cuSPARSE

8.1.1 cuSPARSE概念

cuSPARSE是一个线性代数库,内含很多通用的稀疏线性代数函数。

稠密存储方式(dense)

把矩阵中的每个元素都存储起来,不管它是否为零。
在这里插入图片描述

坐标稀疏矩阵格式(COO)

坐标稀疏矩阵格式(COO)存储了稀疏矩阵中每个非零元素的行坐标、列坐标及其元素值。因此当通过给定的行列坐标对存储在COO格式中的稀疏矩阵进行检索的时候,如果没有匹配值,那么这个位置的值为零. 只有当矩阵中的非零元素不到1/3时,才会节约存储空间。
在这里插入图片描述

压缩稀疏行方式(CSR)和压缩稀疏列方式(CSC)compressed sparse row/col

参考 : https://blog.youkuaiyun.com/m0_57102661/article/details/140112320

#include <iostream>
#include <cuda_runtime.h>
#include <cusparse.h>

int main() {
    // 初始化稠密矩阵 (4x4)
    const int m = 4; // 行数
    const int n = 4; // 列数
    const int nnz = 9; // 非零元素个数
    double h_A[m * n] = {
        1, 0, 0, 2,
        0, 3, 4, 0,
        5, 0, 6, 0,
        0, 7, 0, 8
    };

    // 打印稠密矩阵
    std::cout << "Dense Matrix:" << std::endl;
    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {
            std::cout << h_A[i * n + j] << " ";
        }
        std::cout << std::endl;
    }

    // 初始化 cuSPARSE
    cusparseHandle_t handle;
    CHECK_CUSPARSE(cusparseCreate(&handle));

    // 分配设备内存并拷贝稠密矩阵到设备
    double *d_A;
    CHECK_CUDA(cudaMalloc((void**)&d_A, m * n * sizeof(double)));
    CHECK_CUDA(cudaMemcpy(d_A, h_A, m * n * sizeof(double), cudaMemcpyHostToDevice));

    // 创建稠密矩阵描述符
    cusparseDnMatDescr_t matA;
    CHECK_CUSPARSE(cusparseCreateDnMat(&matA, m, n, n, d_A, CUDA_R_64F, CUSPARSE_ORDER_ROW));

    // 创建稀疏矩阵描述符 (CSR 格式)
    cusparseSpMatDescr_t matB;
    int *d_csrRowPtr, *d_csrColInd;
    double *d_csrVal;
    CHECK_CUDA(cudaMalloc((void**)&d_csrRowPtr, (m + 1) * sizeof(int)));
    CHECK_CUDA(cudaMalloc((void**)&d_csrColInd, nnz * sizeof(int)));
    CHECK_CUDA(cudaMalloc((void**)&d_csrVal, nnz * sizeof(double)));
    CHECK_CUSPARSE(cusparseCreateCsr(&matB, m, n, nnz, d_csrRowPtr, d_csrColInd, d_csrVal,
                   CUSPARSE_INDEX_32I, CUSPARSE_INDEX_32I, CUSPARSE_INDEX_BASE_ZERO, CUDA_R_64F));

    // 分配缓冲区
    size_t bufferSize = 0;
    CHECK_CUSPARSE(cusparseDenseToSparse_bufferSize(handle, matA, matB, CUSPARSE_DENSETOSPARSE_ALG_DEFAULT, &bufferSize));
    void *d_buffer;
    CHECK_CUDA(cudaMalloc(&d_buffer, bufferSize));

    // 执行稠密矩阵转稀疏矩阵
    CHECK_CUSPARSE(cusparseDenseToSparse_analysis(handle, matA, matB, CUSPARSE_DENSETOSPARSE_ALG_DEFAULT, d_buffer));
    CHECK_CUSPARSE(cusparseDenseToSparse_convert(handle, matA, matB, CUSPARSE_DENSETOSPARSE_ALG_DEFAULT, d_buffer));

    // 将结果拷贝回主机
    int h_csrRowPtr[m + 1];
    int h_csrColInd[nnz];
    double h_csrVal[nnz];
    CHECK_CUDA(cudaMemcpy(h_csrRowPtr, d_csrRowPtr, (m + 1) * sizeof(int), cudaMemcpyDeviceToHost));
    CHECK_CUDA(cudaMemcpy(h_csrColInd, d_csrColInd, nnz * sizeof(int), cudaMemcpyDeviceToHost));
    CHECK_CUDA(cudaMemcpy(h_csrVal, d_csrVal, nnz * sizeof(double), cudaMemcpyDeviceToHost));

    // 打印 CSR 格式的结果
    std::cout << "\nCSR RowPtr:" << std::endl;
    for (int i = 0; i <= m; i++) {
        std::cout << h_csrRowPtr[i] << " ";
    }
    std::cout << std::endl;

    std::cout << "CSR ColInd:" << std::endl;
    for (int i = 0; i < nnz; i++) {
        std::cout << h_csrColInd[i] << " ";
    }
    std::cout << std::endl;

    std::cout << "CSR Val:" << std::endl;
    for (int i = 0; i < nnz; i++) {
        std::cout << h_csrVal[i] << " ";
    }
    std::cout << std::endl;

    // 释放设备内存
    CHECK_CUDA(cudaFree(d_A));
    CHECK_CUDA(cudaFree(d_csrRowPtr));
    CHECK_CUDA(cudaFree(d_csrColInd));
    CHECK_CUDA(cudaFree(d_csrVal));
    CHECK_CUDA(cudaFree(d_buffer));

    // 销毁描述符和句柄
    CHECK_CUSPARSE(cusparseDestroyDnMat(matA));
    CHECK_CUSPARSE(cusparseDestroySpMat(matB));
    CHECK_CUSPARSE(cusparseDestroy(handle));

    return 0;
}

在common.h里添加

```c
// 检查 CUDA 错误
#define CHECK_CUDA(func)                                                       \
{                                                                              \
    cudaError_t status = (func);                                               \
    if (status != cudaSuccess) {                                               \
        std::cerr << "CUDA Error: " << cudaGetErrorString(status) << std::endl; \
        exit(EXIT_FAILURE);                                                    \
    }                                                                          \
}

// 检查 cuSPARSE 错误
#define CHECK_CUSPARSE(func)                                                   \
{                                                                              \
    cusparseStatus_t status = (func);                                          \
    if (status != CUSPARSE_STATUS_SUCCESS) {                                   \
        std::cerr << "cuSPARSE Error: " << status << std::endl;                \
        exit(EXIT_FAILURE);                                                    \
    }                                                                          \
}
编译: nvcc -o dense2csr cusparse.cu -lcusparse
输出:

```c
Dense Matrix:
1 0 0 2 
0 3 4 0 
5 0 6 0 
0 7 0 8 

CSR RowPtr:
0 2 4 6 8 
CSR ColInd:
0 3 1 2 0 2 1 3 0 
CSR Val:
1 2 3 4 5 6 7 8 0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值