cuSPARSE

cuSPARSE(CUDA稀疏矩阵库)的API参考指南。

1. 简介

cuSPARSE库包含一组GPU加速的基础线性代数子程序,用于处理稀疏矩阵,其性能显著优于仅使用CPU的替代方案。根据具体操作的不同,该库针对稀疏度在70%至99.9%范围内的矩阵进行了优化。 该库基于NVIDIA® CUDA™运行时(属于CUDA工具包的一部分)实现,并设计为可通过C和C++调用。

另请参阅 cuSPARSELt: 用于稀疏矩阵乘法的高性能CUDA库

cuSPARSE 版本说明: cuda-toolkit-release-notes

cuSPARSE GitHub示例: CUDALibrarySamples

Nvidia开发者论坛: GPU加速库

提供反馈: Math-Libs-Feedback@nvidia.com

近期cuSPARSE/cuSPARSELt博客文章与GTC演讲

该库例程提供以下功能:

  • 稀疏向量稠密向量之间的操作:求和、点积、分散、聚集

  • 稠密矩阵稀疏向量之间的运算:乘法

  • 稀疏矩阵稠密向量之间的运算:乘法、三角求解器、三对角求解器、五对角求解器

  • 稀疏矩阵稠密矩阵之间的运算:乘法、三角求解器、三对角求解器、五对角求解器

  • 稀疏矩阵稀疏矩阵之间的运算:求和、乘法

  • 稠密矩阵之间的运算,输出结果为稀疏矩阵:乘法

  • 稀疏矩阵预处理器: 不完全Cholesky分解(级别0), 不完全LU分解(级别0)

  • 在不同稀疏矩阵存储格式之间进行重新排序和转换操作


1.1. 库组织结构与特性

cuSPARSE库分为两组API:

  • 传统API受到稀疏BLAS标准的启发,提供了一套有限的功能集,并且在未来的版本中不会进行改进,尽管仍会确保标准维护。这一类别中的某些例程可能会在短期内被弃用并移除。在弃用过程中,将为其中最重要的功能提供替代方案。

  • 通用API提供了cuSPARSE的标准接口层。它们允许以灵活的方式计算最常见的稀疏线性代数运算,例如稀疏矩阵-向量乘法(SpMV)和稀疏矩阵-矩阵乘法(SpMM)。新API具有以下功能和特点:

    • 设置矩阵数据的布局批次数量和存储格式(例如CSR、COO等)。

    • 设置输入/输出/计算数据类型。这也支持混合数据类型计算

    • 设置稀疏向量/矩阵索引的类型(例如32位、64位)。

    • 选择用于计算的算法

    • 为内部操作确保外部设备内存。

    • 提供对输入矩阵和向量的全面一致性检查。这包括验证大小、数据类型、布局、允许的操作等。

    • 为向量和矩阵输入提供常量描述符,以支持常量安全接口,并确保API不会修改其输入。


1.2. 静态库支持

从CUDA 6.5开始,cuSPARSE库在Linux平台上还以静态形式提供,文件名为libcusparse_static.a

例如,要使用cuSPARSE针对动态库编译一个小型应用程序,可以使用以下命令:

nvcc my_cusparse_app.cu  -lcusparse  -o my_cusparse_app

而要针对静态库进行编译,则必须使用以下命令:

nvcc my_cusparse_app.cu  -lcusparse_static -o my_cusparse_app

也可以使用原生Host C++编译器。根据主机操作系统的不同,在链接行可能需要一些额外的库,如pthreaddl。在Linux上建议使用以下命令:

gcc my_cusparse_app.c -lcusparse_static -lcudart_static -lpthread -ldl -I <cuda-toolkit-path>/include -L <cuda-toolkit-path>/lib64 -o my_cusparse_app

请注意,在后一种情况下,不需要cuda库。CUDA运行时会根据需要尝试显式打开cuda库。对于未安装CUDA驱动的系统,这允许应用程序优雅地处理此问题,并在仅支持CPU路径的情况下仍可能运行。


1.3. 库依赖项

从CUDA 12.0开始,cuSPARSE将依赖nvJitLink库来实现JIT(即时)LTO(链接时优化)功能;更多信息请参阅cusparseSpMMOp() API。

如果用户链接到动态库,运行时加载库的环境变量(例如Linux上的LD_LIBRARY_PATH和Windows上的PATH)必须包含libnvjitlink.so所在的路径。如果它与cuSPARSE位于同一目录,则用户无需采取任何操作。

如果链接到静态库,用户需要链接-lnvjitlink并相应设置编译时加载库的环境变量LIBRARY_PATH/PATH



2. 使用cuSPARSE API

本章介绍如何使用cuSPARSE库API。它并非cuSPARSE API数据类型和函数的参考文档,这些内容将在后续章节中提供。

2.1. API使用说明

cuSPARSE库使开发者能够访问NVIDIA图形处理单元(GPU)的计算资源。

  • cuSPARSE API 假设输入和输出数据(向量和矩阵)驻留在 GPU(设备)内存中

  • 输入和输出的标量(例如\(\alpha\)\(\beta\))可以通过主机或设备上的引用传递,而不仅限于在主机上通过值传递。这使得库函数即使由先前内核生成也能使用流异步执行,从而实现最大并行度。

  • 通过函数初始化cuSPARSE库上下文的句柄,并显式传递给后续所有库函数调用。这使得用户在使用多主机线程和多GPU时能更好地控制库的设置。

  • 所有cuSPARSE库函数调用都会返回错误状态cusparseStatus_t

开发者的职责是使用标准CUDA运行时API例程(如cudaMalloc()cudaFree()cudaMemcpy()cudaMemcpyAsync())分配内存并在GPU内存与CPU内存之间复制数据。

cuSPARSE库函数相对于主机是异步执行的,可能在结果准备好之前就将控制权返回给主机应用程序。开发人员可以使用cudaDeviceSynchronize()函数来确保特定cuSPARSE库例程的执行已完成。

开发者也可以使用cudaMemcpy()例程,通过分别指定cudaMemcpyDeviceToHostcudaMemcpyHostToDevice参数,将数据从设备复制到主机或反之。在这种情况下,无需额外调用cudaDeviceSynchronize(),因为使用上述参数的cudaMemcpy()调用是阻塞式的,只有当结果在主机端准备就绪时才会完成。


2.2. 已弃用的API

cuSPARSE库文档明确标注了已弃用的API/枚举器/数据结构集合。对于已弃用的API,该库遵循以下策略:

  1. API在X.Y版本(例如11.2)上被标记为[[DEPRECATED]]

    • 如果有可用的替代方案,文档会进行索引

    • 否则,该功能在未来将不会被维护

  2. 该API将在X+1.0版本(例如12.0)中被移除

即使对于已弃用的API,仍会修复正确性错误,但性能问题并不总能得到保证。

除了文档说明外,当使用已弃用的API时,在大多数平台上会生成编译时警告。可以通过在包含cusparse.h之前定义宏DISABLE_CUSPARSE_DEPRECATED,或者向编译器传递标志-DDISABLE_CUSPARSE_DEPRECATED来禁用弃用警告。

2.3. 线程安全

该库是线程安全的。 只要它所使用的数据没有同时被其他线程写入,就可以在任何线程中随时安全地调用任何函数。 cuSPARSE函数是否写入对象通常通过const参数来指示。

不建议在多个线程之间共享同一个cuSPARSE句柄。 虽然可以这样做,但对句柄的更改 (例如设置流销毁) 会影响所有线程并引发全局同步问题。


2.4. 结果可复现性

cuSPARSE的设计优先考虑性能而非逐位可重现性。

使用转置或共轭转置的操作 cusparseOperation_t 无法保证可重现性。

对于剩余的操作, 在同一台机器上使用相同的可执行文件,以完全相同的参数执行两次相同的API调用, 将产生位级完全相同的结果。 这种位级可重现性可能会受到以下变化的影响: 硬件、CUDA驱动程序、cuSPARSE版本、数据的内存对齐方式或算法选择。


2.5. NaN与Inf传播

浮点数有特殊的NaN(非数字)和Inf(无穷大)值。cuSPARSE中的函数不保证NaN和Inf的传播行为。

cuSPARSE算法在评估时假设所有浮点数值均为有限值。只有当算法恰好生成或传播NaN和Inf时,它们才会出现在输出结果中。由于算法可能根据工具包版本和运行时考量进行调整,因此NaN和Inf的传播行为也可能随之变化。

NaN传播在cuSPARSE中与典型的密集数值线性代数(如cuBLAS)有所不同。 向量[0, 1, 0][1, 1, NaN]的点积 在使用典型密集数值算法时为NaN, 但在典型稀疏数值算法中会是1.0。


2.6. 使用流实现并行计算

如果应用程序执行多个小型独立计算,或者在计算过程中并行传输数据,可以使用CUDA流来重叠这些任务。

The application can conceptually associate a stream with each task. To achieve the overlap of computation between the tasks, the developer should create CUDA streams using the function cudaStreamCreate() and set the stream to be used by each individual cuSPARSE library routine by calling cusparseSetStream() just before calling the actual cuSPARSE routine. Then, computations performed in separate streams would be overlapped automatically on the GPU, when possible. This approach is especially useful when the computation performed by a single task is relatively small and is not enough to fill the GPU with work, or when there is a data transfer that can be performed in parallel with the computation.

当使用流时,我们建议采用新的cuSPARSE API,通过设备内存中的引用传递标量参数和结果,以实现最大的计算重叠。

虽然开发者可以创建多个流,但实际上同时执行的并发内核数量不可能超过16个。


2.7. 兼容性与版本控制

cuSPARSE API旨在保持与未来版本的源代码级向后兼容性(除非特定未来版本的发布说明中另有说明)。换句话说,如果程序使用了cuSPARSE,它应该能在不修改源代码的情况下继续编译并正确运行于新版本的cuSPARSE。但cuSPARSE不保证二进制级别的向后兼容性。不支持混用不同版本的cusparse.h头文件和共享库。也不支持混用不同版本的cuSPARSE和CUDA运行时。


该库采用标准的版本语义约定来标识不同发布版本。

版本号由四个字段组成,以点号连接:MAJOR.MINOR.PATCH.BUILD

这些版本字段根据以下规则递增:

  • MAJOR: API重大变更或新CUDA主版本(底层破坏性变更,如驱动程序、编译器、库等)

  • MINOR: 新增API和功能

  • PATCH: 错误修复或性能改进(或 * 新CUDA版本)

  • BUILD: 内部构建编号

* 不同版本的CUDA工具包会确保库版本号不同,即使库本身没有发生变化。


2.8. 优化说明

大多数cuSPARSE例程可以通过利用CUDA Graphs捕获硬件内存压缩特性进行优化。

更详细地说,单个cuSPARSE调用或一系列调用可以被CUDA Graph捕获并在稍后执行。这最大限度地减少了内核启动开销,并允许CUDA运行时优化整个工作流程。关于将CUDA图捕获应用于cuSPARSE例程的完整示例,请参阅cuSPARSE Library Samples - CUDA Graph

其次,cuSPARSE涉及的数据类型和功能适用于安培架构GPU设备(计算能力8.0及以上)提供的硬件内存压缩技术。该特性允许对含有足够多零字节的数据进行无损内存压缩。设备内存必须通过CUDA驱动API进行分配。关于硬件内存压缩在cuSPARSE例程中的应用完整示例,可参阅cuSPARSE库示例 - 内存压缩



3. cuSPARSE存储格式

cuSPARSE库支持稠密和稀疏向量,以及稠密和稀疏矩阵格式。

3.1. 索引基础

该库支持从0开始和从1开始的索引方式,分别确保与C/C++和Fortran语言的兼容性。索引基准通过cusparseIndexBase_t类型进行选择。


3.2. 向量格式

本节介绍密集和稀疏向量格式。

3.2.1. 稠密向量格式

稠密向量通过存储在内存中的单个线性数据数组表示,例如下面的\(7 \times 1\)稠密向量。

_images/dense_vector.png

密集向量表示


3.2.2. 稀疏向量格式

稀疏向量用两个数组表示。

  • values数组存储了密集格式等效数组中的非零值。

  • indices数组表示对应的非零值在密集格式等效数组中的位置。

例如,3.2.1节中的密集向量可以存储为使用从零开始或从一开始索引的稀疏向量。

_images/sparse_vector.png

稀疏向量表示

注意

cuSPARSE例程假设索引是按递增顺序提供的,并且每个索引仅出现一次。在相反的情况下,计算的正确性并不总是能得到保证。


3.3. 矩阵格式

本节将讨论矩阵的密集格式和几种稀疏格式。

3.3.1. 稠密矩阵格式

密集矩阵可以存储在行优先列优先的内存布局(排序)中,它由以下参数表示。

  • 矩阵中的行数

  • 矩阵中的列数

  • 主维度必须满足

    • 大于或等于行优先布局中的列数

    • 大于或等于列优先布局中的行数

  • 指向长度为数组的指针

    • \(rows \times leading\; dimension\)行优先布局中

    • \(columns \times leading\; dimension\)列优先布局中

下图展示了一个\(5 \times 2\)密集矩阵的两种内存布局方式

_images/dense_matrix.png

稠密矩阵表示

矩阵中的索引表示内存中的连续位置。

前导维度有助于表示原始矩阵中的一个子矩阵

_images/sub_matrix.png

子矩阵表示


3.3.2. 坐标格式 (COO)

COO格式存储的稀疏矩阵由以下参数表示。

  • 矩阵中的行数

  • 矩阵中的列数

  • 矩阵中的非零元素数量 (nnz)。

  • 指向长度为nnz行索引数组的指针,该数组包含值数组中对应元素的行索引。

  • 指向长度为nnz列索引数组的指针,该数组包含值数组中对应元素的列索引。

  • 指向长度为nnz数组的指针,该数组以行优先顺序存储矩阵的所有非零值。

  • COO表示法中的每个条目由一个<行, 列>对组成。

  • COO格式假定为按行排序。

以下示例展示了一个以COO格式表示的\(5 \times 4\)矩阵。

_images/coo.png
_images/coo_one_base.png

注意

cuSPARSE支持给定行内已排序未排序的列索引。

注意

如果给定行中的列索引不唯一,则无法始终保证计算的正确性。

给定一个COO格式(基于零)的条目,对应的密集矩阵位置计算如下:

// row-major
rows_indices[i] * leading_dimension + column_indices[i]

// column-major
column_indices[i] * leading_dimension + rows_indices[i]

3.3.3. 压缩稀疏行(CSR)

CSR格式与COO类似,其中行索引被压缩并替换为一个偏移量数组。

以CSR格式存储的稀疏矩阵由以下参数表示。

  • 矩阵中的行数

  • 矩阵中的列数

  • 矩阵中的非零元素数量 (nnz)。

  • 指向长度为行数 + 1行偏移量数组的指针,该数组表示每行在列和值数组中的起始位置。

  • 指向长度为nnz列索引数组的指针,该数组包含值数组中对应元素的列索引。

  • 指向长度为nnz数组的指针,该数组以行优先顺序存储矩阵的所有非零值。

以下示例展示了一个以CSR格式表示的\(5 \times 4\)矩阵。

_images/csr.png
_images/csr_one_base.png

注意

cuSPARSE支持给定行内已排序未排序的列索引。

注意

如果给定中的列索引不唯一,则无法始终保证计算的正确性。

给定CSR格式(基于零)中的一个条目,其在稠密矩阵中的对应位置计算如下:

// row-major
row * leading_dimension + column_indices[row_offsets[row] + k]

// column-major
column_indices[row_offsets[row] + k] * leading_dimension + row

3.3.4. 压缩稀疏列(CSC)

CSC格式与COO类似,其中列索引被压缩并替换为一个偏移量数组。

以CSC格式存储的稀疏矩阵由以下参数表示。

  • 矩阵中的行数

  • 矩阵中的列数

  • 矩阵中的非零元素数量 (nnz)。

  • 指向长度为列数 + 1列偏移量数组的指针,该数组表示每列在列和值数组中的起始位置。

  • 指向长度为nnz行索引数组的指针,该数组包含值数组中对应元素的行索引。

  • 指向长度为nnzvalues数组的指针,该数组以列主序存储矩阵的所有非零值。

以下示例展示了一个以CSC格式表示的\(5 \times 4\)矩阵。

_images/csc.png
_images/csc_one_base.png

注意

CSR格式的内存布局与其在CSC格式中的转置完全相同(反之亦然)。

注意

cuSPARSE支持在给定列内使用已排序未排序的行索引。

注意

如果给定中的行索引不唯一,则无法始终保证计算的正确性。

给定CSC格式(基于零索引)中的一个条目,其在稠密矩阵中的对应位置计算如下:

// row-major
column * leading_dimension + row_indices[column_offsets[column] + k]

// column-major
row_indices[column_offsets[column] + k] * leading_dimension + column

3.3.5. 切片式Ellpack (SELL)

Sliced Ellpack格式是一种标准化且广为人知的先进技术。该格式能显著提升所有涉及每行非零元素数量变化较小问题的性能。

在Sliced Ellpack格式中,矩阵被划分为由用户定义的精确行数\(sliceSize\))组成的切片。 每个切片会计算其最大行长度(即每行非零元素的最大数量),并将切片中的每一行填充至该最大长度。 填充时使用值-1

一个\(m \times n\)的稀疏矩阵\(A\)等价于一个具有\(nslices = \left \lceil{\frac{m}{sliceSize}}\right \rceil\)切片行和\(n\)列的切片稀疏矩阵\(A_{s}\)。为了提高内存合并和内存利用率,每个切片以列优先顺序存储。

以SELL格式存储的稀疏矩阵由以下参数表示。

  • 切片数量

  • 矩阵中的行数

  • 矩阵中的列数

  • 矩阵中的非零元素数量 (nnz)。

  • 元素总数 (sellValuesSize),包括非零值和填充元素。

  • 指向长度为\(nslices + 1\)切片偏移量的指针,该偏移量保存与列和值数组对应的切片的偏移量。

  • 指向长度为sellValuesSize列索引数组的指针,该数组包含values数组中对应元素的列索引。列索引以列优先方式存储。值-1表示填充。

  • 指向长度为sellValuesSizevalues数组的指针,该数组以列优先布局保存所有非零值和填充。

以下示例展示了一个以SELL格式表示的\(5 \times 4\)矩阵。

_images/sell.png
_images/sell_one_base.png

3.3.6. 块稀疏行(BSR)

BSR格式与CSR类似,其中列索引表示的是二维块而非单个矩阵元素。

Block Sparse Row格式的矩阵被组织成由用户定义的大小为\(blockSize\)的块。

一个\(m \times n\)的稀疏矩阵\(A\)等价于一个块稀疏矩阵\(A_{B}\)\(mb \times nb\),其中\(mb = \frac{m}{blockSize}\)块行\(nb = \frac{n}{blockSize}\)块列。 如果\(m\)\(n\)不是\(blockSize\)的倍数,用户需要用零填充矩阵。

注意

cuSPARSE目前仅支持方形块。

BSR格式以行优先顺序存储块。然而,块的内部存储格式可以是列优先cusparseDirection_t=CUSPARSE_DIRECTION_COLUMN)或行优先cusparseDirection_t=CUSPARSE_DIRECTION_ROW),与基索引无关。

以BSR格式存储的稀疏矩阵由以下参数表示。

  • 块大小

  • 矩阵中的行块数量

  • 矩阵中的列块数量

  • 矩阵中的非零块数量 (nnzb)。

  • 指向长度为行块数 + 1行块偏移数组的指针,该数组表示每个行块在列和值数组中的起始位置。

  • 指向长度为nnzb列块索引数组的指针,该数组包含值数组中对应元素的位置。

  • 指向长度为nnzb值数组的指针,该数组保存矩阵的所有非零值。

以下示例展示了一个以BSR格式表示的\(4 \times 7\)矩阵。

_images/bsr.png
_images/bsr_one_base.png

3.3.7. 分块Ellpack格式(BLOCKED-ELL)

Blocked Ellpack格式与标准Ellpack类似,其中列索引表示的是二维块而非单个矩阵条目。

Blocked Ellpack格式的矩阵被组织成由用户定义的大小为\(blockSize\)的块。每行的列数\(nEllCols\)也由用户定义(\(nEllCols \le n\))。

一个\(m \times n\)的稀疏矩阵\(A\)等价于一个分块ELL矩阵\(A_{B}\):具有\(mb = \left \lceil{\frac{m}{blockSize}}\right \rceil\)块行\(nb = \left \lceil{\frac{nEllCols}{blockSize}}\right \rceil\)个块列的\(mb \times nb\)矩阵。 如果\(m\)\(n\)不是\(blockSize\)的倍数,则剩余元素为零。

以Blocked-ELL格式存储的稀疏矩阵由以下参数表示。

  • 块大小

  • 矩阵中的行数

  • 矩阵中的列数

  • 矩阵中每行的列数 (nEllCols)。

  • 指向长度为\(mb \times nb\)列块索引数组的指针,该数组包含值数组中对应元素的位置。空块可以用-1索引表示。

  • 指向长度为\(m \times nEllCols\)值数组的指针,该数组以行优先顺序存储矩阵的所有非零值。

以下示例展示了一个以Blocked-ELL格式表示的\(9 \times 9\)矩阵。

_images/blockedell.png
_images/blockedell_one_base.png

3.3.8. 扩展BSR格式(BSRX) [已弃用]

BSRX格式与BSR格式类似,但数组bsrRowPtrA被分为两部分。每行的第一个非零块仍由数组bsrRowPtrA指定(与BSR格式相同),但每行最后一个非零块的下一个位置由数组bsrEndPtrA指定。简而言之,BSRX格式就像是BSR格式的四向量变体。

矩阵 A 通过以下参数以BSRX格式表示。

blockDim

(整数)

矩阵A的块维度。

mb

(整数)

A的块行数。

nb

(整数)

A的块列数。

nnzb

(整数)

矩阵 A 中非零块的数量。

bsrValA

(指针)

指向长度为\(nnzb \ast blockDim^{2}\)的数据数组,该数组保存了A所有非零块元素。块元素按列优先顺序或行优先顺序存储。

bsrRowPtrA

(指针)

指向长度为mb的整数数组,该数组保存指向bsrColIndAbsrValA数组的索引;bsrRowPtrA(i)表示第i个块行在bsrColIndAbsrValA中第一个非零块的位置。

bsrEndPtrA

(指针)

指向长度为mb的整型数组,该数组保存指向bsrColIndAbsrValA数组的索引;bsrRowPtrA(i)表示第i个块行在bsrColIndAbsrValA中最后一个非零块之后的位置。

bsrColIndA

(指针)

指向长度为nnzb的整型数组,该数组包含bsrValA数组中对应块的列索引。

BSR和BSRX之间的简单转换可以按如下方式进行。假设开发者有一个\(2 \times 3\)块稀疏矩阵\(A_{b}\),其表示形式如下所示。

\[\begin{split}A_{b} = \begin{bmatrix} A_{00} & A_{01} & A_{02} \\ A_{10} & A_{11} & A_{12} \\ \end{bmatrix}\end{split}\]

假设它具有以下BSR格式:

\[\begin{split}\begin{matrix} \text{bsrValA of BSR} & = & \begin{bmatrix} A_{00} & A_{01} & A_{10} & A_{11} & A_{12} \\ \end{bmatrix} \\ \text{bsrRowPtrA of BSR} & = & \begin{bmatrix} {0\phantom{.0}} & {2\phantom{.0}} & 5 \\ \end{bmatrix} \\ \text{bsrColIndA of BSR} & = & \begin{bmatrix} {0\phantom{.0}} & {1\phantom{.0}} & {0\phantom{.0}} & {1\phantom{.0}} & 2 \\ \end{bmatrix} \\ \end{matrix}\end{split}\]

BSRX格式中的bsrRowPtrA就是BSR格式bsrRowPtrA的前两个元素。而BSRX格式的bsrEndPtrA则是BSR格式bsrRowPtrA的最后两个元素。

\[\begin{split}\begin{matrix} \text{BSRX的bsrRowPtrA} & = & \begin{bmatrix} {0\phantom{.0}} & 2 \\ \end{bmatrix} \\ \text{BSRX的bsrEndPtrA} & = & \begin{bmatrix} {2\phantom{.0}} & 5 \\ \end{bmatrix} \\ \end{matrix}\end{split}\]

BSRX格式的优势在于,开发者可以通过修改bsrRowPtrAbsrEndPtrA来指定原始BSR格式中的子矩阵,同时保持bsrColIndAbsrValA不变。

例如,要创建一个与\(A\)略有不同的块矩阵\(\widetilde{A} = \begin{bmatrix} O & O & O \\ O & A_{11} & O \\ \end{bmatrix}\),开发者可以保留bsrColIndAbsrValA,但通过正确设置bsrRowPtrAbsrEndPtrA来重构\(\widetilde{A}\)。以下4维向量描述了\(\widetilde{A}\)

\[\begin{split}\begin{matrix} {\text{bsrValA of }\widetilde{A}} & = & \begin{bmatrix} A_{00} & A_{01} & A_{10} & A_{11} & A_{12} \\ \end{bmatrix} \\ {\text{bsrColIndA of }\widetilde{A}} & = & \begin{bmatrix} {0\phantom{.0}} & {1\phantom{.0}} & {0\phantom{.0}} & {1\phantom{.0}} & 2 \\ \end{bmatrix} \\ {\text{bsrRowPtrA of }\widetilde{A}} & = & \begin{bmatrix} {0\phantom{.0}} & 3 \\ \end{bmatrix} \\ {\text{bsrEndPtrA of }\widetilde{A}} & = & \begin{bmatrix} {0\phantom{.0}} & 4 \\ \end{bmatrix} \\ \end{matrix}\end{split}\]


4. cuSPARSE基础API

4.1. cuSPARSE 类型参考

4.1.1. cuda数据类型_t

本节描述了多个CUDA库共享的类型,这些类型定义在头文件library_types.h中。cudaDataType类型是一个枚举器,用于指定数据精度。当数据引用本身不携带类型时(例如void*)会使用它。例如,该类型在例程cusparseSpMM()中被使用。

含义

数据类型

头信息

CUDA_R_16F

数据类型为16位IEEE-754浮点数

__half

cuda_fp16.h

CUDA_C_16F

数据类型为16位复数IEEE-754浮点数

__half2

cuda_fp16.h

[已弃用]

CUDA_R_16BF

数据类型为16位bfloat浮点数

__nv_bfloat16

cuda_bf16.h

CUDA_C_16BF

数据类型为16位复数bfloat浮点数

__nv_bfloat162

cuda_bf16.h

[已弃用]

CUDA_R_32F

数据类型为32位IEEE-754浮点数

float

CUDA_C_32F

数据类型为32位复数IEEE-754浮点数

cuComplex

cuComplex.h

CUDA_R_64F

该数据类型为64位IEEE-754浮点数

double

CUDA_C_64F

数据类型为64位复数IEEE-754浮点数

cuDoubleComplex

cuComplex.h

CUDA_R_8I

数据类型为8位整数

int8_t

stdint.h

CUDA_R_32I

数据类型为32位整数

int32_t

stdint.h

重要提示:通用API例程仅支持在具有原生支持的GPU架构上使用文档相应章节中列出的所有数据类型。如果特定GPU型号未提供对给定数据类型的原生支持,该例程将返回CUSPARSE_STATUS_ARCH_MISMATCH错误。

不支持的数据类型和计算能力(CC):

  • __half 在计算能力 CC < 53 的GPU上(例如Kepler架构)

  • __nv_bfloat16 在计算能力 CC < 80 的GPU上(例如Kepler、Maxwell、Pascal、Volta、Turing架构)

参见 https://developer.nvidia.com/cuda-gpus


4.1.2. cusparseStatus_t

该数据类型表示库函数返回的状态,它可以有以下取值:

描述

CUSPARSE_STATUS_SUCCESS

操作成功完成

CUSPARSE_STATUS_NOT_INITIALIZED

cuSPARSE库未被初始化。这通常是由于缺少先前的调用、cuSPARSE例程调用的CUDA Runtime API出错,或硬件设置错误导致的

需要修正:在调用该函数前先调用cusparseCreate();并检查硬件、适当版本的驱动程序以及cuSPARSE库是否正确安装

该错误同样适用于通用API(cuSPARSE通用API),用于表示矩阵/向量描述符未初始化

CUSPARSE_STATUS_ALLOC_FAILED

cuSPARSE库内部资源分配失败。这通常由设备内存分配(cudaMalloc())或主机内存分配失败引起

需要修正:在函数调用前,尽可能释放之前分配的内存

CUSPARSE_STATUS_INVALID_VALUE

向函数传递了不支持的值或参数(例如负向量大小)

需要修正:确保所有传递的参数都具有有效值

CUSPARSE_STATUS_ARCH_MISMATCH

该函数需要的功能在当前设备架构中缺失

需要修正:在具有适当计算能力的设备上编译并运行应用程序

CUSPARSE_STATUS_EXECUTION_FAILED

GPU程序执行失败。这通常是由于GPU上的内核启动失败引起的,可能由多种原因导致

需要修正: 检查硬件、适当版本的驱动程序以及cuSPARSE库是否正确安装

CUSPARSE_STATUS_INTERNAL_ERROR

内部cuSPARSE操作失败

需要修正: 检查硬件设备、适当版本的驱动程序以及cuSPARSE库是否正确安装。同时,确保作为参数传递给例程的内存在例程完成前未被释放。

CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED

该函数不支持此矩阵类型。这通常是由于向函数传递了无效的矩阵描述符所致

需要修正: 检查cusparseMatDescr_t descrA中的字段是否设置正确

CUSPARSE_STATUS_NOT_SUPPORTED

该函数目前不支持此操作或数据类型组合

CUSPARSE_STATUS_INSUFFICIENT_RESOURCES

The resources for the computation, such as GPU global or shared memory, are not sufficient to complete the operation. The error can also indicate that the current computation mode (e.g. bit size of sparse matrix indices) does not allow to handle the given input


4.1.3. cusparseHandle_t

这是一个指向不透明cuSPARSE上下文的指针类型,用户必须在调用任何其他库函数之前通过调用cusparseCreate()来初始化它。由cusparseCreate()创建并返回的句柄必须传递给每个cuSPARSE函数。


4.1.4. cusparsePointerMode_t

该类型用于指示标量值是通过主机还是设备引用传递。需要特别指出的是,如果在函数调用中通过引用传递多个标量值,它们都将遵循相同的单一指针模式。指针模式可以分别通过cusparseSetPointerMode()cusparseGetPointerMode()例程进行设置和获取。

含义

CUSPARSE_POINTER_MODE_HOST

标量通过主机上的引用传递。

CUSPARSE_POINTER_MODE_DEVICE

标量通过设备上的引用传递。


4.1.5. cusparseOperation_t

此类型指示对相关输入(例如稀疏矩阵或向量)应用了哪些操作。

含义

CUSPARSE_OPERATION_NON_TRANSPOSE

选择非转置操作。

CUSPARSE_OPERATION_TRANSPOSE

已选择转置操作。

CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE

选择了共轭转置操作。


4.1.6. cusparseDiagType_t

此类型表示矩阵对角线元素是否为1。对角线元素始终被视为存在,但如果将CUSPARSE_DIAG_TYPE_UNIT传递给API例程,则该例程会假定所有对角线元素均为1,且不会读取或修改这些元素。请注意,在这种情况下,无论内存中实际设置的值是多少,例程都会假定对角线元素等于1。

含义

CUSPARSE_DIAG_TYPE_NON_UNIT

矩阵对角线包含非单位元素。

CUSPARSE_DIAG_TYPE_UNIT

矩阵对角线上的元素为单位元素。


4.1.7. cusparseFillMode_t

该类型指示矩阵的下三角部分还是上三角部分存储在稀疏存储中。

含义

CUSPARSE_FILL_MODE_LOWER

存储的是下三角部分。

CUSPARSE_FILL_MODE_UPPER

存储的是矩阵的上三角部分。


4.1.8. cusparseIndexBase_t

该类型表示矩阵索引的基数是零还是一。

含义

CUSPARSE_INDEX_BASE_ZERO

基础索引从零开始(兼容C语言)。

CUSPARSE_INDEX_BASE_ONE

基础索引从1开始(与Fortran兼容)。


4.1.9. cusparseDirection_t

该类型指示在函数cusparse[S|D|C|Z]nnz中,稠密矩阵的元素应按行还是按列进行解析(假设内存中稠密矩阵采用列优先存储)。此外,BSR格式中块的存储格式也由此类型控制。

含义

CUSPARSE_DIRECTION_ROW

矩阵应按行解析。

CUSPARSE_DIRECTION_COLUMN

矩阵应按列解析。



4.2. cuSPARSE管理API

本节介绍用于管理库的cuSPARSE函数。


4.2.1. cusparseCreate()

cusparseStatus_t
cusparseCreate(cusparseHandle_t *handle)

该函数用于初始化cuSPARSE库并创建cuSPARSE上下文句柄。在调用任何其他cuSPARSE API函数之前,必须先调用此函数。它会分配访问GPU所需的硬件资源。

参数

输入/输出

含义

handle

IN

指向cuSPARSE上下文句柄的指针

有关返回状态的描述,请参考cusparseStatus_t


4.2.2. cusparseDestroy()

cusparseStatus_t
cusparseDestroy(cusparseHandle_t handle)

此函数释放cuSPARSE库使用的CPU端资源。GPU端资源的释放可能会延迟到应用程序关闭时。

参数

输入/输出

含义

handle

IN

cuSPARSE上下文的句柄

有关返回状态的描述,请参考cusparseStatus_t


4.2.3. cusparseGetErrorName()

const char*
cusparseGetErrorString(cusparseStatus_t status)

该函数返回错误代码枚举名称的字符串表示形式。如果错误代码未被识别,则返回“无法识别的错误代码”。

参数

输入/输出

含义

status

IN

将错误代码转换为字符串

const char*

输出

指向以NULL结尾的字符串的指针


4.2.4. cusparseGetErrorString()

const char*
cusparseGetErrorString(cusparseStatus_t status)

返回错误码的描述字符串。如果错误码未被识别,则返回“无法识别的错误码”。

参数

输入/输出

含义

status

IN

将错误代码转换为字符串

const char*

输出

指向以NULL结尾的字符串的指针


4.2.5. cusparseGetProperty()

cusparseStatus_t
cusparseGetProperty(libraryPropertyType type,
                    int*                value)

该函数返回所请求属性的值。支持的属性类型请参考libraryPropertyType

参数

输入/输出

含义

type

IN

请求的属性

value

输出

请求属性的值

libraryPropertyType (定义于 library_types.h):

含义

MAJOR_VERSION

用于查询主版本的枚举器

MINOR_VERSION

用于查询次要版本的枚举器

PATCH_LEVEL

用于标识补丁级别的编号

有关返回状态的描述,请参考cusparseStatus_t


4.2.6. cusparseGetVersion()

cusparseStatus_t
cusparseGetVersion(cusparseHandle_t handle,
                   int*             version)

该函数返回cuSPARSE库的版本号。

参数

输入/输出

含义

handle

IN

cuSPARSE 句柄

version

输出

库的版本号

有关返回状态的描述,请参考cusparseStatus_t


4.2.7. cusparseGetPointerMode()

cusparseStatus_t
cusparseGetPointerMode(cusparseHandlet handle,
                       cusparsePointerMode_t *mode)

该函数获取cuSPARSE库使用的指针模式。详情请参阅关于cusparsePointerMode_t类型的章节。

参数

输入/输出

含义

handle

IN

cuSPARSE上下文的句柄

mode

输出

枚举指针模式类型之一

有关返回状态的描述,请参考cusparseStatus_t


4.2.8. cusparseSetPointerMode()

cusparseStatus_t
cusparseSetPointerMode(cusparseHandle_t handle,
                       cusparsePointerMode_t mode)

此函数设置cuSPARSE库使用的指针模式。默认情况下,值通过主机上的引用传递。有关更多详细信息,请参阅cublasPointerMode_t类型的相关章节。

参数

输入/输出

含义

handle

IN

cuSPARSE上下文的句柄

mode

IN

枚举指针模式类型之一

有关返回状态的描述,请参考cusparseStatus_t


4.2.9. cusparseGetStream()

cusparseStatus_t
cusparseGetStream(cusparseHandle_t handle, cudaStream_t *streamId)

此函数获取当前用于执行所有cuSPARSE库函数调用的cuSPARSE库流。如果未设置cuSPARSE库流,则所有内核将使用默认的NULL流。

参数

输入/输出

含义

handle

IN

cuSPARSE上下文的句柄

streamId

输出

该库使用的流

有关返回状态的描述,请参考cusparseStatus_t


4.2.10. cusparseSetStream()

cusparseStatus_t
cusparseSetStream(cusparseHandle_t handle, cudaStream_t streamId)

此函数设置cuSPARSE库用于执行其例程的流。

参数

输入/输出

含义

handle

IN

cuSPARSE上下文的句柄

streamId

IN

库将使用的流

有关返回状态的描述,请参考cusparseStatus_t



4.3. cuSPARSE日志记录API

可以通过在启动目标应用程序之前设置以下环境变量来启用cuSPARSE日志记录机制:

CUSPARSE_LOG_LEVEL= - 其中level为以下级别之一:

  • 0 - 关闭 - 日志记录已禁用(默认)

  • 1 - 错误 - 仅记录错误信息

  • 2 - 追踪 - 调用启动CUDA内核的API会记录其参数和重要信息

  • 3 - 提示 - 可能提升应用性能的提示

  • 4 - 信息 - 提供关于库执行的一般信息,可能包含启发式算法状态的细节

  • 5 - API跟踪 - API调用将记录其参数和重要信息

CUSPARSE_LOG_MASK= - 其中mask是以下掩码的组合:

  • 0 - 关闭

  • 1 - 错误

  • 2 - 追踪

  • 4 - 提示

  • 8 - 信息

  • 16 - API 追踪

CUSPARSE_LOG_FILE= - 其中file_name是日志文件的路径。文件名可以包含%i,它将被替换为进程ID。例如_%i.log

如果未定义CUSPARSE_LOG_FILE,日志消息将被打印到stdout

从CUDA 12.3开始,还可以通过在创建过程中设置环境变量CUSPARSE_STORE_INPUT_MATRIX将稀疏矩阵(CSR、CSC、COO、SELL、BSR)转储到二进制文件中。之后,可以将这些二进制文件发送至Math-Libs-Feedback@nvidia.com,用于调试和复现特定正确性/性能问题。

另一个选项是使用实验性的cuSPARSE日志记录API。参考:

注意

旧版API不支持日志记录机制。


4.3.1. cusparseLoggerSetCallback()

cusparseStatus_t
cusparseLoggerSetCallback(cusparseLoggerCallback_t callback)

实验性功能:该函数用于设置日志记录回调函数。

参数

输入/输出

含义

callback

IN

指向回调函数的指针

其中 cusparseLoggerCallback_t 具有以下签名:

void (*cusparseLoggerCallback_t)(int         logLevel,
                                 const char* functionName,
                                 const char* message)

参数

输入/输出

含义

logLevel

IN

选定的日志级别

functionName

IN

记录此消息的API名称

message

IN

日志消息

有关返回状态的描述,请参见cusparseStatus_t


4.3.2. cusparseLoggerSetFile()

cusparseStatus_t
cusparseLoggerSetFile(FILE* file)

实验性功能: 此函数用于设置日志输出文件。注意:通过此函数调用注册后,除非再次调用该函数切换至其他文件句柄,否则不得关闭提供的文件句柄。

参数

输入/输出

含义

file

IN

指向一个已打开文件的指针。该文件应具有写入权限

有关返回状态的描述,请参见cusparseStatus_t


4.3.3. cusparseLoggerOpenFile()

cusparseStatus_t
cusparseLoggerOpenFile(const char* logFile)

实验性功能:该函数会在指定路径下打开一个日志输出文件。

参数

输入/输出

含义

logFile

IN

日志输出文件的路径

有关返回状态的描述,请参见cusparseStatus_t


4.3.4. cusparseLoggerSetLevel()

cusparseStatus_t
cusparseLoggerSetLevel(int level)

实验性功能: 该函数用于设置日志记录级别的值。路径。

参数

输入/输出

含义

level

IN

日志记录级别的值

有关返回状态的描述,请参见cusparseStatus_t


4.3.5. cusparseLoggerSetMask()

cusparseStatus_t
cusparseLoggerSetMask(int mask)

实验性功能: 该函数用于设置日志掩码的值。

参数

输入/输出

含义

mask

IN

日志掩码的值

有关返回状态的描述,请参见cusparseStatus_t



5. cuSPARSE传统API

5.1. 命名规范

cuSPARSE传统函数支持以下数据类型:floatdoublecuComplexcuDoubleComplex。稀疏矩阵的Level 2和Level 3函数遵循以下命名规范:

cusparse<t>[<matrix data format>]<operation>[<output matrix data format>]

其中 <t> 可以是 SDCZX,分别对应数据类型 floatdoublecuComplexcuDoubleComplex 以及通用类型。

matrix data format可以是densecoocsrcsc,分别对应稠密矩阵、坐标格式、压缩稀疏行格式和压缩稀疏列格式。

5.2. cuSPARSE传统类型参考

5.2.1. cusparseAction_t

该类型指示操作是仅针对索引执行,还是针对数据和索引执行。

含义

CUSPARSE_ACTION_SYMBOLIC

该操作仅在索引上执行。

CUSPARSE_ACTION_NUMERIC

该操作在数据和索引上执行。

5.2.2. cusparseMatDescr_t

此结构用于描述矩阵的形状和属性。

typedef struct {
    cusparseMatrixType_t MatrixType;
    cusparseFillMode_t FillMode;
    cusparseDiagType_t DiagType;
    cusparseIndexBase_t IndexBase;
} cusparseMatDescr_t;

5.2.3. cusparseMatrixType_t

此类型表示稀疏存储中矩阵的类型。请注意,对于对称矩阵、厄米特矩阵和三角矩阵,仅存储其下三角或上三角部分。

矩阵类型和填充模式的整体思路是保持对称/厄米特矩阵的最小存储量,同时利用SpMV(稀疏矩阵向量乘法)中的对称特性。当A是对称矩阵且仅存储下三角部分时,计算y=A*x需要两个步骤:第一步计算y=(L+D)*x,第二步计算y=L^T*x + y。考虑到转置操作y=L^T*x比非转置版本y=L*x慢10倍,对称特性并未带来任何性能优势。对于用户而言,更好的做法是将对称矩阵扩展为普通矩阵,并使用矩阵类型CUSPARSE_MATRIX_TYPE_GENERAL来执行y=A*x运算。

通常,在迭代求解器(如PCG和GMRES)中,SpMV、预处理器(不完全Cholesky或不完全LU)和三角求解器会结合使用。如果用户始终使用通用矩阵(而非对称矩阵),则预处理器无需支持通用矩阵以外的类型。因此,新例程[bsr|csr]sv2(三角求解器)、[bsr|csr]ilu02(不完全LU)和[bsr|csr]ic02(不完全Cholesky)仅支持矩阵类型CUSPARSE_MATRIX_TYPE_GENERAL

含义

CUSPARSE_MATRIX_TYPE_GENERAL

矩阵是通用的。

CUSPARSE_MATRIX_TYPE_SYMMETRIC

该矩阵是对称的。

CUSPARSE_MATRIX_TYPE_HERMITIAN

该矩阵是厄米特矩阵。

CUSPARSE_MATRIX_TYPE_TRIANGULAR

该矩阵是三角矩阵。

5.2.4. cusparseColorInfo_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了csrcolor()中使用的信息。

5.2.5. cusparseSolvePolicy_t [已弃用]

该类型指示是否在csrsv2, csric02, csrilu02, bsrsv2, bsric02 bsrilu02中生成和使用级别信息。

含义

CUSPARSE_SOLVE_POLICY_NO_LEVEL

未生成或使用任何层级信息。

CUSPARSE_SOLVE_POLICY_USE_LEVEL

生成并使用层级信息。

5.2.6. bsric02Info_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了在bsric02_bufferSize()bsric02_analysis()bsric02()中使用的信息。

5.2.7. bsrilu02Info_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了在bsrilu02_bufferSize()bsrilu02_analysis()bsrilu02()中使用的信息。

5.2.8. bsrsm2Info_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了在bsrsm2_bufferSize()bsrsm2_analysis()bsrsm2_solve()中使用的信息。

5.2.9. bsrsv2Info_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了在bsrsv2_bufferSize()bsrsv2_analysis()bsrsv2_solve()中使用的信息。

5.2.10. csric02Info_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了在csric02_bufferSize()csric02_analysis()csric02()中使用的信息。

5.2.11. csrilu02Info_t [已弃用]

这是一个指向不透明结构的指针类型,该结构保存了在csrilu02_bufferSize()csrilu02_analysis()csrilu02()中使用的信息。

5.3. cuSPARSE辅助函数参考

本节介绍cuSPARSE辅助函数。

5.3.1. cusparseCreateColorInfo() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateColorInfo(cusparseColorInfo_t* info)

该函数创建并初始化cusparseColorInfo_t结构体,将其设置为默认值。

输入

信息

指向 cusparseColorInfo_t 结构的指针

有关返回状态的描述,请参见cusparseStatus_t

5.3.2. cusparseCreateMatDescr()

cusparseStatus_t
cusparseCreateMatDescr(cusparseMatDescr_t *descrA)

该函数用于初始化矩阵描述符。它将字段MatrixTypeIndexBase分别设置为默认CUSPARSE_MATRIX_TYPE_GENERALCUSPARSE_INDEX_BASE_ZERO,而其他字段则保持未初始化状态。

输入

描述A

指向矩阵描述符的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.3. cusparseDestroyColorInfo() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyColorInfo(cusparseColorInfo_t info)

该函数销毁并释放该结构所需的任何内存。

输入

信息

指向csrcolor()结构体的指针

有关返回状态的描述,请参见cusparseStatus_t

5.3.4. cusparseDestroyMatDescr()

cusparseStatus_t
cusparseDestroyMatDescr(cusparseMatDescr_t descrA)

该函数释放为矩阵描述符分配的内存。

输入

描述A

矩阵描述符。

有关返回状态的描述,请参见cusparseStatus_t

5.3.5. cusparseGetMatDiagType()

cusparseDiagType_t
cusparseGetMatDiagType(const cusparseMatDescr_t descrA)

该函数返回矩阵描述符descrA中的DiagType字段。

输入

描述A

矩阵描述符。

返回

 

枚举类型diagType中的一种。

5.3.6. cusparseGetMatFillMode()

cusparseFillMode_t
cusparseGetMatFillMode(const cusparseMatDescr_t descrA)

该函数返回矩阵描述符descrAFillMode字段。

输入

描述A

矩阵描述符。

返回

 

枚举填充模式类型之一。

5.3.7. cusparseGetMatIndexBase()

cusparseIndexBase_t
cusparseGetMatIndexBase(const cusparseMatDescr_t descrA)

该函数返回矩阵描述符descrAIndexBase字段。

输入

描述A

矩阵描述符。

返回

 

枚举的indexBase类型之一。

5.3.8. cusparseGetMatType()

cusparseMatrixType_t
cusparseGetMatType(const cusparseMatDescr_t descrA)

该函数返回矩阵描述符descrAMatrixType字段。

输入

描述A

矩阵描述符。

返回

 

枚举矩阵类型之一。

5.3.9. cusparseSetMatDiagType()

cusparseStatus_t
cusparseSetMatDiagType(cusparseMatDescr_t descrA,
                       cusparseDiagType_t diagType)

此函数设置矩阵描述符descrADiagType字段。

输入

diagType

枚举的diagType类型之一。

输出

描述A

矩阵描述符。

有关返回状态的描述,请参见cusparseStatus_t

5.3.10. cusparseSetMatFillMode()

cusparseStatus_t
cusparseSetMatFillMode(cusparseMatDescr_t descrA,
                       cusparseFillMode_t fillMode)

此函数设置矩阵描述符descrAFillMode字段。

输入

fillMode

枚举的fillMode类型之一。

输出

描述A

矩阵描述符。

有关返回状态的描述,请参见cusparseStatus_t

5.3.11. cusparseSetMatIndexBase()

cusparseStatus_t
cusparseSetMatIndexBase(cusparseMatDescr_t descrA,
                        cusparseIndexBase_t base)

此函数设置矩阵描述符descrAIndexBase字段。

输入

base

枚举的indexBase类型之一。

输出

描述A

矩阵描述符。

有关返回状态的描述,请参见cusparseStatus_t

5.3.12. cusparseSetMatType()

cusparseStatus_t
cusparseSetMatType(cusparseMatDescr_t descrA, cusparseMatrixType_t type)

此函数设置矩阵描述符descrAMatrixType字段。

输入

type

枚举矩阵类型之一。

输出

描述A

矩阵描述符。

有关返回状态的描述,请参见cusparseStatus_t

5.3.13. cusparseCreateCsric02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateCsric02Info(csric02Info_t *info);

该函数创建并初始化不完全Cholesky的求解和分析结构为默认值。

输入

信息

指向不完全Cholesky分解求解与分析结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.14. cusparseDestroyCsric02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyCsric02Info(csric02Info_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

求解(csric02_solve)和分析(csric02_analysis)结构。

有关返回状态的描述,请参见cusparseStatus_t

5.3.15. cusparseCreateCsrilu02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateCsrilu02Info(csrilu02Info_t *info);

该函数创建并初始化不完全LU分解的求解和分析结构为默认值。

输入

信息

指向不完全LU分解的求解与分析结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.16. cusparseDestroyCsrilu02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyCsrilu02Info(csrilu02Info_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

求解 (csrilu02_solve) 和分析 (csrilu02_analysis) 结构。

有关返回状态的描述,请参见cusparseStatus_t

5.3.17. cusparseCreateBsrsv2Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateBsrsv2Info(bsrsv2Info_t *info);

该函数创建并初始化bsrsv2的求解和分析结构为默认值。

输入

信息

指向bsrsv2求解和分析结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.18. cusparseDestroyBsrsv2Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyBsrsv2Info(bsrsv2Info_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

解决 (bsrsv2_solve) 和分析 (bsrsv2_analysis) 结构。

有关返回状态的描述,请参见cusparseStatus_t

5.3.19. cusparseCreateBsrsm2Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateBsrsm2Info(bsrsm2Info_t *info);

该函数创建并初始化bsrsm2的求解和分析结构为默认值。

输入

信息

指向bsrsm2求解和分析结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.20. cusparseDestroyBsrsm2Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyBsrsm2Info(bsrsm2Info_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

解决 (bsrsm2_solve) 和分析 (bsrsm2_analysis) 结构。

有关返回状态的描述,请参见cusparseStatus_t

5.3.21. cusparseCreateBsric02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateBsric02Info(bsric02Info_t *info);

此函数创建并初始化块不完全Cholesky的求解和分析结构为默认值。

输入

信息

指向块不完全Cholesky求解和分析结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.22. cusparseDestroyBsric02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyBsric02Info(bsric02Info_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

求解 (bsric02_solve) 和分析 (bsric02_analysis) 结构。

有关返回状态的描述,请参见cusparseStatus_t

5.3.23. cusparseCreateBsrilu02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateBsrilu02Info(bsrilu02Info_t *info);

该函数创建并初始化块不完全LU的求解和分析结构为默认值。

输入

信息

指向块不完全LU分解的求解和分析结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.24. cusparseDestroyBsrilu02Info() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyBsrilu02Info(bsrilu02Info_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

求解 (bsrilu02_solve) 和分析 (bsrilu02_analysis) 结构。

有关返回状态的描述,请参见cusparseStatus_t

5.3.25. cusparseCreatePruneInfo() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreatePruneInfo(pruneInfo_t *info);

该函数创建并初始化prune结构为默认值。

输入

信息

指向prune结构的指针。

有关返回状态的描述,请参见cusparseStatus_t

5.3.26. cusparseDestroyPruneInfo() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseDestroyPruneInfo(pruneInfo_t info);

该函数销毁并释放该结构所需的任何内存。

输入

信息

prune的结构。

有关返回状态的描述,请参见cusparseStatus_t

5.4. cuSPARSE 二级函数参考

本章介绍稀疏线性代数函数,这些函数执行稀疏矩阵与密集向量之间的运算。

5.4.1. cusparsebsrmv()

cusparseStatus_t
cusparseSbsrmv(cusparseHandle_t         handle,
               cusparseDirection_t      dir,
               cusparseOperation_t      trans,
               int                      mb,
               int                      nb,
               int                      nnzb,
               const float*             alpha,
               const cusparseMatDescr_t descr,
               const float*             bsrVal,
               const int*               bsrRowPtr,
               const int*               bsrColInd,
               int                      blockDim,
               const float*             x,
               const float*             beta,
               float*                   y)

cusparseStatus_t
cusparseDbsrmv(cusparseHandle_t         handle,
               cusparseDirection_t      dir,
               cusparseOperation_t      trans,
               int                      mb,
               int                      nb,
               int                      nnzb,
               const double*            alpha,
               const cusparseMatDescr_t descr,
               const double*            bsrVal,
               const int*               bsrRowPtr,
               const int*               bsrColInd,
               int                      blockDim,
               const double*            x,
               const double*            beta,
               double*                  y)

cusparseStatus_t
cusparseCbsrmv(cusparseHandle_t         handle,
               cusparseDirection_t      dir,
               cusparseOperation_t      trans,
               int                      mb,
               int                      nb,
               int                      nnzb,
               const cuComplex*         alpha,
               const cusparseMatDescr_t descr,
               const cuComplex*         bsrVal,
               const int*               bsrRowPtr,
               const int*               bsrColInd,
               int                      blockDim,
               const cuComplex*         x,
               const cuComplex*         beta,
               cuComplex*               y)

cusparseStatus_t
cusparseZbsrmv(cusparseHandle_t         handle,
               cusparseDirection_t      dir,
               cusparseOperation_t      trans,
               int                      mb,
               int                      nb,
               int                      nnzb,
               const cuDoubleComplex*   alpha,
               const cusparseMatDescr_t descr,
               const cuDoubleComplex*   bsrVal,
               const int*               bsrRowPtr,
               const int*               bsrColInd,
               int                      blockDim,
               const cuDoubleComplex*   x,
               const cuDoubleComplex*   beta,
               cuDoubleComplex*         y)

该函数执行矩阵-向量运算

\[\text{y} = \alpha \ast \text{op}(A) \ast \text{x} + \beta \ast \text{y}\]

其中 \(A\text{ is an }(mb \ast blockDim) \times (nb \ast blockDim)\) 是一个稀疏矩阵,通过三个数组 bsrValbsrRowPtrbsrColInd 以BSR存储格式定义;xy 是向量;\(\alpha\text{ and }\beta\) 是标量;并且

image1

bsrmv() 具有以下特性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

关于bsrmv()的几点说明:

  • 仅支持 blockDim > 1

  • 仅支持 CUSPARSE_OPERATION_NON_TRANSPOSE 操作,即

\[\text{y} = \alpha \ast A \ast \text{x} + \beta{} \ast \text{y}\]
  • 仅支持CUSPARSE_MATRIX_TYPE_GENERAL

  • 向量x的大小至少应为\((nb \ast blockDim)\),向量y的大小至少应为\((mb \ast blockDim)\);否则,内核可能因数组越界而返回CUSPARSE_STATUS_EXECUTION_FAILED

例如,假设用户拥有CSR格式的数据并希望尝试bsrmv(),以下代码展示了如何在单精度下使用csr2bsr()转换和bsrmv()乘法运算。

// Suppose that A is m x n sparse matrix represented by CSR format,
// hx is a host vector of size n, and hy is also a host vector of size m.
// m and n are not multiple of blockDim.
// step 1: transform CSR to BSR with column-major order
int base, nnz;
int nnzb;
cusparseDirection_t dirA = CUSPARSE_DIRECTION_COLUMN;
int mb = (m + blockDim-1)/blockDim;
int nb = (n + blockDim-1)/blockDim;
cudaMalloc((void**)&bsrRowPtrC, sizeof(int) *(mb+1));
cusparseXcsr2bsrNnz(handle, dirA, m, n,
        descrA, csrRowPtrA, csrColIndA, blockDim,
        descrC, bsrRowPtrC, &nnzb);
cudaMalloc((void**)&bsrColIndC, sizeof(int)*nnzb);
cudaMalloc((void**)&bsrValC, sizeof(float)*(blockDim*blockDim)*nnzb);
cusparseScsr2bsr(handle, dirA, m, n,
        descrA, csrValA, csrRowPtrA, csrColIndA, blockDim,
        descrC, bsrValC, bsrRowPtrC, bsrColIndC);
// step 2: allocate vector x and vector y large enough for bsrmv
cudaMalloc((void**)&x, sizeof(float)*(nb*blockDim));
cudaMalloc((void**)&y, sizeof(float)*(mb*blockDim));
cudaMemcpy(x, hx, sizeof(float)*n, cudaMemcpyHostToDevice);
cudaMemcpy(y, hy, sizeof(float)*m, cudaMemcpyHostToDevice);
// step 3: perform bsrmv
cusparseSbsrmv(handle, dirA, transA, mb, nb, nnzb, &alpha,
   descrC, bsrValC, bsrRowPtrC, bsrColIndC, blockDim, x, &beta, y);

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

trans

运算 \(\text{op}(A)\)。仅支持 CUSPARSE_OPERATION_NON_TRANSPOSE

mb

矩阵 \(A\) 的块行数。

nb

矩阵 \(A\) 的块列数。

nnzb

矩阵\(A\)的非零块数量。

alpha

用于乘法的标量。

描述

矩阵\(A\)的描述符。支持的矩阵类型是CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrVal

数组,包含矩阵 \(A\)nnz\(( =\)csrRowPtrA(mb)\(-\)csrRowPtrA(0)\()\) 个非零块。

bsrRowPtr

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColInd

长度为nnz\(( =\)csrRowPtrA(mb)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵\(A\)非零块的列索引。

blockDim

稀疏矩阵\(A\)的块维度,大于零。

x

<类型> 包含 \(nb \ast blockDim\) 个元素的向量。

beta

用于乘法的标量。如果 beta 为零,则 y 不需要是有效输入。

y

\(mb \ast blockDim\) 个元素组成的向量。

输出

y

更新后的向量。

有关返回状态的描述,请参见cusparseStatus_t

5.4.2. cusparsebsrxmv() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrxmv(cusparseHandle_t         handle,
                cusparseDirection_t      dir,
                cusparseOperation_t      trans,
                int                      sizeOfMask,
                int                      mb,
                int                      nb,
                int                      nnzb,
                const float*             alpha,
                const cusparseMatDescr_t descr,
                const float*             bsrVal,
                const int*               bsrMaskPtr,
                const int*               bsrRowPtr,
                const int*               bsrEndPtr,
                const int*               bsrColInd,
                int                      blockDim,
                const float*             x,
                const float*             beta,
                float*                   y)

cusparseStatus_t
cusparseDbsrxmv(cusparseHandle_t         handle,
                cusparseDirection_t      dir,
                cusparseOperation_t      trans,
                int                      sizeOfMask,
                int                      mb,
                int                      nb,
                int                      nnzb,
                const double*            alpha,
                const cusparseMatDescr_t descr,
                const double*            bsrVal,
                const int*               bsrMaskPtr,
                const int*               bsrRowPtr,
                const int*               bsrEndPtr,
                const int*               bsrColInd,
                int                      blockDim,
                const double*            x,
                const double*            beta,
                double*                  y)

cusparseStatus_t
cusparseCbsrxmv(cusparseHandle_t         handle,
                cusparseDirection_t      dir,
                cusparseOperation_t      trans,
                int                      sizeOfMask,
                int                      mb,
                int                      nb,
                int                      nnzb,
                const cuComplex*         alpha,
                const cusparseMatDescr_t descr,
                const cuComplex*         bsrVal,
                const int*               bsrMaskPtr,
                const int*               bsrRowPtr,
                const int*               bsrEndPtr,
                const int*               bsrColInd,
                int                      blockDim,
                const cuComplex*         x,
                const cuComplex*         beta,
                cuComplex*               y)

cusparseStatus_t
cusparseZbsrxmv(cusparseHandle_t         handle,
                cusparseDirection_t      dir,
                cusparseOperation_t      trans,
                int                      sizeOfMask,
                int                      mb,
                int                      nb,
                int                      nnzb,
                const cuDoubleComplex*   alpha,
                const cusparseMatDescr_t descr,
                const cuDoubleComplex*   bsrVal,
                const int*               bsrMaskPtr,
                const int*               bsrRowPtr,
                const int*               bsrEndPtr,
                const int*               bsrColInd,
                int                      blockDim,
                const cuDoubleComplex*   x,
                const cuDoubleComplex*   beta,
                cuDoubleComplex*         y)

该函数执行bsrmv和掩码操作

\[\text{y(mask)} = (\alpha \ast \text{op}(A) \ast \text{x} + \beta \ast \text{y})\text{(mask)}\]

其中\(A\text{ 是一个 }(mb \ast blockDim) \times (nb \ast blockDim)\)稀疏矩阵,由四个数组bsrValbsrRowPtrbsrEndPtrbsrColInd以BSRX存储格式定义;xy是向量;\(\alpha\text{~和~}\beta\)是标量;并且

image1

掩码操作由数组bsrMaskPtr定义,该数组包含\(y\)更新后的块行索引。如果行\(i\)未在bsrMaskPtr中指定,则bsrxmv()不会触及\(A\)\(y\)的行块\(i\)

例如,考虑一个\(2 \times 3\)的分块矩阵\(A\)

\[\begin{split}\begin{matrix} {A = \begin{bmatrix} A_{11} & A_{12} & O \\ A_{21} & A_{22} & A_{23} \\ \end{bmatrix}} \\ \end{matrix}\end{split}\]

其基于1的BSR格式(三向量形式)为:

\[\begin{split}\begin{matrix} \text{bsrVal} & = & \begin{bmatrix} A_{11} & A_{12} & A_{21} & A_{22} & A_{23} \\ \end{bmatrix} \\ \text{bsrRowPtr} & = & \begin{bmatrix} {1\phantom{.0}} & {3\phantom{.0}} & 6 \\ \end{bmatrix} \\ \text{bsrColInd} & = & \begin{bmatrix} {1\phantom{.0}} & {2\phantom{.0}} & {1\phantom{.0}} & {2\phantom{.0}} & 3 \\ \end{bmatrix} \\ \end{matrix}\end{split}\]

假设我们想对矩阵\(\bar{A}\)执行以下bsrmv操作,该矩阵与\(A\)略有不同。

\[\begin{split}\begin{bmatrix} y_{1} \\ y_{2} \\ \end{bmatrix}:=alpha \ast (\widetilde{A} = \begin{bmatrix} O & O & O \\ O & A_{22} & O \\ \end{bmatrix}) \ast \begin{bmatrix} x_{1} \\ x_{2} \\ x_{3} \\ \end{bmatrix} + \begin{bmatrix} y_{1} \\ {beta \ast y_{2}} \\ \end{bmatrix}\end{split}\]

我们无需为新矩阵\(\bar{A}\)创建另一种BSR格式,只需保持bsrValbsrColInd不变,但修改bsrRowPtr并新增一个数组bsrEndPtr,该数组指向\(\bar{A}\)每行最后一个非零元素的下一个位置。

例如,以下bsrRowPtrbsrEndPtr可以表示矩阵\(\bar{A}\)

\[\begin{split}\begin{matrix} \text{bsrRowPtr} & = & \begin{bmatrix} {1\phantom{.0}} & 4 \\ \end{bmatrix} \\ \text{bsrEndPtr} & = & \begin{bmatrix} {1\phantom{.0}} & 5 \\ \end{bmatrix} \\ \end{matrix}\end{split}\]

此外,我们可以使用掩码运算符(由数组bsrMaskPtr指定)仅更新\(y\)的特定块行索引,因为\(y_{1}\)永远不会改变。在这种情况下,bsrMaskPtr\(=\) [2]且sizeOfMask=1。

mask操作符等同于以下操作:

\[\begin{split}\begin{bmatrix} ? \\ y_{2} \\ \end{bmatrix}:=alpha \ast \begin{bmatrix} ? & ? & ? \\ O & A_{22} & O \\ \end{bmatrix} \ast \begin{bmatrix} x_{1} \\ x_{2} \\ x_{3} \\ \end{bmatrix} + beta \ast \begin{bmatrix} ? \\ y_{2} \\ \end{bmatrix}\end{split}\]

如果某个块行不在bsrMaskPtr中,则不会对该行执行计算,并且y中的对应值保持不变。问号"?"用于表示不在bsrMaskPtr中的行块。

在这种情况下,第一行块不存在于bsrMaskPtr中,因此bsrRowPtr[0]bsrEndPtr[0]也不会被修改。

\[\begin{split}\begin{matrix} \text{bsrRowPtr} & = & \begin{bmatrix} {?\phantom{.0}} & 4 \\ \end{bmatrix} \\ \text{bsrEndPtr} & = & \begin{bmatrix} {?\phantom{.0}} & 5 \\ \end{bmatrix} \\ \end{matrix}\end{split}\]

bsrxmv() 具有以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

关于bsrxmv()的一些说明:

  • 仅支持 blockDim > 1

  • 仅支持 CUSPARSE_OPERATION_NON_TRANSPOSECUSPARSE_MATRIX_TYPE_GENERAL

  • 参数 bsrMaskPtr, bsrRowPtr, bsrEndPtrbsrColInd 与基础索引保持一致,可以是一基或零基。上面的示例是一基的。

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

trans

运算 \(\text{op}(A)\)。仅支持 CUSPARSE_OPERATION_NON_TRANSPOSE

sizeOfMask

更新的块行数 \(y\)

mb

矩阵 \(A\) 的块行数。

nb

矩阵 \(A\) 的块列数。

nnzb

矩阵\(A\)的非零块数量。

alpha

用于乘法的标量。

描述

矩阵\(A\)的描述符。支持的矩阵类型是CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrVal

矩阵 \(A\)nnz 个非零块的数组。

bsrMaskPtr

包含对应已更新块行索引的sizeOfMask元素整数数组。

bsrRowPtr

包含每个块行起始位置的mb元素整数数组。

bsrEndPtr

包含每个块行末尾加1的mb个元素的整数数组。

bsrColInd

矩阵\(A\)非零块的nnzb列索引的整数数组。

blockDim

稀疏矩阵\(A\)的块维度,大于零。

x

<类型> 包含 \(nb \ast blockDim\) 个元素的向量。

beta

<type> 用于乘法的标量。如果 beta 为零,则 y 不需要是有效输入。

y

<type> 由 \(mb \ast blockDim\) 个元素组成的向量。

有关返回状态的描述,请参见cusparseStatus_t

5.4.3. cusparsebsrsv2_bufferSize() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrsv2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           float*                   bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrsv2Info_t             info,
                           int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseDbsrsv2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           double*                  bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrsv2Info_t             info,
                           int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseCbsrsv2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           cuComplex*               bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrsv2Info_t             info,
                           int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseZbsrsv2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           cuDoubleComplex*         bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrsv2Info_t             info,
                           int*                     pBufferSizeInBytes)

该函数返回bsrsv2中使用的缓冲区大小,这是一个新的稀疏三角线性系统op(A)*y =\(\alpha\)x

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;xy 分别是右侧向量和解向量;\(\alpha\) 是一个标量;

image1

尽管参数trans与矩阵A的上(下)三角部分存在六种组合情况,但bsrsv2_bufferSize()会返回这些组合中所需的最大缓冲区大小。缓冲区大小取决于维度参数mbblockDim以及矩阵非零块数量nnzb。若用户修改了矩阵,必须重新调用bsrsv2_bufferSize()以获取正确的缓冲区大小,否则可能导致段错误。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 \(\text{op}(A)\)

mb

矩阵A的块行数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,而支持的对角线类型包括CUSPARSE_DIAG_TYPE_UNITCUSPARSE_DIAG_TYPE_NON_UNIT

bsrValA

数组,包含矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度;必须大于零。

输出

信息

基于不同算法的内部状态记录。

pBufferSizeInBytes

用于bsrsv2_analysis()bsrsv2_solve()的缓冲区字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.4.4. cusparsebsrsv2_analysis() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrsv2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         int                      mb,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const float*             bsrValA,
                         const int*               bsrRowPtrA,
                         const int*               bsrColIndA,
                         int                      blockDim,
                         bsrsv2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

cusparseStatus_t
cusparseDbsrsv2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         int                      mb,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const double*            bsrValA,
                         const int*               bsrRowPtrA,
                         const int*               bsrColIndA,
                         int                      blockDim,
                         bsrsv2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

cusparseStatus_t
cusparseDbsrsv2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         int                      mb,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const cuComplex*         bsrValA,
                         const int*               bsrRowPtrA,
                         const int*               bsrColIndA,
                         int                      blockDim,
                         bsrsv2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

cusparseStatus_t
cusparseZbsrsv2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         int                      mb,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const cuDoubleComplex*   bsrValA,
                         const int*               bsrRowPtrA,
                         const int*               bsrColIndA,
                         int                      blockDim,
                         bsrsv2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

该函数执行bsrsv2的分析阶段,这是一个新的稀疏三角线性系统op(A)*y =\(\alpha\)x

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;xy 分别是右侧向量和解向量;\(\alpha\) 是一个标量;

image1

BSR格式的块大小为blockDim*blockDim,根据参数dirA决定按列优先或行优先存储,该参数可以是CUSPARSE_DIRECTION_COLUMNCUSPARSE_DIRECTION_ROW。矩阵类型必须为CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。

预期该函数对于给定的矩阵和特定操作类型仅执行一次。

此函数需要一个由bsrsv2_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

函数 bsrsv2_analysis() 会报告结构零并计算层级信息,这些信息存储在非透明结构体 info 中。层级信息可为三角求解器提取更多并行性。但 bsrsv2_solve() 无需层级信息也可执行。要禁用层级信息,用户需将三角求解器的策略指定为 CUSPARSE_SOLVE_POLICY_NO_LEVEL

函数 bsrsv2_analysis() 总是报告第一个结构性零,即使参数 policy 设置为 CUSPARSE_SOLVE_POLICY_NO_LEVEL。如果指定了 CUSPARSE_DIAG_TYPE_UNIT,则不会报告结构性零,即使某些 j 的块 A(j,j) 缺失。用户需要调用 cusparseXbsrsv2_zeroPivot() 来了解结构性零的位置。

是否在bsrsv2_analysis()报告结构零时调用bsrsv2_solve()由用户决定。在这种情况下,用户仍可调用bsrsv2_solve(),该函数将在结构零的相同位置返回数值零。但结果x将毫无意义。

  • 此函数需要临时额外存储空间,该空间在内部分配

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 \(\text{op}(A)\)

mb

矩阵A的块行数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,而支持的对角线类型包括CUSPARSE_DIAG_TYPE_UNITCUSPARSE_DIAG_TYPE_NON_UNIT

bsrValA

矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,大于零。

信息

使用cusparseCreateBsrsv2Info()初始化的结构体。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区,其大小由bsrsv2_bufferSize()返回。

输出

信息

在分析阶段收集的信息填充的结构(应原封不动地传递给解决阶段)。

有关返回状态的描述,请参见cusparseStatus_t

5.4.5. cusparsebsrsv2_solve() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrsv2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      int                      mb,
                      int                      nnzb,
                      const float*             alpha,
                      const cusparseMatDescr_t descrA,
                      const float*             bsrValA,
                      const int*               bsrRowPtrA,
                      const int*               bsrColIndA,
                      int                      blockDim,
                      bsrsv2Info_t             info,
                      const float*             x,
                      float*                   y,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

cusparseStatus_t
cusparseDbsrsv2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      int                      mb,
                      int                      nnzb,
                      const double*            alpha,
                      const cusparseMatDescr_t descrA,
                      const double*            bsrValA,
                      const int*               bsrRowPtrA,
                      const int*               bsrColIndA,
                      int                      blockDim,
                      bsrsv2Info_t             info,
                      const double*            x,
                      double*                  y,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

cusparseStatus_t
cusparseCbsrsv2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      int                      mb,
                      int                      nnzb,
                      const cuComplex*         alpha,
                      const cusparseMatDescr_t descrA,
                      const cuComplex*         bsrValA,
                      const int*               bsrRowPtrA,
                      const int*               bsrColIndA,
                      int                      blockDim,
                      bsrsv2Info_t             info,
                      const cuComplex*         x,
                      cuComplex*               y,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

cusparseStatus_t
cusparseZbsrsv2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      int                      mb,
                      int                      nnzb,
                      const cuDoubleComplex*   alpha,
                      const cusparseMatDescr_t descrA,
                      const cuDoubleComplex*   bsrValA,
                      const int*               bsrRowPtrA,
                      const int*               bsrColIndA,
                      int                      blockDim,
                      bsrsv2Info_t             info,
                      const cuDoubleComplex*   x,
                      cuDoubleComplex*         y,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

该函数执行bsrsv2的求解阶段,这是一个新的稀疏三角线性系统op(A)*y =\(\alpha\)x

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;xy 分别是右侧向量和解向量;\(\alpha\) 是一个标量;

image1

BSR格式中的块大小为blockDim*blockDim,根据参数dirA决定按列优先或行优先存储,该参数可以是CUSPARSE_DIRECTION_COLUMNCUSPARSE_DIRECTION_ROW。矩阵类型必须为CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。函数bsrsv02_solve()可以支持任意的blockDim

对于给定的矩阵和特定操作类型,此函数可能会被执行多次。

此函数需要一个由bsrsv2_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

虽然bsrsv2_solve()可以在没有层级信息的情况下执行,但用户仍需注意一致性。如果bsrsv2_analysis()调用时使用策略CUSPARSE_SOLVE_POLICY_USE_LEVEL,那么bsrsv2_solve()可以在有或没有层级的情况下运行。另一方面,如果bsrsv2_analysis()调用时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL,那么bsrsv2_solve()只能接受CUSPARSE_SOLVE_POLICY_NO_LEVEL;否则将返回CUSPARSE_STATUS_INVALID_VALUE

层级信息可能不会提升性能,反而会花费额外时间进行分析。例如,三对角矩阵不具备并行性。在这种情况下,CUSPARSE_SOLVE_POLICY_NO_LEVEL的表现优于CUSPARSE_SOLVE_POLICY_USE_LEVEL。如果用户使用迭代求解器,最佳做法是先用CUSPARSE_SOLVE_POLICY_USE_LEVEL执行一次bsrsv2_analysis(),然后在首次运行时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL执行bsrsv2_solve(),在第二次运行时改用CUSPARSE_SOLVE_POLICY_USE_LEVEL,最后选择较快的方式执行剩余迭代。

函数 bsrsv02_solve() 的行为与 csrsv02_solve() 相同。也就是说,bsr2csr(bsrsv02(A)) = csrsv02(bsr2csr(A))csrsv02_solve() 的数值零表示存在某些零元素 A(j,j)。而 bsrsv02_solve() 的数值零则表示存在某些不可逆的块 A(j,j)

函数 bsrsv2_solve() 会报告第一个数值为零的情况,包括结构零。如果指定了 CUSPARSE_DIAG_TYPE_UNIT,即使某些 A(j,j) 不可逆,也不会报告数值零。用户需要调用 cusparseXbsrsv2_zeroPivot() 来了解数值零的位置。

如果pBuffer != NULL,该函数支持以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

例如,假设L是一个单位对角线的下三角矩阵,那么以下代码利用层级信息求解L*y=x

// Suppose that L is m x m sparse matrix represented by BSR format,
// The number of block rows/columns is mb, and
// the number of nonzero blocks is nnzb.
// L is lower triangular with unit diagonal.
// Assumption:
// - dimension of matrix L is m(=mb*blockDim),
// - matrix L has nnz(=nnzb*blockDim*blockDim) nonzero elements,
// - handle is already created by cusparseCreate(),
// - (d_bsrRowPtr, d_bsrColInd, d_bsrVal) is BSR of L on device memory,
// - d_x is right hand side vector on device memory.
// - d_y is solution vector on device memory.
// - d_x and d_y are of size m.
cusparseMatDescr_t descr = 0;
bsrsv2Info_t info = 0;
int pBufferSize;
void *pBuffer = 0;
int structural_zero;
int numerical_zero;
const double alpha = 1.;
const cusparseSolvePolicy_t policy = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
const cusparseOperation_t trans = CUSPARSE_OPERATION_NON_TRANSPOSE;
const cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;

// step 1: create a descriptor which contains
// - matrix L is base-1
// - matrix L is lower triangular
// - matrix L has unit diagonal, specified by parameter CUSPARSE_DIAG_TYPE_UNIT
//   (L may not have all diagonal elements.)
cusparseCreateMatDescr(&descr);
cusparseSetMatIndexBase(descr, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatFillMode(descr, CUSPARSE_FILL_MODE_LOWER);
cusparseSetMatDiagType(descr, CUSPARSE_DIAG_TYPE_UNIT);

// step 2: create a empty info structure
cusparseCreateBsrsv2Info(&info);

// step 3: query how much memory used in bsrsv2, and allocate the buffer
cusparseDbsrsv2_bufferSize(handle, dir, trans, mb, nnzb, descr,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, &pBufferSize);

// pBuffer returned by cudaMalloc is automatically aligned to 128 bytes.
cudaMalloc((void**)&pBuffer, pBufferSize);

// step 4: perform analysis
cusparseDbsrsv2_analysis(handle, dir, trans, mb, nnzb, descr,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim,
    info, policy, pBuffer);
// L has unit diagonal, so no structural zero is reported.
status = cusparseXbsrsv2_zeroPivot(handle, info, &structural_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("L(%d,%d) is missing\n", structural_zero, structural_zero);
}

// step 5: solve L*y = x
cusparseDbsrsv2_solve(handle, dir, trans, mb, nnzb, &alpha, descr,
   d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info,
   d_x, d_y, policy, pBuffer);
// L has unit diagonal, so no numerical zero is reported.
status = cusparseXbsrsv2_zeroPivot(handle, info, &numerical_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("L(%d,%d) is zero\n", numerical_zero, numerical_zero);
}

// step 6: free resources
cudaFree(pBuffer);
cusparseDestroyBsrsv2Info(info);
cusparseDestroyMatDescr(descr);
cusparseDestroy(handle);

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 \(\text{op}(A)\)

mb

矩阵A的块行数和块列数。

alpha

用于乘法的标量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,而支持的对角线类型包括CUSPARSE_DIAG_TYPE_UNITCUSPARSE_DIAG_TYPE_NON_UNIT

bsrValA

<type> 数组,包含矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,必须大于零。

信息

包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。

x

大小为 m 的右侧向量。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区,其大小由bsrsv2_bufferSize()返回。

输出

y

大小为 m 的解向量。

有关返回状态的描述,请参见cusparseStatus_t

5.4.6. cusparseXbsrsv2_zeroPivot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseXbsrsv2_zeroPivot(cusparseHandle_t handle,
                          bsrsv2Info_t     info,
                          int*             position)

如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOTposition=j表示A(j,j)是结构零或数值零(奇异块)。否则position=-1

position 可以是基于0或基于1的索引,与矩阵的索引方式相同。

函数 cusparseXbsrsv2_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。

position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。

  • 该例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

信息

info 如果用户已经调用了 bsrsv2_analysis()bsrsv2_solve(),则包含结构零或数值零。

输出

position

如果没有结构或数值上的零值,position为-1;否则如果A(j,j)缺失或U(j,j)为零,则position=j

有关返回状态的描述,请参见cusparseStatus_t

5.4.7. cusparsegemvi() [已弃用]

> 此例程将在未来的主要版本中移除。

cusparseStatus_t
cusparseSgemvi_bufferSize(cusparseHandle_t    handle,
                          cusparseOperation_t transA,
                          int                 m,
                          int                 n,
                          int                 nnz,
                          int*                pBufferSize)

cusparseStatus_t
cusparseDgemvi_bufferSize(cusparseHandle_t    handle,
                          cusparseOperation_t transA,
                          int                 m,
                          int                 n,
                          int                 nnz,
                          int*                pBufferSize)

cusparseStatus_t
cusparseCgemvi_bufferSize(cusparseHandle_t    handle,
                          cusparseOperation_t transA,
                          int                 m,
                          int                 n,
                          int                 nnz,
                          int*                pBufferSize)

cusparseStatus_t
cusparseZgemvi_bufferSize(cusparseHandle_t    handle,
                          cusparseOperation_t transA,
                          int                 m,
                          int                 n,
                          int                 nnz,
                          int*                pBufferSize)
cusparseStatus_t
cusparseSgemvi(cusparseHandle_t     handle,
               cusparseOperation_t  transA,
               int                  m,
               int                  n,
               const float*         alpha,
               const float*         A,
               int                  lda,
               int                  nnz,
               const float*         x,
               const int*           xInd,
               const float*         beta,
               float*               y,
               cusparseIndexBase_t  idxBase,
               void*                pBuffer)

cusparseStatus_t
cusparseDgemvi(cusparseHandle_t     handle,
               cusparseOperation_t  transA,
               int                  m,
               int                  n,
               const double*        alpha,
               const double*        A,
               int                  lda,
               int                  nnz,
               const double*        x,
               const int*           xInd,
               const double*        beta,
               double*              y,
               cusparseIndexBase_t  idxBase,
               void*                pBuffer)

cusparseStatus_t
cusparseCgemvi(cusparseHandle_t     handle,
               cusparseOperation_t  transA,
               int                  m,
               int                  n,
               const cuComplex*     alpha,
               const cuComplex*     A,
               int                  lda,
               int                  nnz,
               const cuComplex*     x,
               const int*           xInd,
               const cuComplex*     beta,
               cuComplex*           y,
               cusparseIndexBase_t  idxBase,
               void*                pBuffer)

cusparseStatus_t
cusparseZgemvi(cusparseHandle_t       handle,
               cusparseOperation_t    transA,
               int                    m,
               int                    n,
               const cuDoubleComplex* alpha,
               const cuDoubleComplex* A,
               int                    lda,
               int                    nnz,
               const cuDoubleComplex* x,
               const int*             xInd,
               const cuDoubleComplex* beta,
               cuDoubleComplex*       y,
               cusparseIndexBase_t    idxBase,
               void*                  pBuffer)

该函数执行矩阵-向量运算

\[\text{y} = \alpha \ast \text{op}(A) \ast \text{x} + \beta \ast \text{y}\]

A 是一个 \(m \times n\) 的稠密矩阵,稀疏向量 x 通过两个长度为 nnz 的数组 xVal, xInd 以稀疏存储格式定义,y 是一个稠密向量;\(\alpha \;\)\(\beta \;\) 是标量;且

image2

为了简化实现,我们目前尚未对转置多重情况进行优化。对于对此情况感兴趣的用户,我们推荐以下方法。

  1. 使用csr2csc()函数之一将矩阵从CSR格式转换为CSC格式。请注意,通过交换结果的行和列,您实际上是在对矩阵进行转置。

  2. 调用gemvi()函数,将cusparseOperation_t参数设置为CUSPARSE_OPERATION_NON_TRANSPOSE,并使用以CSC格式存储的矩阵行列互换版本。这(隐式地)实现了向量与原始CSR格式矩阵转置的乘法运算。

    • 该例程不需要额外的存储空间

    • 该例程支持异步执行

    • 该例程支持CUDA图捕获

函数 cusparsegemvi_bufferSize() 返回在 cusparsegemvi() 中使用的缓冲区大小。

输入

handle

cuSPARSE库上下文的句柄。

trans

操作 \(\text{op}(A)\)

m

矩阵A的行数。

n

矩阵A的列数。

alpha

用于乘法的标量。

A

指向稠密矩阵 A 的指针。

lda

A的前导维度大小。

nnz

向量x的非零元素数量。

x

稀疏向量,包含nnz个元素,当\(\text{op}(A)=A\)时大小为n,当\(\text{op}(A)=A^{T}\)时大小为m

xInd

x中非零值的索引。

beta

<type> 用于乘法的标量。如果 beta 为零,则 y 不需要是有效输入。

y

如果\(\text{op}(A)=A\)则为m个元素的密集向量,如果\(\text{op}(A)=A^{T}\)则为n个元素的密集向量。

idxBase

0或1,分别表示基于0或基于1的索引。

pBufferSize

缓冲区在cusparsegemvi()中所需的元素数量。

pBuffer

工作空间缓冲区。

输出

y

更新后的密集向量。

有关返回状态的描述,请参见cusparseStatus_t

5.5. cuSPARSE 三级函数参考

本章介绍稀疏线性代数函数,这些函数在稀疏矩阵与(通常为高维)稠密矩阵之间执行运算。

5.5.1. cusparsebsrmm() [已弃用]

> 此例程将在未来的主要版本中移除。 请改用支持BSR矩阵的cusparseSpMM()函数。

cusparseStatus_t
cusparseSbsrmm(cusparseHandle_t         handle,
               cusparseDirection_t      dirA,
               cusparseOperation_t      transA,
               cusparseOperation_t      transB,
               int                      mb,
               int                      n,
               int                      kb,
               int                      nnzb,
               const float*             alpha,
               const cusparseMatDescr_t descrA,
               const float*             bsrValA,
               const int*               bsrRowPtrA,
               const int*               bsrColIndA,
               int                      blockDim,
               const float*             B,
               int                      ldb,
               const float*             beta,
               float*                   C,
               int                      ldc)

cusparseStatus_t
cusparseDbsrmm(cusparseHandle_t         handle,
               cusparseDirection_t      dirA,
               cusparseOperation_t      transA,
               cusparseOperation_t      transB,
               int                      mb,
               int                      n,
               int                      kb,
               int                      nnzb,
               const double*            alpha,
               const cusparseMatDescr_t descrA,
               const double*            bsrValA,
               const int*               bsrRowPtrA,
               const int*               bsrColIndA,
               int                      blockDim,
               const double*            B,
               int                      ldb,
               const double*            beta,
               double*                  C,
               int                      ldc)

cusparseStatus_t
cusparseCbsrmm(cusparseHandle_t         handle,
               cusparseDirection_t      dirA,
               cusparseOperation_t      transA,
               cusparseOperation_t      transB,
               int                      mb,
               int                      n,
               int                      kb,
               int                      nnzb,
               const cuComplex*         alpha,
               const cusparseMatDescr_t descrA,
               const cuComplex*         bsrValA,
               const int*               bsrRowPtrA,
               const int*               bsrColIndA,
               int                      blockDim,
               const cuComplex*         B,
               int                      ldb,
               const cuComplex*         beta,
               cuComplex*               C,
               int                      ldc)

cusparseStatus_t
cusparseZbsrmm(cusparseHandle_t         handle,
               cusparseDirection_t      dirA,
               cusparseOperation_t      transA,
               cusparseOperation_t      transB,
               int                      mb,
               int                      n,
               int                      kb,
               int                      nnzb,
               const cuDoubleComplex*   alpha,
               const cusparseMatDescr_t descrA,
               const cuDoubleComplex*   bsrValA,
               const int*               bsrRowPtrA,
               const int*               bsrColIndA,
               int                      blockDim,
               const cuDoubleComplex*   B,
               int                      ldb,
               const cuDoubleComplex*   beta,
               cuDoubleComplex*         C,
               int                      ldc)

该函数执行以下矩阵-矩阵运算之一:

\[C = \alpha \ast \text{op}(A) \ast \text{op}(B) + \beta \ast C\]

A 是一个 \(mb \times kb\) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;BC 是稠密矩阵;\(\alpha\text{~和~}\beta\) 是标量;并且

image3

image4

该函数有以下限制:

  • 仅支持CUSPARSE_MATRIX_TYPE_GENERAL矩阵类型

  • 仅支持 blockDim > 1

  • 如果 blockDim ≤ 4,则 max(mb)/max(n) = 524,272

  • 如果4 < blockDim ≤ 8,则最大(mb) = 524,272,最大(n) = 262,136

  • 如果 blockDim 大于 8,则 m 小于 65,535 且最大(n) = 262,136

使用transpose(B)的动机是为了改善矩阵B的内存访问效率。当矩阵B采用列优先存储时,A*transpose(B)的计算模式等同于矩阵B采用行优先存储时的A*B运算。

在实践中,迭代求解器或特征值求解器中的操作都不会使用A*transpose(B)。不过,我们可以执行A*transpose(transpose(B)),这与A*B是等价的。例如,假设A的维度是mb*kbB的维度是k*n,而C的维度是m*n,以下代码展示了cusparseDbsrmm()的用法。

// A is mb*kb, B is k*n and C is m*n
    const int m = mb*blockSize;
    const int k = kb*blockSize;
    const int ldb_B = k; // leading dimension of B
    const int ldc   = m; // leading dimension of C
// perform C:=alpha*A*B + beta*C
    cusparseSetMatType(descrA, CUSPARSE_MATRIX_TYPE_GENERAL );
    cusparseDbsrmm(cusparse_handle,
               CUSPARSE_DIRECTION_COLUMN,
               CUSPARSE_OPERATION_NON_TRANSPOSE,
               CUSPARSE_OPERATION_NON_TRANSPOSE,
               mb, n, kb, nnzb, alpha,
               descrA, bsrValA, bsrRowPtrA, bsrColIndA, blockSize,
               B, ldb_B,
               beta, C, ldc);

我们的建议不是直接使用A*B,而是先调用cublasgeam()B转置为Bt,然后再执行A*transpose(Bt)

// step 1: Bt := transpose(B)
    const int m = mb*blockSize;
    const int k = kb*blockSize;
    double *Bt;
    const int ldb_Bt = n; // leading dimension of Bt
    cudaMalloc((void**)&Bt, sizeof(double)*ldb_Bt*k);
    double one  = 1.0;
    double zero = 0.0;
    cublasSetPointerMode(cublas_handle, CUBLAS_POINTER_MODE_HOST);
    cublasDgeam(cublas_handle, CUBLAS_OP_T, CUBLAS_OP_T,
        n, k, &one, B, int ldb_B, &zero, B, int ldb_B, Bt, ldb_Bt);

// step 2: perform C:=alpha*A*transpose(Bt) + beta*C
    cusparseDbsrmm(cusparse_handle,
               CUSPARSE_DIRECTION_COLUMN,
               CUSPARSE_OPERATION_NON_TRANSPOSE,
               CUSPARSE_OPERATION_TRANSPOSE,
               mb, n, kb, nnzb, alpha,
               descrA, bsrValA, bsrRowPtrA, bsrColIndA, blockSize,
               Bt, ldb_Bt,
               beta, C, ldc);

bsrmm() 具有以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 op(A)

transB

操作 op(B)

mb

稀疏矩阵A的块行数。

n

稠密矩阵 op(B)A 的列数。

kb

稀疏矩阵A的块列数。

nnzb

稀疏矩阵A的非零块数量。

alpha

用于乘法的标量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,必须大于零。

B

维度数组 (ldb, n) 如果 op(B)=B 否则为 (ldb, k)

ldb

B的主维度。如果op(B)=B,则必须至少为\(\max\text{(1,\ k)}\);如果op(B) != B,则必须至少为max(1, n)

beta

用于乘法的标量。如果 beta 为零,则 C 不需要是有效输入。

C

维度数组 (ldc, n)

ldc

C的主维度。如果op(A)=A则必须至少为\(\max\text{(1,\ m)}\),否则至少为\(\max\text{(1,\ k)}\)

输出

C

更新后的维度数组 (ldc, n)

有关返回状态的描述,请参见cusparseStatus_t

5.5.2. cusparsebsrsm2_bufferSize() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrsm2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           cusparseOperation_t      transX,
                           int                      mb,
                           int                      n,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           float*                   bsrSortedValA,
                           const int*               bsrSortedRowPtrA,
                           const int*               bsrSortedColIndA,
                           int                      blockDim,
                           bsrsm2Info_t             info,
                           int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseDbsrsm2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           cusparseOperation_t      transX,
                           int                      mb,
                           int                      n,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           double*                  bsrSortedValA,
                           const int*               bsrSortedRowPtrA,
                           const int*               bsrSortedColIndA,
                           int                      blockDim,
                           bsrsm2Info_t             info,
                           int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseCbsrsm2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           cusparseOperation_t      transX,
                           int                      mb,
                           int                      n,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           cuComplex*               bsrSortedValA,
                           const int*               bsrSortedRowPtrA,
                           const int*               bsrSortedColIndA,
                           int                      blockDim,
                           bsrsm2Info_t             info,
                           int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseZbsrsm2_bufferSize(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           cusparseOperation_t      transA,
                           cusparseOperation_t      transX,
                           int                      mb,
                           int                      n,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           cuDoubleComplex*         bsrSortedValA,
                           const int*               bsrSortedRowPtrA,
                           const int*               bsrSortedColIndA,
                           int                      blockDim,
                           bsrsm2Info_t             info,
                           int*                     pBufferSizeInBytes)

该函数返回bsrsm2()中使用的缓冲区大小,这是一个新的稀疏三角线性系统op(A)*op(X)=\(\alpha\)op(B)

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;BX 分别是右侧矩阵和解矩阵;\(\alpha\) 是一个标量;

image9

尽管参数trans与矩阵A的上(下)三角部分存在六种组合情况,但bsrsm2_bufferSize()会返回这些组合中所需的缓冲区最大尺寸。缓冲区大小取决于维度mb,blockDim以及矩阵非零元素数量nnzb。若用户修改了矩阵,必须重新调用bsrsm2_bufferSize()获取正确的缓冲区大小,否则可能导致段错误。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 op(A)

transX

操作 op(X)

mb

矩阵A的块行数。

n

矩阵 op(B)op(X) 的列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,而支持的对角线类型包括CUSPARSE_DIAG_TYPE_UNITCUSPARSE_DIAG_TYPE_NON_UNIT

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的分块维度;必须大于零。

输出

信息

根据不同算法记录内部状态。

pBufferSizeInBytes

bsrsm2_analysis()bsrsm2_solve()中使用的缓冲区字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.5.3. cusparsebsrsm2_analysis() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrsm2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         cusparseOperation_t      transX,
                         int                      mb,
                         int                      n,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const float*             bsrSortedVal,
                         const int*               bsrSortedRowPtr,
                         const int*               bsrSortedColInd,
                         int                      blockDim,
                         bsrsm2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

cusparseStatus_t
cusparseDbsrsm2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         cusparseOperation_t      transX,
                         int                      mb,
                         int                      n,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const double*            bsrSortedVal,
                         const int*               bsrSortedRowPtr,
                         const int*               bsrSortedColInd,
                         int                      blockDim,
                         bsrsm2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

cusparseStatus_t
cusparseCbsrsm2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         cusparseOperation_t      transX,
                         int                      mb,
                         int                      n,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const cuComplex*         bsrSortedVal,
                         const int*               bsrSortedRowPtr,
                         const int*               bsrSortedColInd,
                         int                      blockDim,
                         bsrsm2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

cusparseStatus_t
cusparseZbsrsm2_analysis(cusparseHandle_t         handle,
                         cusparseDirection_t      dirA,
                         cusparseOperation_t      transA,
                         cusparseOperation_t      transX,
                         int                      mb,
                         int                      n,
                         int                      nnzb,
                         const cusparseMatDescr_t descrA,
                         const cuDoubleComplex*   bsrSortedVal,
                         const int*               bsrSortedRowPtr,
                         const int*               bsrSortedColInd,
                         int                      blockDim,
                         bsrsm2Info_t             info,
                         cusparseSolvePolicy_t    policy,
                         void*                    pBuffer)

此函数执行bsrsm2()的分析阶段,这是一个新的稀疏三角线性系统op(A)*op(X) =\(\alpha\)op(B)

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;BX 分别是右侧矩阵和解矩阵;\(\alpha\) 是一个标量;

image9

image5

op(B)op(X) 相等。

BSR格式的块大小为blockDim*blockDim,根据参数dirA决定按列优先或行优先存储,该参数可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN。矩阵类型必须为CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。

预期该函数对于给定的矩阵和特定操作类型仅执行一次。

此函数需要由bsrsm2_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

函数 bsrsm2_analysis() 会报告结构零并计算存储在非透明结构 info 中的层级信息。该层级信息可在三角求解器中提取更多并行性。但 bsrsm2_solve() 可不依赖层级信息执行。如需禁用层级信息,用户需将三角求解器的策略指定为 CUSPARSE_SOLVE_POLICY_NO_LEVEL

函数 bsrsm2_analysis() 总是会报告第一个结构零值,即使参数 policy 设置为 CUSPARSE_SOLVE_POLICY_NO_LEVEL。此外,如果指定了 CUSPARSE_DIAG_TYPE_UNIT,即使某些 j 的块 A(j,j) 缺失,也不会报告结构零值。用户必须调用 cusparseXbsrsm2_query_zero_pivot() 来了解结构零值的位置。

如果bsrsm2_analysis()报告存在结构零值,求解过程将在相同位置返回数值零,但该结果X没有实际意义。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 op(A)

transX

操作 op(B)op(X)

mb

矩阵A的块行数。

n

矩阵 op(B)op(X) 的列数。

nnzb

矩阵A的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,而支持的对角线类型包括CUSPARSE_DIAG_TYPE_UNITCUSPARSE_DIAG_TYPE_NON_UNIT

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度;必须大于零。

信息

使用cusparseCreateBsrsm2Info初始化的结构。

policy

支持的政策有CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由bsrsm2_bufferSize()返回。

输出

信息

在分析阶段收集的信息填充的结构(应原封不动地传递给解决阶段)。

有关返回状态的描述,请参见cusparseStatus_t

5.5.4. cusparsebsrsm2_solve() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrsm2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      cusparseOperation_t      transX,
                      int                      mb,
                      int                      n,
                      int                      nnzb,
                      const float*             alpha,
                      const cusparseMatDescr_t descrA,
                      const float*             bsrSortedVal,
                      const int*               bsrSortedRowPtr,
                      const int*               bsrSortedColInd,
                      int                      blockDim,
                      bsrsm2Info_t             info,
                      const float*             B,
                      int                      ldb,
                      float*                   X,
                      int                      ldx,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

cusparseStatus_t
cusparseDbsrsm2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      cusparseOperation_t      transX,
                      int                      mb,
                      int                      n,
                      int                      nnzb,
                      const double*            alpha,
                      const cusparseMatDescr_t descrA,
                      const double*            bsrSortedVal,
                      const int*               bsrSortedRowPtr,
                      const int*               bsrSortedColInd,
                      int                      blockDim,
                      bsrsm2Info_t             info,
                      const double*            B,
                      int                      ldb,
                      double*                  X,
                      int                      ldx,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

cusparseStatus_t
cusparseCbsrsm2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      cusparseOperation_t      transX,
                      int                      mb,
                      int                      n,
                      int                      nnzb,
                      const cuComplex*         alpha,
                      const cusparseMatDescr_t descrA,
                      const cuComplex*         bsrSortedVal,
                      const int*               bsrSortedRowPtr,
                      const int*               bsrSortedColInd,
                      int                      blockDim,
                      bsrsm2Info_t             info,
                      const cuComplex*         B,
                      int                      ldb,
                      cuComplex*               X,
                      int                      ldx,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

cusparseStatus_t
cusparseZbsrsm2_solve(cusparseHandle_t         handle,
                      cusparseDirection_t      dirA,
                      cusparseOperation_t      transA,
                      cusparseOperation_t      transX,
                      int                      mb,
                      int                      n,
                      int                      nnzb,
                      const cuDoubleComplex*   alpha,
                      const cusparseMatDescr_t descrA,
                      const cuDoubleComplex*   bsrSortedVal,
                      const int*               bsrSortedRowPtr,
                      const int*               bsrSortedColInd,
                      int                      blockDim,
                      bsrsm2Info_t             info,
                      const cuDoubleComplex*   B,
                      int                      ldb,
                      cuDoubleComplex*         X,
                      int                      ldx,
                      cusparseSolvePolicy_t    policy,
                      void*                    pBuffer)

该函数执行稀疏三角线性系统解的求解阶段:

\[\text{op}(A) \ast \text{op(X)} = \alpha \ast \text{op(B)}\]

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义;BX 分别是右侧矩阵和解矩阵;\(\alpha\) 是一个标量,且

image9

image6

仅支持 op(A)=A

op(B)op(X) 必须以相同的方式执行。换句话说,如果 op(B)=B,则 op(X)=X

BSR格式的块大小为blockDim*blockDim,根据参数dirA决定以列优先或行优先方式存储,该参数可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN。矩阵类型必须为CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。函数bsrsm02_solve()可以支持任意blockDim值。

对于给定的矩阵和特定操作类型,此函数可能会被执行多次。

此函数需要由bsrsm2_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

虽然bsrsm2_solve()可以在没有层级信息的情况下执行,但用户仍需注意一致性。如果bsrsm2_analysis()调用时使用策略CUSPARSE_SOLVE_POLICY_USE_LEVEL,则bsrsm2_solve()可以在有或没有层级的情况下运行。另一方面,如果bsrsm2_analysis()调用时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL,则bsrsm2_solve()只能接受CUSPARSE_SOLVE_POLICY_NO_LEVEL;否则将返回CUSPARSE_STATUS_INVALID_VALUE

函数 bsrsm02_solve() 的行为与 bsrsv02_solve() 相同,会报告第一个数值为零的情况,包括结构零。用户必须调用 cusparseXbsrsm2_query_zero_pivot() 来了解数值零的位置。

transpose(X)的动机是为了优化矩阵X的内存访问。当矩阵X采用列优先存储时,transpose(X)的计算模式等同于采用行优先存储的矩阵X

支持原地操作,要求BX指向相同的内存块,且ldb=ldx

如果pBuffer != NULL,该函数支持以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

transA

操作 op(A)

transX

操作 op(B)op(X)

mb

矩阵A的块行数。

n

矩阵 op(B)op(X) 的列数。

nnzb

矩阵A的非零块数量。

alpha

用于乘法的标量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,而支持的对角线类型包括CUSPARSE_DIAG_TYPE_UNITCUSPARSE_DIAG_TYPE_NON_UNIT

bsrValA

数组,包含矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的分块维度;必须大于零。

信息

使用cusparseCreateBsrsm2Info()初始化的结构。

B

右侧数组。

ldb

B的主维度。如果op(B)=B,则ldb >= (mb*blockDim);否则ldb >= n

ldx

X的主维度。如果op(X)=X,则ldx >= (mb*blockDim);否则ldx >= n

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由bsrsm2_bufferSize()返回。

输出

X

解决方案数组,包含前导维度 ldx

有关返回状态的描述,请参见cusparseStatus_t

5.5.5. cusparseXbsrsm2_zeroPivot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseXbsrsm2_zeroPivot(cusparseHandle_t handle,
                          bsrsm2Info_t     info,
                          int*             position)

如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOTposition=j表示A(j,j)是结构零或数值零(奇异块)。否则position=-1

position 可以是基于0或基于1的索引,与矩阵的索引方式相同。

函数 cusparseXbsrsm2_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。

position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。

  • 该例程不需要额外的存储空间。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

信息

info 如果用户已经调用了 bsrsm2_analysis()bsrsm2_solve(),则包含结构零或数值零。

输出

position

如果没有结构或数值上的零值,position为-1;否则,如果A(j,j)缺失或U(j,j)为零,则position=j

有关返回状态的描述,请参见cusparseStatus_t

5.6. cuSPARSE 额外函数参考

本章介绍用于操作稀疏矩阵的额外例程。

5.6.1. cusparsecsrgeam2()

cusparseStatus_t
cusparseScsrgeam2_bufferSizeExt(cusparseHandle_t         handle,
                                int                      m,
                                int                      n,
                                const float*             alpha,
                                const cusparseMatDescr_t descrA,
                                int                      nnzA,
                                const float*             csrSortedValA,
                                const int*               csrSortedRowPtrA,
                                const int*               csrSortedColIndA,
                                const float*             beta,
                                const cusparseMatDescr_t descrB,
                                int                      nnzB,
                                const float*             csrSortedValB,
                                const int*               csrSortedRowPtrB,
                                const int*               csrSortedColIndB,
                                const cusparseMatDescr_t descrC,
                                const float*             csrSortedValC,
                                const int*               csrSortedRowPtrC,
                                const int*               csrSortedColIndC,
                                size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseDcsrgeam2_bufferSizeExt(cusparseHandle_t         handle,
                                int                      m,
                                int                      n,
                                const double*            alpha,
                                const cusparseMatDescr_t descrA,
                                int                      nnzA,
                                const double*            csrSortedValA,
                                const int*               csrSortedRowPtrA,
                                const int*               csrSortedColIndA,
                                const double*            beta,
                                const cusparseMatDescr_t descrB,
                                int                      nnzB,
                                const double*            csrSortedValB,
                                const int*               csrSortedRowPtrB,
                                const int*               csrSortedColIndB,
                                const cusparseMatDescr_t descrC,
                                const double*            csrSortedValC,
                                const int*               csrSortedRowPtrC,
                                const int*               csrSortedColIndC,
                                size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseCcsrgeam2_bufferSizeExt(cusparseHandle_t         handle,
                                int                      m,
                                int                      n,
                                const cuComplex*         alpha,
                                const cusparseMatDescr_t descrA,
                                int                      nnzA,
                                const cuComplex*         csrSortedValA,
                                const int*               csrSortedRowPtrA,
                                const int*               csrSortedColIndA,
                                const cuComplex*         beta,
                                const cusparseMatDescr_t descrB,
                                int                      nnzB,
                                const cuComplex*         csrSortedValB,
                                const int*               csrSortedRowPtrB,
                                const int*               csrSortedColIndB,
                                const cusparseMatDescr_t descrC,
                                const cuComplex*         csrSortedValC,
                                const int*               csrSortedRowPtrC,
                                const int*               csrSortedColIndC,
                                size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseZcsrgeam2_bufferSizeExt(cusparseHandle_t         handle,
                                int                      m,
                                int                      n,
                                const cuDoubleComplex*   alpha,
                                const cusparseMatDescr_t descrA,
                                int                      nnzA,
                                const cuDoubleComplex*   csrSortedValA,
                                const int*               csrSortedRowPtrA,
                                const int*               csrSortedColIndA,
                                const cuDoubleComplex*   beta,
                                const cusparseMatDescr_t descrB,
                                int                      nnzB,
                                const cuDoubleComplex*   csrSortedValB,
                                const int*               csrSortedRowPtrB,
                                const int*               csrSortedColIndB,
                                const cusparseMatDescr_t descrC,
                                const cuDoubleComplex*   csrSortedValC,
                                const int*               csrSortedRowPtrC,
                                const int*               csrSortedColIndC,
                                size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseXcsrgeam2Nnz(cusparseHandle_t         handle,
                     int                      m,
                     int                      n,
                     const cusparseMatDescr_t descrA,
                     int                      nnzA,
                     const int*               csrSortedRowPtrA,
                     const int*               csrSortedColIndA,
                     const cusparseMatDescr_t descrB,
                     int                      nnzB,
                     const int*               csrSortedRowPtrB,
                     const int*               csrSortedColIndB,
                     const cusparseMatDescr_t descrC,
                     int*                     csrSortedRowPtrC,
                     int*                     nnzTotalDevHostPtr,
                     void*                    workspace)
cusparseStatus_t
cusparseScsrgeam2(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  const float*             alpha,
                  const cusparseMatDescr_t descrA,
                  int                      nnzA,
                  const float*             csrSortedValA,
                  const int*               csrSortedRowPtrA,
                  const int*               csrSortedColIndA,
                  const float*             beta,
                  const cusparseMatDescr_t descrB,
                  int                      nnzB,
                  const float*             csrSortedValB,
                  const int*               csrSortedRowPtrB,
                  const int*               csrSortedColIndB,
                  const cusparseMatDescr_t descrC,
                  float*                   csrSortedValC,
                  int*                     csrSortedRowPtrC,
                  int*                     csrSortedColIndC,
                  void*                    pBuffer)

cusparseStatus_t
cusparseDcsrgeam2(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  const double*            alpha,
                  const cusparseMatDescr_t descrA,
                  int                      nnzA,
                  const double*            csrSortedValA,
                  const int*               csrSortedRowPtrA,
                  const int*               csrSortedColIndA,
                  const double*            beta,
                  const cusparseMatDescr_t descrB,
                  int                      nnzB,
                  const double*            csrSortedValB,
                  const int*               csrSortedRowPtrB,
                  const int*               csrSortedColIndB,
                  const cusparseMatDescr_t descrC,
                  double*                  csrSortedValC,
                  int*                     csrSortedRowPtrC,
                  int*                     csrSortedColIndC,
                  void*                    pBuffer)

cusparseStatus_t
cusparseCcsrgeam2(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  const cuComplex*         alpha,
                  const cusparseMatDescr_t descrA,
                  int                      nnzA,
                  const cuComplex*         csrSortedValA,
                  const int*               csrSortedRowPtrA,
                  const int*               csrSortedColIndA,
                  const cuComplex*         beta,
                  const cusparseMatDescr_t descrB,
                  int                      nnzB,
                  const cuComplex*         csrSortedValB,
                  const int*               csrSortedRowPtrB,
                  const int*               csrSortedColIndB,
                  const cusparseMatDescr_t descrC,
                  cuComplex*               csrSortedValC,
                  int*                     csrSortedRowPtrC,
                  int*                     csrSortedColIndC,
                  void*                    pBuffer)

cusparseStatus_t
cusparseZcsrgeam2(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  const cuDoubleComplex*   alpha,
                  const cusparseMatDescr_t descrA,
                  int                      nnzA,
                  const cuDoubleComplex*   csrSortedValA,
                  const int*               csrSortedRowPtrA,
                  const int*               csrSortedColIndA,
                  const cuDoubleComplex*   beta,
                  const cusparseMatDescr_t descrB,
                  int                      nnzB,
                  const cuDoubleComplex*   csrSortedValB,
                  const int*               csrSortedRowPtrB,
                  const int*               csrSortedColIndB,
                  const cusparseMatDescr_t descrC,
                  cuDoubleComplex*         csrSortedValC,
                  int*                     csrSortedRowPtrC,
                  int*                     csrSortedColIndC,
                  void*                    pBuffer)

该函数执行以下矩阵-矩阵运算

\[C = \alpha \ast A + \beta \ast B\]

其中ABC\(m \times n\)稀疏矩阵(分别由三个数组csrValA|csrValB|csrValCcsrRowPtrA|csrRowPtrB|csrRowPtrCcsrColIndA|csrColIndB|csrcolIndC以CSR存储格式定义),\(\alpha\text{~和~}\beta\)为标量。由于AB具有不同的稀疏模式,cuSPARSE采用两步法完成稀疏矩阵C的计算。第一步,用户分配m+1个元素的csrRowPtrC数组,并调用函数cusparseXcsrgeam2Nnz()来确定csrRowPtrC及非零元素总数。第二步,用户从(nnzC=*nnzTotalDevHostPtr)(nnzC=csrRowPtrC(m)-csrRowPtrC(0))获取矩阵C的非零元素数量nnzC,然后分别分配nnzC个元素的csrValC, csrColIndC数组,最终调用函数cusparse[S|D|C|Z]csrgeam2()完成矩阵C的计算。

一般流程如下:

int baseC, nnzC;
/* alpha, nnzTotalDevHostPtr points to host memory */
size_t BufferSizeInBytes;
char *buffer = NULL;
int *nnzTotalDevHostPtr = &nnzC;
cusparseSetPointerMode(handle, CUSPARSE_POINTER_MODE_HOST);
cudaMalloc((void**)&csrRowPtrC, sizeof(int)*(m+1));
/* prepare buffer */
cusparseScsrgeam2_bufferSizeExt(handle, m, n,
    alpha,
    descrA, nnzA,
    csrValA, csrRowPtrA, csrColIndA,
    beta,
    descrB, nnzB,
    csrValB, csrRowPtrB, csrColIndB,
    descrC,
    csrValC, csrRowPtrC, csrColIndC
    &bufferSizeInBytes
    );
cudaMalloc((void**)&buffer, sizeof(char)*bufferSizeInBytes);
cusparseXcsrgeam2Nnz(handle, m, n,
        descrA, nnzA, csrRowPtrA, csrColIndA,
        descrB, nnzB, csrRowPtrB, csrColIndB,
        descrC, csrRowPtrC, nnzTotalDevHostPtr,
        buffer);
if (NULL != nnzTotalDevHostPtr){
    nnzC = *nnzTotalDevHostPtr;
}else{
    cudaMemcpy(&nnzC, csrRowPtrC+m, sizeof(int), cudaMemcpyDeviceToHost);
    cudaMemcpy(&baseC, csrRowPtrC, sizeof(int), cudaMemcpyDeviceToHost);
    nnzC -= baseC;
}
cudaMalloc((void**)&csrColIndC, sizeof(int)*nnzC);
cudaMalloc((void**)&csrValC, sizeof(float)*nnzC);
cusparseScsrgeam2(handle, m, n,
        alpha,
        descrA, nnzA,
        csrValA, csrRowPtrA, csrColIndA,
        beta,
        descrB, nnzB,
        csrValB, csrRowPtrB, csrColIndB,
        descrC,
        csrValC, csrRowPtrC, csrColIndC
        buffer);

关于csrgeam2()的几点说明:

  • cuSPARSE不支持其他三种组合NT、TN和TT。若需执行其中任一操作,用户应使用csr2csc()例程将\(A\) | \(B\)转换为\(A^{T}\) | \(B^{T}\)

  • 仅支持CUSPARSE_MATRIX_TYPE_GENERAL。如果AB是对称或厄米特矩阵,用户必须将矩阵扩展为完整矩阵,并将描述符的MatrixType字段重新配置为CUSPARSE_MATRIX_TYPE_GENERAL

  • 如果已知矩阵C的稀疏模式,用户可以跳过对函数cusparseXcsrgeam2Nnz()的调用。例如,假设用户有一个迭代算法会不断更新AB但保持稀疏模式不变。用户可以仅调用一次cusparseXcsrgeam2Nnz()来设置C的稀疏模式,然后在每次迭代时仅调用函数cusparse[S|D|C|Z]geam()

  • 指针 alphabeta 必须有效。

  • alphabeta为零时,cuSPARSE不会将其视为特殊情况。C的稀疏模式与alphabeta的值无关。如果用户需要\(C = 0 \times A + 1 \times B^{T}\),那么使用csr2csc()会比csrgeam2()更合适。

  • csrgeam2()csrgeam() 功能相同,区别在于 csrgeam2() 需要显式缓冲区,而 csrgeam() 会在内部自动分配缓冲区。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

稀疏矩阵 A,B,C 的行数。

n

稀疏矩阵 A,B,C 的列数。

alpha

用于乘法的标量。

描述A

矩阵A的描述符。支持的矩阵类型仅为CUSPARSE_MATRIX_TYPE_GENERAL

nnzA

稀疏矩阵A的非零元素数量。

csrValA

数组,包含矩阵 AnnzA\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾加一的位置。

csrColIndA

nnzA\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零元素的列索引。

beta

<type> 用于乘法的标量。如果 beta 为零,则 y 不需要是有效输入。

描述B

矩阵B的描述符。支持的矩阵类型仅为CUSPARSE_MATRIX_TYPE_GENERAL

nnzB

稀疏矩阵B的非零元素数量。

csrValB

数组,包含矩阵 BnnzB\(( =\)csrRowPtrB(m)\(-\)csrRowPtrB(0)\()\) 个非零元素。

csrRowPtrB

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾的下一个位置。

csrColIndB

nnzB\(( =\)csrRowPtrB(m)\(-\)csrRowPtrB(0)\()\) 的整数数组,表示矩阵 B 非零元素的列索引。

descrC

矩阵C的描述符。仅支持CUSPARSE_MATRIX_TYPE_GENERAL矩阵类型。

输出

csrValC

矩阵 CnnzC\(( =\)csrRowPtrC(m)\(-\)csrRowPtrC(0)\()\) 个非零元素的数组。

csrRowPtrC

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾加一的位置。

csrColIndC

长度为nnzC\(( =\)csrRowPtrC(m)\(-\)csrRowPtrC(0)\()\)的整型数组,表示矩阵C非零元素的列索引。

nnzTotalDevHostPtr

设备或主机内存中非零元素的总数。它等于(csrRowPtrC(m)-csrRowPtrC(0))

有关返回状态的描述,请参见cusparseStatus_t

5.7. cuSPARSE预条件子参考

本章介绍实现不同预条件子的例程。

5.7.1. 不完全Cholesky分解:级别0 [已弃用]

本节讨论了ic0的不同算法。

5.7.1.1. cusparsecsric02_bufferSize() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsric02_bufferSize(cusparseHandle_t         handle,
                            int                      m,
                            int                      nnz,
                            const cusparseMatDescr_t descrA,
                            float*                   csrValA,
                            const int*               csrRowPtrA,
                            const int*               csrColIndA,
                            csric02Info_t            info,
                            int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseDcsric02_bufferSize(cusparseHandle_t         handle,
                            int                      m,
                            int                      nnz,
                            const cusparseMatDescr_t descrA,
                            double*                  csrValA,
                            const int*               csrRowPtrA,
                            const int*               csrColIndA,
                            csric02Info_t            info,
                            int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseCcsric02_bufferSize(cusparseHandle_t         handle,
                            int                      m,
                            int                      nnz,
                            const cusparseMatDescr_t descrA,
                            cuComplex*               csrValA,
                            const int*               csrRowPtrA,
                            const int*               csrColIndA,
                            csric02Info_t            info,
                            int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseZcsric02_bufferSize(cusparseHandle_t         handle,
                            int                      m,
                            int                      nnz,
                            const cusparseMatDescr_t descrA,
                            cuDoubleComplex*         csrValA,
                            const int*               csrRowPtrA,
                            const int*               csrColIndA,
                            csric02Info_t            info,
                            int*                     pBufferSizeInBytes)

该函数返回用于计算不完全Cholesky分解的缓冲区大小,该分解采用\(0\)填充且无主元旋转:

\[A \approx LL^{H}\]

A 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValAcsrRowPtrAcsrColIndA 以 CSR 存储格式定义。

缓冲区大小取决于矩阵的维度m和非零元素数量nnz。如果用户更改了矩阵,必须再次调用csric02_bufferSize()以获取正确的缓冲区大小,否则可能会出现段错误。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数和列数。

nnz

矩阵 A 的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素的数组。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾加一的位置。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

输出

信息

根据不同算法记录内部状态

pBufferSizeInBytes

csric02_analysis()csric02()中使用的缓冲区字节数

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.2. cusparsecsric02_analysis() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsric02_analysis(cusparseHandle_t         handle,
                          int                      m,
                          int                      nnz,
                          const cusparseMatDescr_t descrA,
                          const float*             csrValA,
                          const int*               csrRowPtrA,
                          const int*               csrColIndA,
                          csric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

cusparseStatus_t
cusparseDcsric02_analysis(cusparseHandle_t         handle,
                          int                      m,
                          int                      nnz,
                          const cusparseMatDescr_t descrA,
                          const double*            csrValA,
                          const int*               csrRowPtrA,
                          const int*               csrColIndA,
                          csric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

cusparseStatus_t
cusparseCcsric02_analysis(cusparseHandle_t         handle,
                          int                      m,
                          int                      nnz,
                          const cusparseMatDescr_t descrA,
                          const cuComplex*         csrValA,
                          const int*               csrRowPtrA,
                          const int*               csrColIndA,
                          csric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

cusparseStatus_t
cusparseZcsric02_analysis(cusparseHandle_t         handle,
                          int                      m,
                          int                      nnz,
                          const cusparseMatDescr_t descrA,
                          const cuDoubleComplex*   csrValA,
                          const int*               csrRowPtrA,
                          const int*               csrColIndA,
                          csric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

该函数执行不完全Cholesky分解的分析阶段,采用\(0\)填充且无主元置换:

\[A \approx LL^{H}\]

A 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValAcsrRowPtrAcsrColIndA 以 CSR 存储格式定义。

此函数需要由csric02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

函数 csric02_analysis() 会报告结构零并计算存储在非透明结构 info 中的层级信息。该层级信息可以在不完全Cholesky分解过程中提取更多并行性。不过 csric02() 也可以在没有层级信息的情况下执行。要禁用层级信息,用户必须将 csric02_analysis()csric02() 的策略指定为 CUSPARSE_SOLVE_POLICY_NO_LEVEL

函数 csric02_analysis() 总是报告第一个结构零,即使策略是 CUSPARSE_SOLVE_POLICY_NO_LEVEL。用户需要调用 cusparseXcsric02_zeroPivot() 来了解结构零的位置。

是否在csric02_analysis()报告结构零时调用csric02()由用户决定。在这种情况下,用户仍可以调用csric02(),该函数将在结构零的相同位置返回数值零。但该结果没有意义。

  • 此函数需要临时额外存储空间,该空间在内部分配

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数和列数。

nnz

矩阵A的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

数组,包含矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾的下一个位置。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

信息

使用cusparseCreateCsric02Info()初始化的结构体。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由csric02_bufferSize()返回。

输出

信息

csric02_analysis()csric02()中使用的缓冲区字节数

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.3. cusparsecsric02() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsric02(cusparseHandle_t         handle,
                 int                      m,
                 int                      nnz,
                 const cusparseMatDescr_t descrA,
                 float*                   csrValA_valM,
                 const int*               csrRowPtrA,
                 const int*               csrColIndA,
                 csric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

cusparseStatus_t
cusparseDcsric02(cusparseHandle_t         handle,
                 int                      m,
                 int                      nnz,
                 const cusparseMatDescr_t descrA,
                 double*                  csrValA_valM,
                 const int*               csrRowPtrA,
                 const int*               csrColIndA,
                 csric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

cusparseStatus_t
cusparseCcsric02(cusparseHandle_t         handle,
                 int                      m,
                 int                      nnz,
                 const cusparseMatDescr_t descrA,
                 cuComplex*               csrValA_valM,
                 const int*               csrRowPtrA,
                 const int*               csrColIndA,
                 csric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

cusparseStatus_t
cusparseZcsric02(cusparseHandle_t         handle,
                 int                      m,
                 int                      nnz,
                 const cusparseMatDescr_t descrA,
                 cuDoubleComplex*         csrValA_valM,
                 const int*               csrRowPtrA,
                 const int*               csrColIndA,
                 csric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

该函数执行计算不完全Cholesky分解的求解阶段,采用\(0\)填充且无主元选择:

\[A \approx LL^{H}\]

此函数需要由csric02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

虽然csric02()可以在没有层级信息的情况下执行,但用户仍需注意一致性。如果csric02_analysis()调用时使用策略CUSPARSE_SOLVE_POLICY_USE_LEVEL,则csric02()可以在有或没有层级的情况下运行。另一方面,如果csric02_analysis()调用时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL,则csric02()只能接受CUSPARSE_SOLVE_POLICY_NO_LEVEL;否则将返回CUSPARSE_STATUS_INVALID_VALUE

函数 csric02() 会报告第一个数值为零的位置,包括结构零。用户必须调用 cusparseXcsric02_zeroPivot() 来确认数值零的具体位置。

函数 csric02() 仅使用矩阵 A 的下三角部分进行分解。矩阵类型必须为 CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型会被忽略,严格上三角部分会被忽略且不会被触及。无论 A 是否为 Hermitian 矩阵都不影响。换句话说,从 csric02() 的角度来看,A 是 Hermitian 矩阵且仅提供下三角部分。

注意

在实践中,一个正定矩阵可能无法进行不完全Cholesky分解。据我们所知,只有矩阵M能保证不完全Cholesky分解的存在。如果csric02()在Cholesky分解过程中失败并报告数值为零,则可能意味着不完全Cholesky分解不存在。

例如,假设A是一个实数m乘以m矩阵,以下代码求解预处理系统M*y = x,其中M是Cholesky分解L与其转置矩阵的乘积。

\[M = LL^{H}\]
// Suppose that A is m x m sparse matrix represented by CSR format,
// Assumption:
// - handle is already created by cusparseCreate(),
// - (d_csrRowPtr, d_csrColInd, d_csrVal) is CSR of A on device memory,
// - d_x is right hand side vector on device memory,
// - d_y is solution vector on device memory.
// - d_z is intermediate result on device memory.

cusparseMatDescr_t descr_M = 0;
cusparseMatDescr_t descr_L = 0;
csric02Info_t info_M  = 0;
csrsv2Info_t  info_L  = 0;
csrsv2Info_t  info_Lt = 0;
int pBufferSize_M;
int pBufferSize_L;
int pBufferSize_Lt;
int pBufferSize;
void *pBuffer = 0;
int structural_zero;
int numerical_zero;
const double alpha = 1.;
const cusparseSolvePolicy_t policy_M  = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_L  = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_Lt = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
const cusparseOperation_t trans_L  = CUSPARSE_OPERATION_NON_TRANSPOSE;
const cusparseOperation_t trans_Lt = CUSPARSE_OPERATION_TRANSPOSE;

// step 1: create a descriptor which contains
// - matrix M is base-1
// - matrix L is base-1
// - matrix L is lower triangular
// - matrix L has non-unit diagonal
cusparseCreateMatDescr(&descr_M);
cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL);

cusparseCreateMatDescr(&descr_L);
cusparseSetMatIndexBase(descr_L, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_L, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatFillMode(descr_L, CUSPARSE_FILL_MODE_LOWER);
cusparseSetMatDiagType(descr_L, CUSPARSE_DIAG_TYPE_NON_UNIT);

// step 2: create a empty info structure
// we need one info for csric02 and two info's for csrsv2
cusparseCreateCsric02Info(&info_M);
cusparseCreateCsrsv2Info(&info_L);
cusparseCreateCsrsv2Info(&info_Lt);

// step 3: query how much memory used in csric02 and csrsv2, and allocate the buffer
cusparseDcsric02_bufferSize(handle, m, nnz,
    descr_M, d_csrVal, d_csrRowPtr, d_csrColInd, info_M, &bufferSize_M);
cusparseDcsrsv2_bufferSize(handle, trans_L, m, nnz,
    descr_L, d_csrVal, d_csrRowPtr, d_csrColInd, info_L, &pBufferSize_L);
cusparseDcsrsv2_bufferSize(handle, trans_Lt, m, nnz,
    descr_L, d_csrVal, d_csrRowPtr, d_csrColInd, info_Lt,&pBufferSize_Lt);

pBufferSize = max(bufferSize_M, max(pBufferSize_L, pBufferSize_Lt));

// pBuffer returned by cudaMalloc is automatically aligned to 128 bytes.
cudaMalloc((void**)&pBuffer, pBufferSize);

// step 4: perform analysis of incomplete Cholesky on M
//         perform analysis of triangular solve on L
//         perform analysis of triangular solve on L'
// The lower triangular part of M has the same sparsity pattern as L, so
// we can do analysis of csric02 and csrsv2 simultaneously.

cusparseDcsric02_analysis(handle, m, nnz, descr_M,
    d_csrVal, d_csrRowPtr, d_csrColInd, info_M,
    policy_M, pBuffer);
status = cusparseXcsric02_zeroPivot(handle, info_M, &structural_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("A(%d,%d) is missing\n", structural_zero, structural_zero);
}

cusparseDcsrsv2_analysis(handle, trans_L, m, nnz, descr_L,
    d_csrVal, d_csrRowPtr, d_csrColInd,
    info_L, policy_L, pBuffer);

cusparseDcsrsv2_analysis(handle, trans_Lt, m, nnz, descr_L,
    d_csrVal, d_csrRowPtr, d_csrColInd,
    info_Lt, policy_Lt, pBuffer);

// step 5: M = L * L'
cusparseDcsric02(handle, m, nnz, descr_M,
    d_csrVal, d_csrRowPtr, d_csrColInd, info_M, policy_M, pBuffer);
status = cusparseXcsric02_zeroPivot(handle, info_M, &numerical_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("L(%d,%d) is zero\n", numerical_zero, numerical_zero);
}

// step 6: solve L*z = x
cusparseDcsrsv2_solve(handle, trans_L, m, nnz, &alpha, descr_L, // replace with cusparseSpSV
   d_csrVal, d_csrRowPtr, d_csrColInd, info_L,
   d_x, d_z, policy_L, pBuffer);

// step 7: solve L'*y = z
cusparseDcsrsv2_solve(handle, trans_Lt, m, nnz, &alpha, descr_L, // replace with cusparseSpSV
   d_csrVal, d_csrRowPtr, d_csrColInd, info_Lt,
   d_z, d_y, policy_Lt, pBuffer);

// step 6: free resources
cudaFree(pBuffer);
cusparseDestroyMatDescr(descr_M);
cusparseDestroyMatDescr(descr_L);
cusparseDestroyCsric02Info(info_M);
cusparseDestroyCsrsv2Info(info_L);
cusparseDestroyCsrsv2Info(info_Lt);
cusparseDestroy(handle);

如果pBuffer != NULL,该函数支持以下属性:

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数和列数。

nnz

矩阵 A 的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA_valM

矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素的数组。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾的下一个位置。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

信息

包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由csric02_bufferSize()返回。

输出

csrValA_valM

矩阵包含不完全Cholesky下三角因子。

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.4. cusparseXcsric02_zeroPivot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseXcsric02_zeroPivot(cusparseHandle_t handle,
                           csric02Info_t    info,
                           int*             position)

如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOTposition=j表示A(j,j)存在结构零或数值零;否则,position=-1

position 可以是基于0或基于1的索引,与矩阵的索引方式相同。

函数 cusparseXcsric02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 以确保之前的所有内核操作都已完成。

position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。

  • 该例程不需要额外的存储空间。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

信息

info 包含结构零或数值零,如果用户已经调用了 csric02_analysis()csric02()

输出

position

如果没有结构或数值上的零值,position为-1;否则,如果A(j,j)缺失或L(j,j)为零,则position=j

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.5. cusparsebsric02_bufferSize() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsric02_bufferSize(cusparseHandle_t         handle,
                            cusparseDirection_t      dirA,
                            int                      mb,
                            int                      nnzb,
                            const cusparseMatDescr_t descrA,
                            float*                   bsrValA,
                            const int*               bsrRowPtrA,
                            const int*               bsrColIndA,
                            int                      blockDim,
                            bsric02Info_t            info,
                            int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseDbsric02_bufferSize(cusparseHandle_t         handle,
                            cusparseDirection_t      dirA,
                            int                      mb,
                            int                      nnzb,
                            const cusparseMatDescr_t descrA,
                            double*                  bsrValA,
                            const int*               bsrRowPtrA,
                            const int*               bsrColIndA,
                            int                      blockDim,
                            bsric02Info_t            info,
                            int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseCbsric02_bufferSize(cusparseHandle_t         handle,
                            cusparseDirection_t      dirA,
                            int                      mb,
                            int                      nnzb,
                            const cusparseMatDescr_t descrA,
                            cuComplex*               bsrValA,
                            const int*               bsrRowPtrA,
                            const int*               bsrColIndA,
                            int                      blockDim,
                            bsric02Info_t            info,
                            int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseZbsric02_bufferSize(cusparseHandle_t         handle,
                            cusparseDirection_t      dirA,
                            int                      mb,
                            int                      nnzb,
                            const cusparseMatDescr_t descrA,
                            cuDoubleComplex*         bsrValA,
                            const int*               bsrRowPtrA,
                            const int*               bsrColIndA,
                            int                      blockDim,
                            bsric02Info_t            info,
                            int*                     pBufferSizeInBytes)

该函数返回用于计算0填充且无旋转的不完全Cholesky分解的缓冲区大小

\[A \approx LL^{H}\]

A 是一个 (mb*blockDim)*(mb*blockDim) 稀疏矩阵,由三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义。

缓冲区大小取决于mbblockDim的维度以及矩阵nnzb的非零块数量。如果用户更改了矩阵,必须再次调用bsric02_bufferSize()以获取正确的缓冲区大小;否则可能会出现段错误。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

矩阵A的块行数和块列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,大于零。

输出

信息

根据不同算法记录内部状态。

pBufferSizeInBytes

bsric02_analysis()bsric02()中使用的缓冲区字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.6. cusparsebsric02_analysis() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsric02_analysis(cusparseHandle_t        handle,
                          cusparseDirection_t     dirA,
                          int                      mb,
                          int                      nnzb,
                          const cusparseMatDescr_t descrA,
                          const float*             bsrValA,
                          const int*               bsrRowPtrA,
                          const int*               bsrColIndA,
                          int                      blockDim,
                          bsric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

cusparseStatus_t
cusparseDbsric02_analysis(cusparseHandle_t        handle,
                          cusparseDirection_t     dirA,
                          int                      mb,
                          int                      nnzb,
                          const cusparseMatDescr_t descrA,
                          const double*            bsrValA,
                          const int*               bsrRowPtrA,
                          const int*               bsrColIndA,
                          int                      blockDim,
                          bsric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

cusparseStatus_t
cusparseCbsric02_analysis(cusparseHandle_t        handle,
                          cusparseDirection_t     dirA,
                          int                      mb,
                          int                      nnzb,
                          const cusparseMatDescr_t descrA,
                          const cuComplex*         bsrValA,
                          const int*               bsrRowPtrA,
                          const int*               bsrColIndA,
                          int                      blockDim,
                          bsric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

cusparseStatus_t
cusparseZbsric02_analysis(cusparseHandle_t        handle,
                          cusparseDirection_t     dirA,
                          int                      mb,
                          int                      nnzb,
                          const cusparseMatDescr_t descrA,
                          const cuDoubleComplex*   bsrValA,
                          const int*               bsrRowPtrA,
                          const int*               bsrColIndA,
                          int                      blockDim,
                          bsric02Info_t            info,
                          cusparseSolvePolicy_t    policy,
                          void*                    pBuffer)

该函数执行不完全Cholesky分解的分析阶段,采用0填充且无主元选择

\[A \approx LL^{H}\]

A 是一个 (mb*blockDim)x(mb*blockDim) 的稀疏矩阵,由三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式为列优先或行优先,由参数 dirA 决定,该参数可以是 CUSPARSE_DIRECTION_COLUMNCUSPARSE_DIRECTION_ROW。矩阵类型必须为 CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。

此函数需要由bsric02_bufferSize90返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

函数bsric02_analysis()会报告结构零并计算存储在info不透明结构中的层级信息。该层级信息可以在不完全Cholesky分解过程中提取更多并行性。但bsric02()无需层级信息也可执行。若要禁用层级信息,用户需将bsric02[_analysis| ]的参数policy指定为CUSPARSE_SOLVE_POLICY_NO_LEVEL

函数 bsric02_analysis 总是报告第一个结构零,即使参数 policy 设置为 CUSPARSE_SOLVE_POLICY_NO_LEVEL。用户必须调用 cusparseXbsric02_zeroPivot() 来定位结构零的位置。

是否在bsric02_analysis()报告结构零时调用bsric02()由用户决定。在这种情况下,用户仍可以调用bsric02(),它会在结构零的相同位置返回数值零。但该结果没有意义。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

矩阵A的块行数和块列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度;必须大于零。

信息

使用cusparseCreateBsric02Info()初始化的结构体。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由bsric02_bufferSize()返回。

输出

信息

填充了分析阶段收集的信息的结构(应原封不动地传递给求解阶段)。

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.7. cusparsebsric02() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsric02(cusparseHandle_t         handle,
                 cusparseDirection_t      dirA,
                 int                      mb,
                 int                      nnzb,
                 const cusparseMatDescr_t descrA,
                 float*                   bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 bsric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

cusparseStatus_t
cusparseDbsric02(cusparseHandle_t         handle,
                 cusparseDirection_t      dirA,
                 int                      mb,
                 int                      nnzb,
                 const cusparseMatDescr_t descrA,
                 double*                  bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 bsric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

cusparseStatus_t
cusparseCbsric02(cusparseHandle_t         handle,
                 cusparseDirection_t      dirA,
                 int                      mb,
                 int                      nnzb,
                 const cusparseMatDescr_t descrA,
                 cuComplex*               bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 bsric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

cusparseStatus_t
cusparseZbsric02(cusparseHandle_t         handle,
                 cusparseDirection_t      dirA,
                 int                      mb,
                 int                      nnzb,
                 const cusparseMatDescr_t descrA,
                 cuDoubleComplex*         bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 bsric02Info_t            info,
                 cusparseSolvePolicy_t    policy,
                 void*                    pBuffer)

该函数执行不完全Cholesky分解的求解阶段,采用0填充且无主元旋转。

\[A \approx LL^{H}\]

A 是一个 (mb*blockDim)x(mb*blockDim) 的稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式为列优先或行优先,由参数 dirA 决定,该参数可以是 CUSPARSE_DIRECTION_COLUMNCUSPARSE_DIRECTION_ROW。矩阵类型必须为 CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。

此函数需要由bsric02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

虽然bsric02()可以在没有层级信息的情况下执行,但用户必须注意一致性。如果bsric02_analysis()调用时使用策略CUSPARSE_SOLVE_POLICY_USE_LEVEL,那么bsric02()可以在有或没有层级的情况下运行。另一方面,如果bsric02_analysis()调用时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL,那么bsric02()只能接受CUSPARSE_SOLVE_POLICY_NO_LEVEL;否则将返回CUSPARSE_STATUS_INVALID_VALUE

函数 bsric02() 的行为与 csric02() 相同。也就是说,bsr2csr(bsric02(A)) = csric02(bsr2csr(A))csric02() 的数值零意味着存在某些零元素 L(j,j)。而 bsric02() 的数值零则表示存在某些不可逆的块 Lj,j)

函数 bsric02 会报告第一个数值零,包括结构零。用户必须调用 cusparseXbsric02_zeroPivot() 来确认数值零的位置。

bsric02() 函数仅使用矩阵 A 的下三角部分进行分解。严格上三角部分会被忽略且不会被触及。无论 A 是否为 Hermitian 矩阵都不影响。换句话说,从 bsric02() 的角度来看,A 被视为 Hermitian 矩阵且仅提供下三角部分。此外,对角块对角线元素的虚部也会被忽略。

例如,假设 A 是一个实数 m×m 矩阵,其中 m=mb*blockDim。以下代码求解预处理系统 M*y = x,其中 M 是 Cholesky 分解 L 与其转置的乘积。

\[M = LL^{H}\]
// Suppose that A is m x m sparse matrix represented by BSR format,
// The number of block rows/columns is mb, and
// the number of nonzero blocks is nnzb.
// Assumption:
// - handle is already created by cusparseCreate(),
// - (d_bsrRowPtr, d_bsrColInd, d_bsrVal) is BSR of A on device memory,
// - d_x is right hand side vector on device memory,
// - d_y is solution vector on device memory.
// - d_z is intermediate result on device memory.
// - d_x, d_y and d_z are of size m.
cusparseMatDescr_t descr_M = 0;
cusparseMatDescr_t descr_L = 0;
bsric02Info_t info_M  = 0;
bsrsv2Info_t  info_L  = 0;
bsrsv2Info_t  info_Lt = 0;
int pBufferSize_M;
int pBufferSize_L;
int pBufferSize_Lt;
int pBufferSize;
void *pBuffer = 0;
int structural_zero;
int numerical_zero;
const double alpha = 1.;
const cusparseSolvePolicy_t policy_M  = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_L  = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_Lt = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
const cusparseOperation_t trans_L  = CUSPARSE_OPERATION_NON_TRANSPOSE;
const cusparseOperation_t trans_Lt = CUSPARSE_OPERATION_TRANSPOSE;
const cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;

// step 1: create a descriptor which contains
// - matrix M is base-1
// - matrix L is base-1
// - matrix L is lower triangular
// - matrix L has non-unit diagonal
cusparseCreateMatDescr(&descr_M);
cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL);

cusparseCreateMatDescr(&descr_L);
cusparseSetMatIndexBase(descr_L, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_L, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatFillMode(descr_L, CUSPARSE_FILL_MODE_LOWER);
cusparseSetMatDiagType(descr_L, CUSPARSE_DIAG_TYPE_NON_UNIT);

// step 2: create a empty info structure
// we need one info for bsric02 and two info's for bsrsv2
cusparseCreateBsric02Info(&info_M);
cusparseCreateBsrsv2Info(&info_L);
cusparseCreateBsrsv2Info(&info_Lt);

// step 3: query how much memory used in bsric02 and bsrsv2, and allocate the buffer
cusparseDbsric02_bufferSize(handle, dir, mb, nnzb,
    descr_M, d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_M, &bufferSize_M);
cusparseDbsrsv2_bufferSize(handle, dir, trans_L, mb, nnzb,
    descr_L, d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_L, &pBufferSize_L);
cusparseDbsrsv2_bufferSize(handle, dir, trans_Lt, mb, nnzb,
    descr_L, d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_Lt, &pBufferSize_Lt);

pBufferSize = max(bufferSize_M, max(pBufferSize_L, pBufferSize_Lt));

// pBuffer returned by cudaMalloc is automatically aligned to 128 bytes.
cudaMalloc((void**)&pBuffer, pBufferSize);

// step 4: perform analysis of incomplete Cholesky on M
//         perform analysis of triangular solve on L
//         perform analysis of triangular solve on L'
// The lower triangular part of M has the same sparsity pattern as L, so
// we can do analysis of bsric02 and bsrsv2 simultaneously.

cusparseDbsric02_analysis(handle, dir, mb, nnzb, descr_M,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_M,
    policy_M, pBuffer);
status = cusparseXbsric02_zeroPivot(handle, info_M, &structural_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("A(%d,%d) is missing\n", structural_zero, structural_zero);
}

cusparseDbsrsv2_analysis(handle, dir, trans_L, mb, nnzb, descr_L,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim,
    info_L, policy_L, pBuffer);

cusparseDbsrsv2_analysis(handle, dir, trans_Lt, mb, nnzb, descr_L,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim,
    info_Lt, policy_Lt, pBuffer);

// step 5: M = L * L'
cusparseDbsric02_solve(handle, dir, mb, nnzb, descr_M,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_M, policy_M, pBuffer);
status = cusparseXbsric02_zeroPivot(handle, info_M, &numerical_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("L(%d,%d) is not positive definite\n", numerical_zero, numerical_zero);
}

// step 6: solve L*z = x
cusparseDbsrsv2_solve(handle, dir, trans_L, mb, nnzb, &alpha, descr_L,
   d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_L,
   d_x, d_z, policy_L, pBuffer);

// step 7: solve L'*y = z
cusparseDbsrsv2_solve(handle, dir, trans_Lt, mb, nnzb, &alpha, descr_L,
   d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_Lt,
   d_z, d_y, policy_Lt, pBuffer);

// step 6: free resources
cudaFree(pBuffer);
cusparseDestroyMatDescr(descr_M);
cusparseDestroyMatDescr(descr_L);
cusparseDestroyBsric02Info(info_M);
cusparseDestroyBsrsv2Info(info_L);
cusparseDestroyBsrsv2Info(info_Lt);
cusparseDestroy(handle);

如果pBuffer != NULL,该函数支持以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

矩阵A的块行数和块列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,大于零。

信息

包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区,其大小由bsric02_bufferSize()返回。

输出

bsrValA

矩阵包含不完全Cholesky下三角因子。

有关返回状态的描述,请参见cusparseStatus_t

5.7.1.8. cusparseXbsric02_zeroPivot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseXbsric02_zeroPivot(cusparseHandle_t handle,
                           bsric02Info_t    info,
                           int*             position)

如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOTposition=j表示A(j,j)存在结构零或数值零(该块不是正定的)。否则position=-1

position 可以是基于0或基于1的索引,与矩阵的索引方式相同。

函数 cusparseXbsric02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。

position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。

  • 该例程不需要额外的存储空间。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

信息

info 如果用户已经调用了 bsric02_analysis()bsric02(),则包含结构零或数值零。

输出

position

如果没有结构或数值上的零值,position为-1;否则如果A(j,j)缺失或L(j,j)不是正定矩阵,则position=j

有关返回状态的描述,请参见cusparseStatus_t

5.7.2. 不完全LU分解:级别0 [已弃用]

本节讨论了ilu0的不同算法。

5.7.2.1. cusparsecsrilu02_numericBoost() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsrilu02_numericBoost(cusparseHandle_t handle,
                               csrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               float*           boost_val)

cusparseStatus_t
cusparseDcsrilu02_numericBoost(cusparseHandle_t handle,
                               csrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               double*          boost_val)

cusparseStatus_t
cusparseCcsrilu02_numericBoost(cusparseHandle_t handle,
                               csrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               cuComplex*       boost_val)

cusparseStatus_t
cusparseZcsrilu02_numericBoost(cusparseHandle_t handle,
                               csrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               cuDoubleComplex* boost_val)

用户可以使用一个提升值来替代不完全LU分解中的数值。tol用于确定数值零,而boost_val则用于替换数值零。具体行为如下:

如果 tol >= fabs(A(j,j)),则 A(j,j)=boost_val

要启用boost值,用户必须在调用csrilu02()之前将参数enable_boost设为1。要禁用boost值,用户可以再次调用csrilu02_numericBoost()并将参数enable_boost设为0。

如果 enable_boost=0,则忽略 tolboost_val

tolboost_val 可以存放在主机内存或设备内存中。用户可以通过 cusparseSetPointerMode() 设置合适的模式。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄

信息

使用cusparseCreateCsrilu02Info()初始化的结构

enable_boost

通过enable_boost=0禁用加速;否则,将启用加速

tol

用于确定数值零的容差

boost_val

用于替换数值零的boost值

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.2. cusparsecsrilu02_bufferSize() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsrilu02_bufferSize(cusparseHandle_t         handle,
                             int                      m,
                             int                      nnz,
                             const cusparseMatDescr_t descrA,
                             float*                   csrValA,
                             const int*               csrRowPtrA,
                             const int*               csrColIndA,
                             csrilu02Info_t           info,
                             int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseDcsrilu02_bufferSize(cusparseHandle_t         handle,
                             int                      m,
                             int                      nnz,
                             const cusparseMatDescr_t descrA,
                             double*                  csrValA,
                             const int*               csrRowPtrA,
                             const int*               csrColIndA,
                             csrilu02Info_t           info,
                             int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseCcsrilu02_bufferSize(cusparseHandle_t         handle,
                             int                      m,
                             int                      nnz,
                             const cusparseMatDescr_t descrA,
                             cuComplex*               csrValA,
                             const int*               csrRowPtrA,
                             const int*               csrColIndA,
                             csrilu02Info_t           info,
                             int*                     pBufferSizeInBytes)

cusparseStatus_t
cusparseZcsrilu02_bufferSize(cusparseHandle_t         handle,
                             int                      m,
                             int                      nnz,
                             const cusparseMatDescr_t descrA,
                             cuDoubleComplex*         csrValA,
                             const int*               csrRowPtrA,
                             const int*               csrColIndA,
                             csrilu02Info_t           info,
                             int*                     pBufferSizeInBytes)

该函数返回用于计算不完全LU分解的缓冲区大小,其中填充量为\(0\)且不进行主元选取:

\[A \approx LU\]

A 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValAcsrRowPtrAcsrColIndA 以 CSR 存储格式定义。

缓冲区大小取决于矩阵的维度m和非零元素数量nnz。如果用户更改了矩阵,必须再次调用csrilu02_bufferSize()以获取正确的缓冲区大小;否则可能会出现段错误。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数和列数。

nnz

矩阵 A 的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

<type> 矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素的数组。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾的下一个位置。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

输出

信息

根据不同算法记录内部状态

pBufferSizeInBytes

csrilu02_analysis()csrilu02()中使用的缓冲区字节数

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.3. cusparsecsrilu02_analysis() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsrilu02_analysis(cusparseHandle_t         handle,
                           int                      m,
                           int                      nnz,
                           const cusparseMatDescr_t descrA,
                           const float*             csrValA,
                           const int*               csrRowPtrA,
                           const int*               csrColIndA,
                           csrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

cusparseStatus_t
cusparseDcsrilu02_analysis(cusparseHandle_t         handle,
                           int                      m,
                           int                      nnz,
                           const cusparseMatDescr_t descrA,
                           const double*            csrValA,
                           const int*               csrRowPtrA,
                           const int*               csrColIndA,
                           csrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

cusparseStatus_t
cusparseCcsrilu02_analysis(cusparseHandle_t         handle,
                           int                      m,
                           int                      nnz,
                           const cusparseMatDescr_t descrA,
                           const cuComplex*         csrValA,
                           const int*               csrRowPtrA,
                           const int*               csrColIndA,
                           csrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

cusparseStatus_t
cusparseZcsrilu02_analysis(cusparseHandle_t         handle,
                           int                      m,
                           int                      nnz,
                           const cusparseMatDescr_t descrA,
                           const cuDoubleComplex*   csrValA,
                           const int*               csrRowPtrA,
                           const int*               csrColIndA,
                           csrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

该函数执行不完全-LU分解的分析阶段,采用\(0\)填充且无主元置换:

\[A \approx LU\]

A 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValAcsrRowPtrAcsrColIndA 以 CSR 存储格式定义。

此函数需要由csrilu02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

函数 csrilu02_analysis() 会报告结构零并计算存储在 info 不透明结构中的层级信息。该层级信息可在不完全LU分解过程中提取更多并行性;但 csrilu02() 可不依赖层级信息执行。若要禁用层级信息,用户需将 csrilu02() 的策略指定为 CUSPARSE_SOLVE_POLICY_NO_LEVEL

是否在csrilu02_analysis()报告结构零时调用csrilu02()由用户决定。在这种情况下,用户仍可以调用csrilu02(),它将在结构零的相同位置返回数值零。但该结果没有意义。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数和列数。

nnz

矩阵 A 的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

<type> 矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素的数组。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾的下一个位置。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

信息

使用cusparseCreateCsrilu02Info()初始化的结构。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区,其大小由csrilu02_bufferSize()返回。

输出

信息

填充了分析阶段收集的信息的结构(应原封不动地传递给求解阶段)。

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.4. cusparsecsrilu02() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsrilu02(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  float*                   csrValA_valM,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  csrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

cusparseStatus_t
cusparseDcsrilu02(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  double*                  csrValA_valM,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  csrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

cusparseStatus_t
cusparseCcsrilu02(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  cuComplex*               csrValA_valM,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  csrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

cusparseStatus_t
cusparseZcsrilu02(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  cuDoubleComplex*         csrValA_valM,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  csrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

该函数执行不完全-LU分解的求解阶段,填充量为\(0\)且不进行主元选择:

\[A \approx LU\]

A 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValA_valMcsrRowPtrAcsrColIndA 以 CSR 存储格式定义。

此函数需要由csrilu02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

矩阵类型必须为CUSPARSE_MATRIX_TYPE_GENERAL。填充模式和对角线类型将被忽略。

虽然csrilu02()可以在没有层级信息的情况下执行,但用户仍需注意一致性。如果csrilu02_analysis()调用时使用策略CUSPARSE_SOLVE_POLICY_USE_LEVEL,那么csrilu02()可以在有或没有层级的情况下运行。另一方面,如果csrilu02_analysis()调用时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL,那么csrilu02()只能接受CUSPARSE_SOLVE_POLICY_NO_LEVEL;否则将返回CUSPARSE_STATUS_INVALID_VALUE

函数 csrilu02() 会报告第一个数值零,包括结构零。用户必须调用 cusparseXcsrilu02_zeroPivot() 来定位数值零的位置。

例如,假设 A 是一个实数 \(m \times m\) 矩阵,以下代码求解预处理系统 M*y = x,其中 M 是 LU 因子 LU 的乘积。

// Suppose that A is m x m sparse matrix represented by CSR format,
// Assumption:
// - handle is already created by cusparseCreate(),
// - (d_csrRowPtr, d_csrColInd, d_csrVal) is CSR of A on device memory,
// - d_x is right hand side vector on device memory,
// - d_y is solution vector on device memory.
// - d_z is intermediate result on device memory.

cusparseMatDescr_t descr_M = 0;
cusparseMatDescr_t descr_L = 0;
cusparseMatDescr_t descr_U = 0;
csrilu02Info_t info_M  = 0;
csrsv2Info_t  info_L  = 0;
csrsv2Info_t  info_U  = 0;
int pBufferSize_M;
int pBufferSize_L;
int pBufferSize_U;
int pBufferSize;
void *pBuffer = 0;
int structural_zero;
int numerical_zero;
const double alpha = 1.;
const cusparseSolvePolicy_t policy_M = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_L = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_U = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
const cusparseOperation_t trans_L  = CUSPARSE_OPERATION_NON_TRANSPOSE;
const cusparseOperation_t trans_U  = CUSPARSE_OPERATION_NON_TRANSPOSE;

// step 1: create a descriptor which contains
// - matrix M is base-1
// - matrix L is base-1
// - matrix L is lower triangular
// - matrix L has unit diagonal
// - matrix U is base-1
// - matrix U is upper triangular
// - matrix U has non-unit diagonal
cusparseCreateMatDescr(&descr_M);
cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL);

cusparseCreateMatDescr(&descr_L);
cusparseSetMatIndexBase(descr_L, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_L, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatFillMode(descr_L, CUSPARSE_FILL_MODE_LOWER);
cusparseSetMatDiagType(descr_L, CUSPARSE_DIAG_TYPE_UNIT);

cusparseCreateMatDescr(&descr_U);
cusparseSetMatIndexBase(descr_U, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_U, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatFillMode(descr_U, CUSPARSE_FILL_MODE_UPPER);
cusparseSetMatDiagType(descr_U, CUSPARSE_DIAG_TYPE_NON_UNIT);

// step 2: create a empty info structure
// we need one info for csrilu02 and two info's for csrsv2
cusparseCreateCsrilu02Info(&info_M);
cusparseCreateCsrsv2Info(&info_L);
cusparseCreateCsrsv2Info(&info_U);

// step 3: query how much memory used in csrilu02 and csrsv2, and allocate the buffer
cusparseDcsrilu02_bufferSize(handle, m, nnz,
    descr_M, d_csrVal, d_csrRowPtr, d_csrColInd, info_M, &pBufferSize_M);
cusparseDcsrsv2_bufferSize(handle, trans_L, m, nnz,
    descr_L, d_csrVal, d_csrRowPtr, d_csrColInd, info_L, &pBufferSize_L);
cusparseDcsrsv2_bufferSize(handle, trans_U, m, nnz,
    descr_U, d_csrVal, d_csrRowPtr, d_csrColInd, info_U, &pBufferSize_U);

pBufferSize = max(pBufferSize_M, max(pBufferSize_L, pBufferSize_U));

// pBuffer returned by cudaMalloc is automatically aligned to 128 bytes.
cudaMalloc((void**)&pBuffer, pBufferSize);

// step 4: perform analysis of incomplete Cholesky on M
//         perform analysis of triangular solve on L
//         perform analysis of triangular solve on U
// The lower(upper) triangular part of M has the same sparsity pattern as L(U),
// we can do analysis of csrilu0 and csrsv2 simultaneously.

cusparseDcsrilu02_analysis(handle, m, nnz, descr_M,
    d_csrVal, d_csrRowPtr, d_csrColInd, info_M,
    policy_M, pBuffer);
status = cusparseXcsrilu02_zeroPivot(handle, info_M, &structural_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("A(%d,%d) is missing\n", structural_zero, structural_zero);
}

cusparseDcsrsv2_analysis(handle, trans_L, m, nnz, descr_L,
    d_csrVal, d_csrRowPtr, d_csrColInd,
    info_L, policy_L, pBuffer);

cusparseDcsrsv2_analysis(handle, trans_U, m, nnz, descr_U,
    d_csrVal, d_csrRowPtr, d_csrColInd,
    info_U, policy_U, pBuffer);

// step 5: M = L * U
cusparseDcsrilu02(handle, m, nnz, descr_M,
    d_csrVal, d_csrRowPtr, d_csrColInd, info_M, policy_M, pBuffer);
status = cusparseXcsrilu02_zeroPivot(handle, info_M, &numerical_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == status){
   printf("U(%d,%d) is zero\n", numerical_zero, numerical_zero);
}

// step 6: solve L*z = x
cusparseDcsrsv2_solve(handle, trans_L, m, nnz, &alpha, descr_L, // replace with cusparseSpSV
   d_csrVal, d_csrRowPtr, d_csrColInd, info_L,
   d_x, d_z, policy_L, pBuffer);

// step 7: solve U*y = z
cusparseDcsrsv2_solve(handle, trans_U, m, nnz, &alpha, descr_U, // replace with cusparseSpSV
   d_csrVal, d_csrRowPtr, d_csrColInd, info_U,
   d_z, d_y, policy_U, pBuffer);

// step 6: free resources
cudaFree(pBuffer);
cusparseDestroyMatDescr(descr_M);
cusparseDestroyMatDescr(descr_L);
cusparseDestroyMatDescr(descr_U);
cusparseDestroyCsrilu02Info(info_M);
cusparseDestroyCsrsv2Info(info_L);
cusparseDestroyCsrsv2Info(info_U);
cusparseDestroy(handle);

如果pBuffer != NULL,该函数支持以下属性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数和列数。

nnz

矩阵 A 的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA_valM

<type> 矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素的数组。

csrRowPtrA

一个包含m\(+ 1\)个元素的整数数组,其中包含每行的起始位置以及最后一行末尾的下一个位置。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

信息

包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由csrilu02_bufferSize()返回。

输出

csrValA_valM

矩阵包含不完全LU分解的下三角和上三角因子。

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.5. cusparseXcsrilu02_zeroPivot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseXcsrilu02_zeroPivot(cusparseHandle_t handle,
                            csrilu02Info_t   info,
                            int*             position)

如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOTposition=j表示A(j,j)存在结构零或数值零;否则,position=-1

position 可以是基于0或基于1的索引,与矩阵的索引方式相同。

函数 cusparseXcsrilu02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。

position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。

  • 该例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

信息

info 包含结构性零或数值零,如果用户已经调用过 csrilu02_analysis()csrilu02()

输出

position

如果没有结构或数值上的零值,position为-1;否则如果A(j,j)缺失或U(j,j)为零,则position=j

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.6. cusparsebsrilu02_numericBoost() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrilu02_numericBoost(cusparseHandle_t handle,
                               bsrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               float*           boost_val)

cusparseStatus_t
cusparseDbsrilu02_numericBoost(cusparseHandle_t handle,
                               bsrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               double*          boost_val)

cusparseStatus_t
cusparseCbsrilu02_numericBoost(cusparseHandle_t handle,
                               bsrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               cuComplex*       boost_val)

cusparseStatus_t
cusparseZbsrilu02_numericBoost(cusparseHandle_t handle,
                               bsrilu02Info_t   info,
                               int              enable_boost,
                               double*          tol,
                               cuDoubleComplex* boost_val)

用户可以使用一个提升值来替代不完全LU分解中的数值。参数tol用于确定数值零,而boost_val用于替换数值零。具体行为如下:

如果 tol >= fabs(A(j,j)),则将块 A(j,j) 的每个对角元素重置为 boost_val

要启用加速值,用户需在调用bsrilu02()前将参数enable_boost设为1。要禁用加速值,用户可调用bsrilu02_numericBoost()并将参数enable_boost=0

如果 enable_boost=0,则忽略 tolboost_val

tolboost_val 可以存储在主机内存或设备内存中。用户可以通过 cusparseSetPointerMode() 设置适当的模式。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

信息

使用cusparseCreateBsrilu02Info()初始化的结构。

enable_boost

通过设置enable_boost=0来禁用boost。否则,boost将保持启用状态。

tol

用于确定数值零的容差。

boost_val

用于替换数值零的boost值。

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.7. cusparsebsrilu02_bufferSize() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrilu02_bufferSize(cusparseHandle_t handle,
                             cusparseDirection_t dirA,
                             int mb,
                             int nnzb,
                             const cusparseMatDescr_t descrA,
                             float *bsrValA,
                             const int *bsrRowPtrA,
                             const int *bsrColIndA,
                             int blockDim,
                             bsrilu02Info_t info,
                             int *pBufferSizeInBytes);

cusparseStatus_t
cusparseDbsrilu02_bufferSize(cusparseHandle_t handle,
                             cusparseDirection_t dirA,
                             int mb,
                             int nnzb,
                             const cusparseMatDescr_t descrA,
                             double *bsrValA,
                             const int *bsrRowPtrA,
                             const int *bsrColIndA,
                             int blockDim,
                             bsrilu02Info_t info,
                             int *pBufferSizeInBytes);

cusparseStatus_t
cusparseCbsrilu02_bufferSize(cusparseHandle_t handle,
                             cusparseDirection_t dirA,
                             int mb,
                             int nnzb,
                             const cusparseMatDescr_t descrA,
                             cuComplex *bsrValA,
                             const int *bsrRowPtrA,
                             const int *bsrColIndA,
                             int blockDim,
                             bsrilu02Info_t info,
                             int *pBufferSizeInBytes);

cusparseStatus_t
cusparseZbsrilu02_bufferSize(cusparseHandle_t handle,
                             cusparseDirection_t dirA,
                             int mb,
                             int nnzb,
                             const cusparseMatDescr_t descrA,
                             cuDoubleComplex *bsrValA,
                             const int *bsrRowPtrA,
                             const int *bsrColIndA,
                             int blockDim,
                             bsrilu02Info_t info,
                             int *pBufferSizeInBytes);

该函数返回用于计算0填充且无旋转的不完全LU分解的缓冲区大小。

\[A \approx LU\]

A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义。

缓冲区大小取决于mbblockDim的维度以及矩阵nnzb的非零块数量。如果用户更改了矩阵,必须再次调用bsrilu02_bufferSize()以获取正确的缓冲区大小;否则可能会出现段错误。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

矩阵A的行列块数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,大于零。

输出

信息

根据不同算法记录内部状态。

pBufferSizeInBytes

bsrilu02_analysis()bsrilu02()中使用的缓冲区字节数。

返回状态

CUSPARSE_STATUS_SUCCESS

操作已成功完成。

CUSPARSE_STATUS_NOT_INITIALIZED

库未初始化。

CUSPARSE_STATUS_ALLOC_FAILED

资源无法分配。

CUSPARSE_STATUS_INVALID_VALUE

传递了无效参数(mb,nnzb<=0),基索引不是0或1。

CUSPARSE_STATUS_ARCH_MISMATCH

该设备仅支持计算能力2.0及以上版本。

CUSPARSE_STATUS_INTERNAL_ERROR

内部操作失败。

CUSPARSE_STATUS_MATRIX_TYPE_NOT_SUPPORTED

不支持该矩阵类型。

5.7.2.8. cusparsebsrilu02_analysis() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrilu02_analysis(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           float*                   bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

cusparseStatus_t
cusparseDbsrilu02_analysis(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           double*                  bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

cusparseStatus_t
cusparseCbsrilu02_analysis(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           cuComplex*               bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

cusparseStatus_t
cusparseZbsrilu02_analysis(cusparseHandle_t         handle,
                           cusparseDirection_t      dirA,
                           int                      mb,
                           int                      nnzb,
                           const cusparseMatDescr_t descrA,
                           cuDoubleComplex*         bsrValA,
                           const int*               bsrRowPtrA,
                           const int*               bsrColIndA,
                           int                      blockDim,
                           bsrilu02Info_t           info,
                           cusparseSolvePolicy_t    policy,
                           void*                    pBuffer)

该函数执行不完全LU分解的分析阶段,采用0填充且无主元选择。

\(A \approx LU\)

A 是一个 (mb*blockDim)×(mb*blockDim) 的稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式可以是列优先或行优先,由参数 dirA 决定,其值为 CUSPARSE_DIRECTION_COLUMNCUSPARSE_DIRECTION_ROW。矩阵类型必须为 CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。

此函数需要由bsrilu02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

函数 bsrilu02_analysis() 会报告结构零并计算存储在非透明结构 info 中的层级信息。该层级信息可以在不完全LU分解过程中提取更多并行性。但 bsrilu02() 无需层级信息也可执行。若要禁用层级信息,用户需将 bsrilu02[_analysis| ] 的参数 policy 指定为 CUSPARSE_SOLVE_POLICY_NO_LEVEL

函数 bsrilu02_analysis() 总会报告第一个结构性零值,即使参数 policy 设置为 CUSPARSE_SOLVE_POLICY_NO_LEVEL。用户必须调用 cusparseXbsrilu02_zeroPivot() 来定位结构性零值的位置。

是否在bsrilu02_analysis()报告结构零时调用bsrilu02()由用户决定。在这种情况下,用户仍可调用bsrilu02(),该函数将在结构零的相同位置返回数值零。但该结果没有意义。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

矩阵A的块行数和块列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度,大于零。

信息

使用cusparseCreateBsrilu02Info()初始化的结构。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区,其大小由bsrilu02_bufferSize()返回。

输出

信息

在分析阶段收集的信息填充的结构(应原封不动地传递给求解阶段)

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.9. cusparsebsrilu02() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSbsrilu02(cusparseHandle_t         handle,
                  cusparseDirection_t      dirA,
                  int                      mb,
                  int                      nnzb,
                  const cusparseMatDescr_t descry,
                  float*                   bsrValA,
                  const int*               bsrRowPtrA,
                  const int*               bsrColIndA,
                  int                      blockDim,
                  bsrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

cusparseStatus_t
cusparseDbsrilu02(cusparseHandle_t         handle,
                  cusparseDirection_t      dirA,
                  int                      mb,
                  int                      nnzb,
                  const cusparseMatDescr_t descry,
                  double*                  bsrValA,
                  const int*               bsrRowPtrA,
                  const int*               bsrColIndA,
                  int                      blockDim,
                  bsrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

cusparseStatus_t
cusparseCbsrilu02(cusparseHandle_t         handle,
                  cusparseDirection_t      dirA,
                  int                      mb,
                  int                      nnzb,
                  const cusparseMatDescr_t descry,
                  cuComplex*               bsrValA,
                  const int*               bsrRowPtrA,
                  const int*               bsrColIndA,
                  int                      blockDim,
                  bsrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

cusparseStatus_t
cusparseZbsrilu02(cusparseHandle_t         handle,
                  cusparseDirection_t      dirA,
                  int                      mb,
                  int                      nnzb,
                  const cusparseMatDescr_t descry,
                  cuDoubleComplex*         bsrValA,
                  const int*               bsrRowPtrA,
                  const int*               bsrColIndA,
                  int                      blockDim,
                  bsrilu02Info_t           info,
                  cusparseSolvePolicy_t    policy,
                  void*                    pBuffer)

该函数执行不完全LU分解的求解阶段,采用0填充且无主元选择。

\[A \approx LU\]

A 是一个 (mb*blockDim)×(mb*blockDim) 的稀疏矩阵,通过三个数组 bsrValAbsrRowPtrAbsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式为列优先或行优先,由参数 dirA 决定,该参数可以是 CUSPARSE_DIRECTION_COLUMNCUSPARSE_DIRECTION_ROW。矩阵类型必须为 CUSPARSE_MATRIX_TYPE_GENERAL,填充模式和对角线类型将被忽略。函数 bsrilu02() 支持任意的 blockDim

此函数需要由bsrilu02_bufferSize()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

虽然bsrilu02()可以在没有层级信息的情况下使用,但用户必须注意一致性。如果bsrilu02_analysis()调用时使用策略CUSPARSE_SOLVE_POLICY_USE_LEVEL,那么bsrilu02()可以在有或没有层级的情况下运行。另一方面,如果bsrilu02_analysis()调用时使用CUSPARSE_SOLVE_POLICY_NO_LEVEL,那么bsrilu02()只能接受CUSPARSE_SOLVE_POLICY_NO_LEVEL;否则会返回CUSPARSE_STATUS_INVALID_VALUE

函数 bsrilu02() 的行为与 csrilu02() 相同。也就是说,bsr2csr(bsrilu02(A)) = csrilu02(bsr2csr(A))csrilu02() 的数值零意味着存在某些零元素 U(j,j)。而 bsrilu02() 的数值零则表示存在某些不可逆的块 U(j,j)

函数 bsrilu02 会报告第一个数值零,包括结构零。用户必须调用 cusparseXbsrilu02_zeroPivot() 来定位数值零的位置。

例如,假设 A 是一个实数 m×m 矩阵,其中 m=mb*blockDim。以下代码求解预处理系统 M*y = x,其中 M 是 LU 因子 LU 的乘积。

// Suppose that A is m x m sparse matrix represented by BSR format,
// The number of block rows/columns is mb, and
// the number of nonzero blocks is nnzb.
// Assumption:
// - handle is already created by cusparseCreate(),
// - (d_bsrRowPtr, d_bsrColInd, d_bsrVal) is BSR of A on device memory,
// - d_x is right hand side vector on device memory.
// - d_y is solution vector on device memory.
// - d_z is intermediate result on device memory.
// - d_x, d_y and d_z are of size m.
cusparseMatDescr_t descr_M = 0;
cusparseMatDescr_t descr_L = 0;
cusparseMatDescr_t descr_U = 0;
bsrilu02Info_t info_M = 0;
bsrsv2Info_t   info_L = 0;
bsrsv2Info_t   info_U = 0;
int pBufferSize_M;
int pBufferSize_L;
int pBufferSize_U;
int pBufferSize;
void *pBuffer = 0;
int structural_zero;
int numerical_zero;
const double alpha = 1.;
const cusparseSolvePolicy_t policy_M = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_L = CUSPARSE_SOLVE_POLICY_NO_LEVEL;
const cusparseSolvePolicy_t policy_U = CUSPARSE_SOLVE_POLICY_USE_LEVEL;
const cusparseOperation_t trans_L  = CUSPARSE_OPERATION_NON_TRANSPOSE;
const cusparseOperation_t trans_U  = CUSPARSE_OPERATION_NON_TRANSPOSE;
const cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;

// step 1: create a descriptor which contains
// - matrix M is base-1
// - matrix L is base-1
// - matrix L is lower triangular
// - matrix L has unit diagonal
// - matrix U is base-1
// - matrix U is upper triangular
// - matrix U has non-unit diagonal
cusparseCreateMatDescr(&descr_M);
cusparseSetMatIndexBase(descr_M, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_M, CUSPARSE_MATRIX_TYPE_GENERAL);

cusparseCreateMatDescr(&descr_L);
cusparseSetMatIndexBase(descr_L, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_L, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatFillMode(descr_L, CUSPARSE_FILL_MODE_LOWER);
cusparseSetMatDiagType(descr_L, CUSPARSE_DIAG_TYPE_UNIT);

cusparseCreateMatDescr(&descr_U);
cusparseSetMatIndexBase(descr_U, CUSPARSE_INDEX_BASE_ONE);
cusparseSetMatType(descr_U, CUSPARSE_MATRIX_TYPE_GENERAL);
cusparseSetMatFillMode(descr_U, CUSPARSE_FILL_MODE_UPPER);
cusparseSetMatDiagType(descr_U, CUSPARSE_DIAG_TYPE_NON_UNIT);

// step 2: create a empty info structure
// we need one info for bsrilu02 and two info's for bsrsv2
cusparseCreateBsrilu02Info(&info_M);
cusparseCreateBsrsv2Info(&info_L);
cusparseCreateBsrsv2Info(&info_U);

// step 3: query how much memory used in bsrilu02 and bsrsv2, and allocate the buffer
cusparseDbsrilu02_bufferSize(handle, dir, mb, nnzb,
    descr_M, d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_M, &pBufferSize_M);
cusparseDbsrsv2_bufferSize(handle, dir, trans_L, mb, nnzb,
    descr_L, d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_L, &pBufferSize_L);
cusparseDbsrsv2_bufferSize(handle, dir, trans_U, mb, nnzb,
    descr_U, d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_U, &pBufferSize_U);

pBufferSize = max(pBufferSize_M, max(pBufferSize_L, pBufferSize_U));

// pBuffer returned by cudaMalloc is automatically aligned to 128 bytes.
cudaMalloc((void**)&pBuffer, pBufferSize);

// step 4: perform analysis of incomplete LU factorization on M
//         perform analysis of triangular solve on L
//         perform analysis of triangular solve on U
// The lower(upper) triangular part of M has the same sparsity pattern as L(U),
// we can do analysis of bsrilu0 and bsrsv2 simultaneously.

cusparseDbsrilu02_analysis(handle, dir, mb, nnzb, descr_M,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_M,
    policy_M, pBuffer);
status = cusparseXbsrilu02_zeroPivot(handle, info_M, &structural_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == statuss){
   printf("A(%d,%d) is missing\n", structural_zero, structural_zero);
}

cusparseDbsrsv2_analysis(handle, dir, trans_L, mb, nnzb, descr_L,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim,
    info_L, policy_L, pBuffer);

cusparseDbsrsv2_analysis(handle, dir, trans_U, mb, nnzb, descr_U,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim,
    info_U, policy_U, pBuffer);

// step 5: M = L * U
cusparseDbsrilu02(handle, dir, mb, nnzb, descr_M,
    d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_M, policy_M, pBuffer);
status = cusparseXbsrilu02_zeroPivot(handle, info_M, &numerical_zero);
if (CUSPARSE_STATUS_ZERO_PIVOT == statuss){
   printf("block U(%d,%d) is not invertible\n", numerical_zero, numerical_zero);
}

// step 6: solve L*z = x
cusparseDbsrsv2_solve(handle, dir, trans_L, mb, nnzb, &alpha, descr_L,
   d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_L,
   d_x, d_z, policy_L, pBuffer);

// step 7: solve U*y = z
cusparseDbsrsv2_solve(handle, dir, trans_U, mb, nnzb, &alpha, descr_U,
   d_bsrVal, d_bsrRowPtr, d_bsrColInd, blockDim, info_U,
   d_z, d_y, policy_U, pBuffer);

// step 6: free resources
cudaFree(pBuffer);
cusparseDestroyMatDescr(descr_M);
cusparseDestroyMatDescr(descr_L);
cusparseDestroyMatDescr(descr_U);
cusparseDestroyBsrilu02Info(info_M);
cusparseDestroyBsrsv2Info(info_L);
cusparseDestroyBsrsv2Info(info_U);
cusparseDestroy(handle);

如果pBuffer != NULL,该函数支持以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

块的存储格式:可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

矩阵A的块行数和块列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

<type> 矩阵 Annzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 个非零块的数组。

bsrRowPtrA

包含每个块行起始位置及最后一个块行结束位置加1的mb\(+ 1\)个元素的整数数组。

bsrColIndA

nnzb\(( =\)bsrRowPtrA(mb)\(-\)bsrRowPtrA(0)\()\) 的整数数组,表示矩阵 A 非零块的列索引。

blockDim

稀疏矩阵A的块维度;必须大于零。

信息

包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。

policy

支持的策略是 CUSPARSE_SOLVE_POLICY_NO_LEVELCUSPARSE_SOLVE_POLICY_USE_LEVEL

pBuffer

由用户分配的缓冲区;大小由bsrilu02_bufferSize()返回。

输出

bsrValA

矩阵包含不完全LU分解的下三角和上三角因子

有关返回状态的描述,请参见cusparseStatus_t

5.7.2.10. cusparseXbsrilu02_zeroPivot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseXbsrilu02_zeroPivot(cusparseHandle_t handle,
                            bsrilu02Info_t   info,
                            int*             position)

如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOTposition=j表示A(j,j)存在结构零或数值零(该块不可逆)。否则position=-1

position 可以是基于0或基于1的索引,与矩阵的索引方式相同。

函数 cusparseXbsrilu02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。

position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。

  • 该例程不需要额外的存储空间。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

信息

info 包含结构零或数值零,如果用户已经调用了 bsrilu02_analysis()bsrilu02()

输出

position

如果没有结构或数值上的零值,position为-1;否则如果A(j,j)缺失或U(j,j)不可逆,则position=j

有关返回状态的描述,请参见cusparseStatus_t

5.7.3. 三对角方程组求解

本节讨论了三对角方程组求解的不同算法。

5.7.3.1. cusparsegtsv2_buffSizeExt()

cusparseStatus_t
cusparseSgtsv2_bufferSizeExt(cusparseHandle_t handle,
                             int              m,
                             int              n,
                             const float*     dl,
                             const float*     d,
                             const float*     du,
                             const float*     B,
                             int              ldb,
                             size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseDgtsv2_bufferSizeExt(cusparseHandle_t handle,
                             int              m,
                             int              n,
                             const double*    dl,
                             const double*    d,
                             const double*    du,
                             const double*    B,
                             int              ldb,
                             size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseCgtsv2_bufferSizeExt(cusparseHandle_t handle,
                             int              m,
                             int              n,
                             const cuComplex* dl,
                             const cuComplex* d,
                             const cuComplex* du,
                             const cuComplex* B,
                             int              ldb,
                             size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseZgtsv2_bufferSizeExt(cusparseHandle_t       handle,
                             int                    m,
                             int                    n,
                             const cuDoubleComplex* dl,
                             const cuDoubleComplex* d,
                             const cuDoubleComplex* du,
                             const cuDoubleComplex* B,
                             int                    ldb,
                             size_t*                bufferSizeInBytes)

该函数返回gtsv2中使用的缓冲区大小,该函数用于计算具有多右端项的三对角线性系统的解。

\[A \ast X = B\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

线性系统的规模(必须 ≥ 3)。

n

右侧的数量,矩阵B的列数。

dl

包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。

du

包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。

B

右侧密集数组,维度为 (ldb, n)

ldb

B的主维度(即 ≥ \(\max\text{(1,\ m))}\))。

输出

pBufferSizeInBytes

gtsv2中使用的缓冲区字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.7.3.2. cusparsegtsv2()

cusparseStatus_t
cusparseSgtsv2(cusparseHandle_t handle,
               int              m,
               int              n,
               const float*     dl,
               const float*     d,
               const float*     du,
               float*           B,
               int              ldb,
               void*            pBuffer)

cusparseStatus_t
cusparseDgtsv2(cusparseHandle_t handle,
               int              m,
               int              n,
               const double*    dl,
               const double*    d,
               const double*    du,
               double*          B,
               int              ldb,
               void*            pBuffer)

cusparseStatus_t
cusparseCgtsv2(cusparseHandle_t handle,
               int              m,
               int              n,
               const cuComplex* dl,
               const cuComplex* d,
               const cuComplex* du,
               cuComplex*       B,
               int              ldb,
               void*            pBuffer)

cusparseStatus_t
cusparseZgtsv2(cusparseHandle_t       handle,
               int                    m,
               int                    n,
               const cuDoubleComplex* dl,
               const cuDoubleComplex* d,
               const cuDoubleComplex* du,
               cuDoubleComplex*       B,
               int                    ldb,
               void*                  pBuffer)

该函数计算具有多个右侧的三对角线性系统的解:

\[A \ast X = B\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B

假设 A 的大小为 m 且基于1,dlddu 由以下公式定义:

dl(i) := A(i, i-1)i=1,2,...,m

dl的第一个元素越界了(dl(1) := A(1,0)),因此dl(1) = 0

d(i) = A(i,i)i=1,2,...,m

du(i) = A(i,i+1)i=1,2,...,m

du的最后一个元素越界了(du(m) := A(m,m+1)),因此du(m) = 0

该例程确实执行了主元选择,虽然会牺牲一些执行时间,但通常能比cusparsegtsv_nopivot()cusparsegtsv2_nopivot()获得更准确和更稳定的结果。

此函数需要由gtsv2_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

线性系统的规模(必须 ≥ 3)。

n

右侧的数量,矩阵B的列数。

dl

包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。

du

包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。

B

右侧密集数组,维度为 (ldb, n)

ldb

B的主维度(即 ≥ \(\max\text{(1,\ m))}\))。

pBuffer

由用户分配的缓冲区,其大小由gtsv2_bufferSizeExt返回。

输出

B

维度为 (ldb, n) 的密集解数组。

有关返回状态的描述,请参见cusparseStatus_t

5.7.3.3. cusparsegtsv2_nopivot_bufferSizeExt()

cusparseStatus_t
cusparseSgtsv2_nopivot_bufferSizeExt(cusparseHandle_t handle,
                                     int              m,
                                     int              n,
                                     const float*     dl,
                                     const float*     d,
                                     const float*     du,
                                     const float*     B,
                                     int              ldb,
                                     size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseDgtsv2_nopivot_bufferSizeExt(cusparseHandle_t handle,
                                     int              m,
                                     int              n,
                                     const double*    dl,
                                     const double*    d,
                                     const double*    du,
                                     const double*    B,
                                     int              ldb,
                                     size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseCgtsv2_nopivot_bufferSizeExt(cusparseHandle_t handle,
                                     int              m,
                                     int              n,
                                     const cuComplex* dl,
                                     const cuComplex* d,
                                     const cuComplex* du,
                                     const cuComplex* B,
                                     int              ldb,
                                     size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseZgtsv2_nopivot_bufferSizeExt(cusparseHandle_t       handle,
                                     int                    m,
                                     int                    n,
                                     const cuDoubleComplex* dl,
                                     const cuDoubleComplex* d,
                                     const cuDoubleComplex* du,
                                     const cuDoubleComplex* B,
                                     int                    ldb,
                                     size_t*                bufferSizeInBytes)

该函数返回gtsv2_nopivot中使用的缓冲区大小,该函数用于计算具有多个右侧项的三对角线性系统的解。

\[A \ast X = B\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

线性系统的规模(必须 ≥ 3)。

n

右侧的数量,矩阵B的列数。

dl

包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。

du

包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。

B

右侧密集数组,维度为 (ldb, n)

ldb

B的前导维度(即 ≥ \(\max\text{(1,\ m))}\))。

输出

pBufferSizeInBytes

gtsv2_nopivot中使用的缓冲区字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.7.3.4. cusparsegtsv2_nopivot()

cusparseStatus_t
cusparseSgtsv2_nopivot(cusparseHandle_t handle,
                       int              m,
                       int              n,
                       const float*     dl,
                       const float*     d,
                       const float*     du,
                       float*           B,
                       int              ldb,
                       void*            pBuffer)

cusparseStatus_t
cusparseDgtsv2_nopivot(cusparseHandle_t handle,
                       int              m,
                       int              n,
                       const double*    dl,
                       const double*    d,
                       const double*    du,
                       double*          B,
                       int              ldb,
                       void*            pBuffer)

cusparseStatus_t
cusparseCgtsv2_nopivot(cusparseHandle_t handle,
                       int              m,
                       int              n,
                       const cuComplex* dl,
                       const cuComplex* d,
                       const cuComplex* du,
                       cuComplex*       B,
                       int              ldb,
                       void*            pBuffer)

cusparseStatus_t
cusparseZgtsv2_nopivot(cusparseHandle_t       handle,
                       int                    m,
                       int                    n,
                       const cuDoubleComplex* dl,
                       const cuDoubleComplex* d,
                       const cuDoubleComplex* du,
                       cuDoubleComplex*       B,
                       int                    ldb,
                       void*                  pBuffer)

该函数计算具有多个右侧的三对角线性系统的解:

\[A \ast X = B\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B

该例程不执行任何主元选择,而是结合使用循环约简(CR)和平行循环约简(PCR)算法来求解。当m是2的幂时,它能获得更好的性能。

此函数需要一个由gtsv2_nopivot_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

线性系统的规模(必须 ≥ 3)。

n

右侧的数量,矩阵B的列数。

dl

包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。

du

包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。

B

<type> 右侧密集数组,维度为 (ldb, n)

ldb

B的前导维度(即 ≥ \(\max\text{(1,\ m))}\))。

pBuffer

用户分配的缓冲区,其大小由gtsv2_nopivot_bufferSizeExt返回。

输出

B

维度为 (ldb, n) 的密集解数组。

有关返回状态的描述,请参见cusparseStatus_t

5.7.4. 批量三对角方程组求解

本节讨论了用于批量三对角方程组求解的不同算法。

5.7.4.1. cusparsegtsv2StridedBatch_bufferSizeExt()

cusparseStatus_t
cusparseSgtsv2StridedBatch_bufferSizeExt(cusparseHandle_t handle,
                                         int              m,
                                         const float*     dl,
                                         const float*     d,
                                         const float*     du,
                                         const float*     x,
                                         int              batchCount,
                                         int              batchStride,
                                         size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseDgtsv2StridedBatch_bufferSizeExt(cusparseHandle_t handle,
                                         int              m,
                                         const double*    dl,
                                         const double*    d,
                                         const double*    du,
                                         const double*    x,
                                         int              batchCount,
                                         int              batchStride,
                                         size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseCgtsv2StridedBatch_bufferSizeExt(cusparseHandle_t handle,
                                         int              m,
                                         const cuComplex* dl,
                                         const cuComplex* d,
                                         const cuComplex* du,
                                         const cuComplex* x,
                                         int              batchCount,
                                         int              batchStride,
                                         size_t*          bufferSizeInBytes)

cusparseStatus_t
cusparseZgtsv2StridedBatch_bufferSizeExt(cusparseHandle_t       handle,
                                         int                    m,
                                         const cuDoubleComplex* dl,
                                         const cuDoubleComplex* d,
                                         const cuDoubleComplex* du,
                                         const cuDoubleComplex* x,
                                         int                    batchCount,
                                         int                    batchStride,
                                         size_t*                bufferSizeInBytes)

该函数返回gtsv2StridedBatch中使用的缓冲区大小,该函数用于计算多个三对角线性方程组的解(针对i=0,…,batchCount):

\[A^{(i)} \ast \text{y}^{(i)} = \text{x}^{(i)}\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵X中。注意解Y会在退出时覆盖右侧项矩阵X。假设不同矩阵具有相同大小,并在内存中以固定的batchStride存储。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

n

线性系统的规模(必须 ≥ 3)。

dl

包含三对角线性系统下对角线的密集数组。对应于第i个线性系统的下对角线\(dl^{(i)}\)在内存中起始于位置dl+batchStride×i。此外,每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。对应于第i线性系统的主对角线\(d^{(i)}\)在内存中起始于位置d+batchStride×i

du

包含三对角线性系统上对角线的密集数组。对应于第i线性系统的上对角线\(du^{(i)}\)在内存中起始于位置du+batchStride×i。此外,每个上对角线的最后一个元素必须为零。

x

包含三对角线性方程组右侧的密集数组。对应于第i线性系统的右侧\(x^{(i)}\)在内存中的起始位置为x+batchStride×i

batchCount

需要求解的系统数量。

batchStride

步幅(元素数量),用于分隔每个系统的向量(必须至少为m)。

输出

pBufferSizeInBytes

gtsv2StridedBatch中使用的缓冲区字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.7.4.2. cusparsegtsv2StridedBatch()

cusparseStatus_t
cusparseSgtsv2StridedBatch(cusparseHandle_t handle,
                           int              m,
                           const float*     dl,
                           const float*     d,
                           const float*     du,
                           float*           x,
                           int              batchCount,
                           int              batchStride,
                           void*            pBuffer)

cusparseStatus_t
cusparseDgtsv2StridedBatch(cusparseHandle_t handle,
                           int              m,
                           const double*    dl,
                           const double*    d,
                           const double*    du,
                           double*          x,
                           int              batchCount,
                           int              batchStride,
                           void*            pBuffer)

cusparseStatus_t
cusparseCgtsv2StridedBatch(cusparseHandle_t handle,
                           int              m,
                           const cuComplex* dl,
                           const cuComplex* d,
                           const cuComplex* du,
                           cuComplex*       x,
                           int              batchCount,
                           int              batchStride,
                           void*            pBuffer)

cusparseStatus_t
cusparseZgtsv2StridedBatch(cusparseHandle_t       handle,
                           int                    m,
                           const cuDoubleComplex* dl,
                           const cuDoubleComplex* d,
                           const cuDoubleComplex* du,
                           cuDoubleComplex*       x,
                           int                    batchCount,
                           int                    batchStride,
                           void*                  pBuffer)

该函数计算多个三对角线性系统的解,其中i=0,…,batchCount

\[A^{(i)} \ast \text{y}^{(i)} = \text{x}^{(i)}\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵X中。请注意,解Y会在退出时覆盖右侧矩阵X。假设不同矩阵具有相同大小,并在内存中以固定的batchStride存储。

该例程不执行任何主元选择,而是结合使用循环约简(CR)和平行循环约简(PCR)算法来求解。当m是2的幂时,它能获得更好的性能。

此函数需要由gtsv2StridedBatch_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

n

线性系统的规模(必须 ≥ 3)。

dl

包含三对角线性系统下对角线的密集数组。对应于第i个线性系统的下对角线\(dl^{(i)}\)在内存中起始于位置dl+batchStride×i。此外,每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。对应于第i个线性系统的主对角线\(d^{(i)}\)在内存中起始于位置d+batchStride×i

du

包含三对角线性系统上对角线的密集数组。对应于第i个线性系统的上对角线\(du^{(i)}\)在内存中起始于位置du+batchStride×i。此外,每个上对角线的最后一个元素必须为零。

x

包含三对角线性方程组右侧的密集数组。对应于第i线性系统的右侧\(x^{(i)}\)在内存中起始于位置x+batchStride×i

batchCount

需要求解的系统数量。

batchStride

步幅(元素数量)用于分隔每个系统的向量(必须至少为n)。

pBuffer

用户分配的缓冲区,其大小由gtsv2StridedBatch_bufferSizeExt返回。

输出

x

包含三对角线性系统解的密集数组。对应于第i个线性系统的解\(x^{(i)}\)在内存中起始于位置x+batchStride×i

有关返回状态的描述,请参见cusparseStatus_t

5.7.4.3. cusparsegtsvInterleavedBatch()

cusparseStatus_t
cusparseSgtsvInterleavedBatch_bufferSizeExt(cusparseHandle_t handle,
                                            int              algo,
                                            int              m,
                                            const float*     dl,
                                            const float*     d,
                                            const float*     du,
                                            const float*     x,
                                            int              batchCount,
                                            size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseDgtsvInterleavedBatch_bufferSizeExt(cusparseHandle_t handle,
                                            int              algo,
                                            int              m,
                                            const double*    dl,
                                            const double*    d,
                                            const double*    du,
                                            const double*    x,
                                            int              batchCount,
                                            size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseCgtsvInterleavedBatch_bufferSizeExt(cusparseHandle_t handle,
                                            int              algo,
                                            int              m,
                                            const cuComplex* dl,
                                            const cuComplex* d,
                                            const cuComplex* du,
                                            const cuComplex* x,
                                            int              batchCount,
                                            size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseZgtsvInterleavedBatch_bufferSizeExt(cusparseHandle_t       handle,
                                            int                    algo,
                                            int                    m,
                                            const cuDoubleComplex* dl,
                                            const cuDoubleComplex* d,
                                            const cuDoubleComplex* du,
                                            const cuDoubleComplex* x,
                                            int                    batchCount,
                                            size_t*                pBufferSizeInBytes)
cusparseStatus_t
cusparseSgtsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              float*           dl,
                              float*           d,
                              float*           du,
                              float*           x,
                              int              batchCount,
                              void*            pBuffer)

cusparseStatus_t
cusparseDgtsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              double*          dl,
                              double*          d,
                              double*          du,
                              double*          x,
                              int              batchCount,
                              void*            pBuffer)

cusparseStatus_t
cusparseCgtsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              cuComplex*       dl,
                              cuComplex*       d,
                              cuComplex*       du,
                              cuComplex*       x,
                              int              batchCount,
                              void*            pBuffer)

cusparseStatus_t
cusparseZgtsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              cuDoubleComplex* dl,
                              cuDoubleComplex* d,
                              cuDoubleComplex* du,
                              cuDoubleComplex* x,
                              int              batchCount,
                              void*            pBuffer)

该函数计算多个三对角线性系统的解,其中i=0,…,batchCount

\[A^{(i)} \ast \text{x}^{(i)} = \text{b}^{(i)}\]

每个三对角线性系统的系数矩阵A由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B

假设 A 的大小为 m 且基于1,dlddu 由以下公式定义:

dl(i) := A(i, i-1)i=1,2,...,m

dl的第一个元素越界了(dl(1) := A(1,0)),因此dl(1) = 0

d(i) = A(i,i)i=1,2,...,m

du(i) = A(i,i+1)i=1,2,...,m

du的最后一个元素越界了(du(m) := A(m,m+1)),因此du(m) = 0

数据布局与gtsvStridedBatch将所有矩阵依次聚合的方式不同。gtsvInterleavedBatch会以连续方式收集不同矩阵的相同元素。如果将dl视为大小为m-by-batchCount的二维数组,则dl(:,j)用于存储第j个矩阵。gtsvStridedBatch使用列优先存储,而gtsvInterleavedBatch使用行优先存储。

该例程提供三种不同的算法,通过参数algo进行选择。第一种算法是由Barcelona Supercomputing Center提供的cuThomas。第二种算法是带部分主元消去的LU分解,最后一种算法是QR分解。从数值稳定性角度来看,cuThomas由于没有主元消去步骤,其数值稳定性较差。带部分主元消去的LU分解和QR分解都具有良好的稳定性。从性能角度来看,带部分主元消去的LU分解和QR分解比cuThomas慢约10%到20%。

此函数需要一个由gtsvInterleavedBatch_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

如果用户准备了聚合格式,可以使用cublasXgeam来获取交错格式。不过这种转换所需时间与求解器本身相当。为了达到最佳性能,用户必须明确准备交错格式。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

algo

algo = 0: cuThomas(不稳定算法); algo = 1: 带主元的LU分解(稳定算法); algo = 2: QR分解(稳定算法)

m

线性系统的规模。

dl

包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。

d

包含三对角线性系统主对角线的密集数组。

du

包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。

x

密集右侧数组,维度为 (batchCount, n)

pBuffer

由用户分配的缓冲区,其大小由gtsvInterleavedBatch_bufferSizeExt返回。

输出

x

维度为 (batchCount, n) 的密集解数组。

有关返回状态的描述,请参见cusparseStatus_t

5.7.5. 批量五对角方程组求解

本节讨论了用于批量五对角求解的不同算法。

5.7.5.1. cusparsegpsvInterleavedBatch()

cusparseStatus_t
cusparseSgpsvInterleavedBatch_bufferSizeExt(cusparseHandle_t handle,
                                            int              algo,
                                            int              m,
                                            const float*     ds,
                                            const float*     dl,
                                            const float*     d,
                                            const float*     du,
                                            const float*     dw,
                                            const float*     x,
                                            int              batchCount,
                                            size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseDgpsvInterleavedBatch_bufferSizeExt(cusparseHandle_t handle,
                                            int              algo,
                                            int              m,
                                            const double*    ds,
                                            const double*    dl,
                                            const double*    d,
                                            const double*    du,
                                            const double*    dw,
                                            const double*    x,
                                            int              batchCount,
                                            size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseCgpsvInterleavedBatch_bufferSizeExt(cusparseHandle_t handle,
                                            int              algo,
                                            int              m,
                                            const cuComplex* ds,
                                            const cuComplex* dl,
                                            const cuComplex* d,
                                            const cuComplex* du,
                                            const cuComplex* dw,
                                            const cuComplex* x,
                                            int              batchCount,
                                            size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseZgpsvInterleavedBatch_bufferSizeExt(cusparseHandle_t       handle,
                                            int                    algo,
                                            int                    m,
                                            const cuDoubleComplex* ds,
                                            const cuDoubleComplex* dl,
                                            const cuDoubleComplex* d,
                                            const cuDoubleComplex* du,
                                            const cuDoubleComplex* dw,
                                            const cuDoubleComplex* x,
                                            int                    batchCount,
                                            size_t*                pBufferSizeInBytes)
cusparseStatus_t
cusparseSgpsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              float*           ds,
                              float*           dl,
                              float*           d,
                              float*           du,
                              float*           dw,
                              float*           x,
                              int              batchCount,
                              void*            pBuffer)

cusparseStatus_t
cusparseDgpsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              double*          ds,
                              double*          dl,
                              double*          d,
                              double*          du,
                              double*          dw,
                              double*          x,
                              int              batchCount,
                              void*            pBuffer)

cusparseStatus_t
cusparseCgpsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              cuComplex*       ds,
                              cuComplex*       dl,
                              cuComplex*       d,
                              cuComplex*       du,
                              cuComplex*       dw,
                              cuComplex*       x,
                              int              batchCount,
                              void*            pBuffer)

cusparseStatus_t
cusparseZgpsvInterleavedBatch(cusparseHandle_t handle,
                              int              algo,
                              int              m,
                              cuDoubleComplex* ds,
                              cuDoubleComplex* dl,
                              cuDoubleComplex* d,
                              cuDoubleComplex* du,
                              cuDoubleComplex* dw,
                              cuDoubleComplex* x,
                              int              batchCount,
                              void*            pBuffer)

该函数计算多个五对角线性方程组的解,其中 i=0,…,batchCount

\[A^{(i)} \ast \text{x}^{(i)} = \text{b}^{(i)}\]

每个五对角线性系统的系数矩阵A由五个向量定义,分别对应其下对角线(ds, dl)、主对角线(d)和上对角线(du, dw);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B

假设A的大小为m且基于1,dsdlddudw由以下公式定义:

ds(i) := A(i, i-2)i=1,2,...,m

ds的前两个元素超出边界(ds(1) := A(1,-1), ds(2) := A(2,0)),因此ds(1) = 0ds(2) = 0

dl(i) := A(i, i-1)i=1,2,...,m

dl的第一个元素越界了(dl(1) := A(1,0)),因此dl(1) = 0

d(i) = A(i,i)i=1,2,...,m

du(i) = A(i,i+1)i=1,2,...,m

du的最后一个元素越界了(du(m) := A(m,m+1)),因此du(m) = 0

dw(i) = A(i,i+2)i=1,2,...,m

dw的最后两个元素越界了(dw(m-1) := A(m-1,m+1), dw(m) := A(m,m+2)),因此 dw(m-1) = 0dw(m) = 0

数据布局与gtsvStridedBatch相同。

该例程在数值上是稳定的,因为它使用QR分解来求解线性系统。

此函数需要由gpsvInterleavedBatch_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE

如果pBuffer != NULL,该函数支持以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

algo

仅支持 algo = 0 (QR)

m

线性系统的规模。

ds

包含五对角线性系统次对角线(距离主对角线2)的密集数组。前两个元素必须为零。

dl

包含五对角线性系统次对角线(距离主对角线1的位置)的密集数组。第一个元素必须为零。

d

包含五对角线性系统主对角线的密集数组。

du

包含五对角线性系统上对角线(距离主对角线1个单位)的密集数组。最后一个元素必须为零。

dw

包含五对角线性系统上对角线(距离主对角线2)的密集数组。最后两个元素必须为零。

x

<type> 密集右侧数组,维度为 (batchCount, n)

pBuffer

由用户分配的缓冲区,其大小由gpsvInterleavedBatch_bufferSizeExt返回。

输出

x

<type> 维度为 (batchCount, n) 的密集解数组。

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE Library Samples - cusparseSgpsvInterleavedBatch查看代码示例。

5.8. cuSPARSE重排序参考

本章介绍用于操作稀疏矩阵的重排序例程。

5.8.1. cusparsecsrcolor() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseScsrcolor(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  const float*             csrValA,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  const float*             fractionToColor,
                  int*                     ncolors,
                  int*                     coloring,
                  int*                     reordering,
                  cusparseColorInfo_t      info)

cusparseStatus_t
cusparseDcsrcolor(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  const double*            csrValA,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  const double*            fractionToColor,
                  int*                     ncolors,
                  int*                     coloring,
                  int*                     reordering,
                  cusparseColorInfo_t      info)

cusparseStatus_t
cusparseCcsrcolor(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  const cuComplex*         csrValA,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  const cuComplex*         fractionToColor,
                  int*                     ncolors,
                  int*                     coloring,
                  int*                     reordering,
                  cusparseColorInfo_t      info)

cusparseStatus_t
cusparseZcsrcolor(cusparseHandle_t         handle,
                  int                      m,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  const cuDoubleComplex*   csrValA,
                  const int*               csrRowPtrA,
                  const int*               csrColIndA,
                  const cuDoubleComplex*   fractionToColor,
                  int*                     ncolors,
                  int*                     coloring,
                  int*                     reordering,
                  cusparseColorInfo_t      info)

此函数对以CSR格式存储的矩阵A所对应的邻接图进行着色处理。着色即为节点分配颜色(整数值),确保相邻节点具有不同颜色。本程序采用近似着色算法,当一定比例的节点完成着色时即停止。其余节点会被分配不同的颜色(从之前使用的最后一个整数开始,按递增序列分配)。最后两个辅助例程可用于提取最终的颜色数量、颜色分配结果以及相关的重排序信息。重排序规则是:被分配相同颜色的节点会被重新排列至相邻位置。

传递给此例程的矩阵A必须以通用矩阵形式存储,并具有对称稀疏模式。如果矩阵非对称,用户应将A+A^T作为参数传递给此例程。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数。

nnz

矩阵A的非零元素数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

<type> 矩阵 Annz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\) 个非零元素的数组。

csrRowPtrA

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndA

长度为nnz\(( =\)csrRowPtrA(m)\(-\)csrRowPtrA(0)\()\)的整型数组,表示矩阵A非零元素的列索引。

fractionToColor

需要着色的节点比例,应在区间[0.0,1.0]内,例如0.8表示80%的节点将被着色。

信息

包含要传递给着色处理的信息的结构。

输出

ncolors

使用的不同颜色数量(最多为矩阵的大小,但很可能小得多)。

coloring

生成的着色排列

reordering

结果的重排序置换(如果为NULL则保持不变)

有关返回状态的描述,请参见cusparseStatus_t

5.9. cuSPARSE格式转换参考

本章介绍不同稀疏与密集存储格式之间的转换例程。

coosortcsrsortcscsortcsru2csr是不含内部malloc的排序例程,下表估算了所需的缓冲区大小。

routine

buffer size

当缓冲区限制为2GB时的 最大 问题 规模

coosort

> 16*n 字节

125M

csrsort or cscsort

> 20*n 字节

100M

csru2csr

'd' > 28*n 字节 ; 'z' > 36*n 字节

'd' 为 71M,'z' 为 55M

5.9.1. cusparsebsr2csr() [已弃用]

> 此例程将在未来的主要版本中移除。

cusparseStatus_t
cusparseSbsr2csr(cusparseHandle_t         handle,
                 cusparseDirection_t      dir,
                 int                      mb,
                 int                      nb,
                 const cusparseMatDescr_t descrA,
                 const float*             bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 const cusparseMatDescr_t descrC,
                 float*                   csrValC,
                 int*                     csrRowPtrC,
                 int*                     csrColIndC)

cusparseStatus_t
cusparseDbsr2csr(cusparseHandle_t         handle,
                 cusparseDirection_t      dir,
                 int                      mb,
                 int                      nb,
                 const cusparseMatDescr_t descrA,
                 const double*            bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 const cusparseMatDescr_t descrC,
                 double*                  csrValC,
                 int*                     csrRowPtrC,
                 int*                     csrColIndC)

cusparseStatus_t
cusparseCbsr2csr(cusparseHandle_t         handle,
                 cusparseDirection_t      dir,
                 int                      mb,
                 int                      nb,
                 const cusparseMatDescr_t descrA,
                 const cuComplex*         bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 const cusparseMatDescr_t descrC,
                 cuComplex*               csrValC,
                 int*                     csrRowPtrC,
                 int*                     csrColIndC)

cusparseStatus_t
cusparseZbsr2csr(cusparseHandle_t         handle,
                 cusparseDirection_t      dir,
                 int                      mb,
                 int                      nb,
                 const cusparseMatDescr_t descrA,
                 const cuDoubleComplex*   bsrValA,
                 const int*               bsrRowPtrA,
                 const int*               bsrColIndA,
                 int                      blockDim,
                 const cusparseMatDescr_t descrC,
                 cuDoubleComplex*         csrValC,
                 int*                     csrRowPtrC,
                 int*                     csrColIndC)

该函数将由三个数组bsrValAbsrRowPtrAbsrColIndA定义的BSR格式稀疏矩阵转换为由数组csrValCcsrRowPtrCcsrColIndC定义的CSR格式稀疏矩阵。

m(=mb*blockDim)为矩阵A的行数,n(=nb*blockDim)为矩阵A的列数,则AC都是m*n的稀疏矩阵。A的BSR格式包含nnzb(=bsrRowPtrA[mb] - bsrRowPtrA[0])个非零块,而稀疏矩阵A包含nnz(=nnzb*blockDim*blockDim)个元素。用户必须为数组csrRowPtrCcsrColIndCcsrValC分配足够的空间。具体要求如下:

csrRowPtrC 包含 m+1 个元素

csrValC 包含 nnz 个元素

csrColIndC 包含 nnz 个元素

一般流程如下:

// Given BSR format (bsrRowPtrA, bsrcolIndA, bsrValA) and
// blocks of BSR format are stored in column-major order.
cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;
int m = mb*blockDim;
int nnzb = bsrRowPtrA[mb] - bsrRowPtrA[0]; // number of blocks
int nnz  = nnzb * blockDim * blockDim; // number of elements
cudaMalloc((void**)&csrRowPtrC, sizeof(int)*(m+1));
cudaMalloc((void**)&csrColIndC, sizeof(int)*nnz);
cudaMalloc((void**)&csrValC, sizeof(float)*nnz);
cusparseSbsr2csr(handle, dir, mb, nb,
        descrA,
        bsrValA, bsrRowPtrA, bsrColIndA,
        blockDim,
        descrC,
        csrValC, csrRowPtrC, csrColIndC);
  • 该例程不需要额外的存储空间

  • 如果blockDim != 1或流序内存分配器可用,该例程支持异步执行

  • 如果blockDim != 1或流序内存分配器可用,该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

稀疏矩阵A的块行数。

nb

稀疏矩阵A的块列数。

描述A

矩阵 A 的描述符。

bsrValA

矩阵 A 的非零元素数组,大小为 nnzb*blockDim*blockDim

bsrRowPtrA

包含矩阵A每个块行起始位置以及最后一个块行结束位置加1的mb+1个元素的整数数组。

bsrColIndA

矩阵A非零块的nnzb列索引的整数数组。

blockDim

稀疏矩阵A的块维度。

descrC

矩阵 C 的描述符。

输出

csrValC

矩阵 Cnnz(=csrRowPtrC[m]-csrRowPtrC[0]) 个非零元素的数组。

csrRowPtrC

包含矩阵C每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndC

矩阵 C 非零元素的 nnz 个列索引的整数数组。

有关返回状态的描述,请参见cusparseStatus_t

5.9.2. cusparsegebsr2gebsc()

cusparseStatus_t
cusparseSgebsr2gebsc_bufferSize(cusparseHandle_t handle,
                               int               mb,
                               int               nb,
                               int               nnzb,
                               const float*      bsrVal,
                               const int*        bsrRowPtr,
                               const int*        bsrColInd,
                               int               rowBlockDim,
                               int               colBlockDim,
                               int*              pBufferSize)

cusparseStatus_t
cusparseDgebsr2gebsc_bufferSize(cusparseHandle_t handle,
                               int               mb,
                               int               nb,
                               int               nnzb,
                               const double*     bsrVal,
                               const int*        bsrRowPtr,
                               const int*        bsrColInd,
                               int               rowBlockDim,
                               int               colBlockDim,
                               int*              pBufferSize)

cusparseStatus_t
cusparseCgebsr2gebsc_bufferSize(cusparseHandle_t handle,
                               int               mb,
                               int               nb,
                               int               nnzb,
                               const cuComplex*  bsrVal,
                               const int*        bsrRowPtr,
                               const int*        bsrColInd,
                               int               rowBlockDim,
                               int               colBlockDim,
                               int*              pBufferSize)

cusparseStatus_t
cusparseZgebsr2gebsc_bufferSize(cusparseHandle_t      handle,
                               int                    mb,
                               int                    nb,
                               int                    nnzb,
                               const cuDoubleComplex* bsrVal,
                               const int*             bsrRowPtr,
                               const int*             bsrColInd,
                               int                    rowBlockDim,
                               int                    colBlockDim,
                               int*                   pBufferSize)
cusparseStatus_t
cusparseSgebsr2gebsc(cusparseHandle_t    handle,
                     int                 mb,
                     int                 nb,
                     int                 nnzb,
                     const float*        bsrVal,
                     const int*          bsrRowPtr,
                     const int*          bsrColInd,
                     int                 rowBlockDim,
                     int                 colBlockDim,
                     float*              bscVal,
                     int*                bscRowInd,
                     int*                bscColPtr,
                     cusparseAction_t    copyValues,
                     cusparseIndexBase_t baseIdx,
                     void*               pBuffer)

cusparseStatus_t
cusparseDgebsr2gebsc(cusparseHandle_t    handle,
                     int                 mb,
                     int                 nb,
                     int                 nnzb,
                     const double*       bsrVal,
                     const int*          bsrRowPtr,
                     const int*          bsrColInd,
                     int                 rowBlockDim,
                     int                 colBlockDim,
                     double*             bscVal,
                     int*                bscRowInd,
                     int*                bscColPtr,
                     cusparseAction_t    copyValues,
                     cusparseIndexBase_t baseIdx,
                     void*               pBuffer)

cusparseStatus_t
cusparseCgebsr2gebsc(cusparseHandle_t    handle,
                     int                 mb,
                     int                 nb,
                     int                 nnzb,
                     const cuComplex*    bsrVal,
                     const int*          bsrRowPtr,
                     const int*          bsrColInd,
                     int                 rowBlockDim,
                     int                 colBlockDim,
                     cuComplex*          bscVal,
                     int*                bscRowInd,
                     int*                bscColPtr,
                     cusparseAction_t    copyValues,
                     cusparseIndexBase_t baseIdx,
                     void*               pBuffer)

cusparseStatus_t
cusparseZgebsr2gebsc(cusparseHandle_t       handle,
                     int                    mb,
                     int                    nb,
                     int                    nnzb,
                     const cuDoubleComplex* bsrVal,
                     const int*             bsrRowPtr,
                     const int*             bsrColInd,
                     int                    rowBlockDim,
                     int                    colBlockDim,
                     cuDoubleComplex*       bscVal,
                     int*                   bscRowInd,
                     int*                   bscColPtr,
                     cusparseAction_t       copyValues,
                     cusparseIndexBase_t    baseIdx,
                     void*                  pBuffer)

此函数可视为与csr2csc()相同,当每个大小为rowBlockDim*colBlockDim的块被视为标量时。

结果矩阵的这种稀疏模式也可以视为原始稀疏矩阵的转置,但块的内存布局不会改变。

用户必须调用gebsr2gebsc_bufferSize()来确定gebsr2gebsc()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给gebsr2gebsc()

  • 如果pBuffer != NULL,该例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

mb

稀疏矩阵A的块行数。

nb

稀疏矩阵A的块列数。

nnzb

矩阵 A 的非零块数量。

bsrVal

矩阵 Annzb*rowBlockDim*colBlockDim 个非零元素数组。

bsrRowPtr

包含每个块行起始位置及最后一个块行结束位置加1的mb+1元素整数数组。

bsrColInd

矩阵A非零块的nnzb列索引的整数数组。

rowBlockDim

A 块内的行数。

colBlockDim

A块中的列数。

copyValues

CUSPARSE_ACTION_SYMBOLICCUSPARSE_ACTION_NUMERIC

baseIdx

CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

pBufferSize

包含gebsr2gebsc()函数中使用的缓冲区字节数的host指针。

pBuffer

由用户分配的缓冲区;大小由gebsr2gebsc_bufferSize()返回。

输出

bscVal

矩阵 Annzb*rowBlockDim*colBlockDim 个非零元素数组。仅当 copyValues 设置为 CUSPARSE_ACTION_NUMERIC 时才会填充。

bscRowInd

矩阵A非零块的行索引的nnzb整数数组。

bscColPtr

包含每个块列起始位置及最后一个块列结束位置加一的nb+1元素整数数组。

有关返回状态的描述,请参见cusparseStatus_t

5.9.3. cusparsegebsr2gebsr() [已弃用]

> 此例程将在未来的主要版本中移除。

cusparseStatus_t
cusparseSgebsr2gebsr_bufferSize(cusparseHandle_t         handle,
                                cusparseDirection_t      dir,
                                int                      mb,
                                int                      nb,
                                int                      nnzb,
                                const cusparseMatDescr_t descrA,
                                const float*             bsrValA,
                                const int*               bsrRowPtrA,
                                const int*               bsrColIndA,
                                int                      rowBlockDimA,
                                int                      colBlockDimA,
                                int                      rowBlockDimC,
                                int                      colBlockDimC,
                                int*                     pBufferSize)

cusparseStatus_t
cusparseDgebsr2gebsr_bufferSize(cusparseHandle_t         handle,
                                cusparseDirection_t      dir,
                                int                      mb,
                                int                      nb,
                                int                      nnzb,
                                const cusparseMatDescr_t descrA,
                                const double*            bsrValA,
                                const int*               bsrRowPtrA,
                                const int*               bsrColIndA,
                                int                      rowBlockDimA,
                                int                      colBlockDimA,
                                int                      rowBlockDimC,
                                int                      colBlockDimC,
                                int*                     pBufferSize)

cusparseStatus_t
cusparseCgebsr2gebsr_bufferSize(cusparseHandle_t         handle,
                                cusparseDirection_t      dir,
                                int                      mb,
                                int                      nb,
                                int                      nnzb,
                                const cusparseMatDescr_t descrA,
                                const cuComplex*         bsrValA,
                                const int*               bsrRowPtrA,
                                const int*               bsrColIndA,
                                int                      rowBlockDimA,
                                int                      colBlockDimA,
                                int                      rowBlockDimC,
                                int                      colBlockDimC,
                                int*                     pBufferSize)

cusparseStatus_t
cusparseZgebsr2gebsr_bufferSize(cusparseHandle_t         handle,
                                cusparseDirection_t      dir,
                                int                      mb,
                                int                      nb,
                                int                      nnzb,
                                const cusparseMatDescr_t descrA,
                                const cuDoubleComplex*   bsrValA,
                                const int*               bsrRowPtrA,
                                const int*               bsrColIndA,
                                int                      rowBlockDimA,
                                int                      colBlockDimA,
                                int                      rowBlockDimC,
                                int                      colBlockDimC,
                                int*                     pBufferSize)
cusparseStatus_t
cusparseXgebsr2gebsrNnz(cusparseHandle_t         handle,
                        cusparseDirection_t      dir,
                        int                      mb,
                        int                      nb,
                        int                      nnzb,
                        const cusparseMatDescr_t descrA,
                        const int*               bsrRowPtrA,
                        const int*               bsrColIndA,
                        int                      rowBlockDimA,
                        int                      colBlockDimA,
                        const cusparseMatDescr_t descrC,
                        int*                     bsrRowPtrC,
                        int                      rowBlockDimC,
                        int                      colBlockDimC,
                        int*                     nnzTotalDevHostPtr,
                        void*                    pBuffer)

cusparseStatus_t
cusparseSgebsr2gebsr(cusparseHandle_t         handle,
                     cusparseDirection_t      dir,
                     int                      mb,
                     int                      nb,
                     int                      nnzb,
                     const cusparseMatDescr_t descrA,
                     const float*             bsrValA,
                     const int*               bsrRowPtrA,
                     const int*               bsrColIndA,
                     int                      rowBlockDimA,
                     int                      colBlockDimA,
                     const cusparseMatDescr_t descrC,
                     float*                   bsrValC,
                     int*                     bsrRowPtrC,
                     int*                     bsrColIndC,
                     int                      rowBlockDimC,
                     int                      colBlockDimC,
                     void*                    pBuffer)

cusparseStatus_t
cusparseDgebsr2gebsr(cusparseHandle_t         handle,
                     cusparseDirection_t      dir,
                     int                      mb,
                     int                      nb,
                     int                      nnzb,
                     const cusparseMatDescr_t descrA,
                     const double*            bsrValA,
                     const int*               bsrRowPtrA,
                     const int*               bsrColIndA,
                     int                      rowBlockDimA,
                     int                      colBlockDimA,
                     const cusparseMatDescr_t descrC,
                     double*                  bsrValC,
                     int*                     bsrRowPtrC,
                     int*                     bsrColIndC,
                     int                      rowBlockDimC,
                     int                      colBlockDimC,
                     void*                    pBuffer)

cusparseStatus_t
cusparseCgebsr2gebsr(cusparseHandle_t         handle,
                     cusparseDirection_t      dir,
                     int                      mb,
                     int                      nb,
                     int                      nnzb,
                     const cusparseMatDescr_t descrA,
                     const cuComplex*         bsrValA,
                     const int*               bsrRowPtrA,
                     const int*               bsrColIndA,
                     int                      rowBlockDimA,
                     int                      colBlockDimA,
                     const cusparseMatDescr_t descrC,
                     cuComplex*               bsrValC,
                     int*                     bsrRowPtrC,
                     int*                     bsrColIndC,
                     int                      rowBlockDimC,
                     int                      colBlockDimC,
                     void*                    pBuffer)

cusparseStatus_t
cusparseZgebsr2gebsr(cusparseHandle_t         handle,
                     cusparseDirection_t      dir,
                     int                      mb,
                     int                      nb,
                     int                      nnzb,
                     const cusparseMatDescr_t descrA,
                     const cuDoubleComplex*   bsrValA,
                     const int*               bsrRowPtrA,
                     const int*               bsrColIndA,
                     int                      rowBlockDimA,
                     int                      colBlockDimA,
                     const cusparseMatDescr_t descrC,
                     cuDoubleComplex*         bsrValC,
                     int*                     bsrRowPtrC,
                     int*                     bsrColIndC,
                     int                      rowBlockDimC,
                     int                      colBlockDimC,
                     void*                    pBuffer)

该函数将由三个数组bsrValAbsrRowPtrAbsrColIndA定义的通用BSR格式稀疏矩阵,转换为由数组bsrValCbsrRowPtrCbsrColIndC定义的另一种通用BSR格式稀疏矩阵。

如果 rowBlockDimA=1colBlockDimA=1,那么 cusparse[S|D|C|Z]gebsr2gebsr() 就等同于 cusparse[S|D|C|Z]csr2gebsr()

如果 rowBlockDimC=1colBlockDimC=1,那么 cusparse[S|D|C|Z]gebsr2gebsr() 就等同于 cusparse[S|D|C|Z]gebsr2csr()

A 是一个 m*n 的稀疏矩阵,其中 m(=mb*rowBlockDim) 表示矩阵 A 的行数,n(=nb*colBlockDim) 表示矩阵 A 的列数。矩阵 A 的通用BSR格式包含 nnzb(=bsrRowPtrA[mb] - bsrRowPtrA[0]) 个非零块。矩阵 C 也是采用不同块大小 rowBlockDimC*colBlockDimC 的通用BSR格式。如果 m 不是 rowBlockDimC 的整数倍,或者 n 不是 colBlockDimC 的整数倍,则会填充零值。矩阵 C 的块行数为 mc(=(m+rowBlockDimC-1)/rowBlockDimC),块列数为 nc(=(n+colBlockDimC-1)/colBlockDimC)。矩阵 C 的非零块数量为 nnzc

该实现采用两步法进行转换。首先,用户分配bsrRowPtrCmc+1个元素,并使用函数cusparseXgebsr2gebsrNnz()确定矩阵C每块行的非零块列数。其次,用户从(nnzc=*nnzTotalDevHostPtr)(nnzc=bsrRowPtrC[mc]-bsrRowPtrC[0])中获取nnzc(矩阵C的非零块列数),并分配bsrValCnnzc*rowBlockDimC*colBlockDimC个元素以及bsrColIndCnnzc个整数。最后调用函数cusparse[S|D|C|Z]gebsr2gebsr()完成转换。

用户必须调用gebsr2gebsr_bufferSize()来获取gebsr2gebsr()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给gebsr2gebsr()

一般流程如下:

// Given general BSR format (bsrRowPtrA, bsrColIndA, bsrValA) and
// blocks of BSR format are stored in column-major order.
cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;
int base, nnzc;
int m = mb*rowBlockDimA;
int n = nb*colBlockDimA;
int mc = (m+rowBlockDimC-1)/rowBlockDimC;
int nc = (n+colBlockDimC-1)/colBlockDimC;
int bufferSize;
void *pBuffer;
cusparseSgebsr2gebsr_bufferSize(handle, dir, mb, nb, nnzb,
    descrA, bsrValA, bsrRowPtrA, bsrColIndA,
    rowBlockDimA, colBlockDimA,
    rowBlockDimC, colBlockDimC,
    &bufferSize);
cudaMalloc((void**)&pBuffer, bufferSize);
cudaMalloc((void**)&bsrRowPtrC, sizeof(int)*(mc+1));
// nnzTotalDevHostPtr points to host memory
int *nnzTotalDevHostPtr = &nnzc;
cusparseXgebsr2gebsrNnz(handle, dir, mb, nb, nnzb,
    descrA, bsrRowPtrA, bsrColIndA,
    rowBlockDimA, colBlockDimA,
    descrC, bsrRowPtrC,
    rowBlockDimC, colBlockDimC,
    nnzTotalDevHostPtr,
    pBuffer);
if (NULL != nnzTotalDevHostPtr){
    nnzc = *nnzTotalDevHostPtr;
}else{
    cudaMemcpy(&nnzc, bsrRowPtrC+mc, sizeof(int), cudaMemcpyDeviceToHost);
    cudaMemcpy(&base, bsrRowPtrC, sizeof(int), cudaMemcpyDeviceToHost);
    nnzc -= base;
}
cudaMalloc((void**)&bsrColIndC, sizeof(int)*nnzc);
cudaMalloc((void**)&bsrValC, sizeof(float)*(rowBlockDimC*colBlockDimC)*nnzc);
cusparseSgebsr2gebsr(handle, dir, mb, nb, nnzb,
    descrA, bsrValA, bsrRowPtrA, bsrColIndA,
    rowBlockDimA, colBlockDimA,
    descrC, bsrValC, bsrRowPtrC, bsrColIndC,
    rowBlockDimC, colBlockDimC,
    pBuffer);
  • 如果pBuffer != NULL,这些例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 这些例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

稀疏矩阵A的块行数。

nb

稀疏矩阵A的块列数。

nnzb

矩阵 A 的非零块数量。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

数组,包含矩阵 Annzb*rowBlockDimA*colBlockDimA 个非零元素。

bsrRowPtrA

包含矩阵A每个块行起始位置以及最后一个块行结束位置加1的mb+1个元素的整数数组。

bsrColIndA

矩阵A非零块的nnzb列索引的整数数组。

rowBlockDimA

A 块内的行数。

colBlockDimA

A 块中的列数。

descrC

矩阵C的描述符。支持的矩阵类型是CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

rowBlockDimC

一个C块内的行数。

colBlockDimC

一个块中的列数C

pBufferSize

包含gebsr2gebsr()中使用的缓冲区字节数的主机指针。

pBuffer

由用户分配的缓冲区;大小由gebsr2gebsr_bufferSize()返回。

输出

bsrValC

矩阵 Cnnzc*rowBlockDimC*colBlockDimC 个非零元素数组。

bsrRowPtrC

包含矩阵C每个块行起始位置及最后一个块行结束位置加1的整型数组,长度为mc+1个元素。

bsrColIndC

矩阵 C 非零块的 nnzc 个块列索引的整数数组。

nnzTotalDevHostPtr

C的非零块总数。*nnzTotalDevHostPtrbsrRowPtrC[mc]-bsrRowPtrC[0]相同。

有关返回状态的描述,请参见cusparseStatus_t

5.9.4. cusparsegebsr2csr() [已弃用]

> 此例程将在未来的主要版本中移除。

cusparseStatus_t
cusparseSgebsr2csr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      mb,
                   int                      nb,
                   const cusparseMatDescr_t descrA,
                   const float*             bsrValA,
                   const int*               bsrRowPtrA,
                   const int*               bsrColIndA,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   const cusparseMatDescr_t descrC,
                   float*                   csrValC,
                   int*                     csrRowPtrC,
                   int*                     csrColIndC)

cusparseStatus_t
cusparseDgebsr2csr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      mb,
                   int                      nb,
                   const cusparseMatDescr_t descrA,
                   const double*            bsrValA,
                   const int*               bsrRowPtrA,
                   const int*               bsrColIndA,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   const cusparseMatDescr_t descrC,
                   double*                  csrValC,
                   int*                     csrRowPtrC,
                   int*                     csrColIndC)

cusparseStatus_t
cusparseCgebsr2csr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      mb,
                   int                      nb,
                   const cusparseMatDescr_t descrA,
                   const cuComplex*         bsrValA,
                   const int*               bsrRowPtrA,
                   const int*               bsrColIndA,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   const cusparseMatDescr_t descrC,
                   cuComplex*               csrValC,
                   int*                     csrRowPtrC,
                   int*                     csrColIndC)

cusparseStatus_t
cusparseZgebsr2csr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      mb,
                   int                      nb,
                   const cusparseMatDescr_t descrA,
                   const cuDoubleComplex*   bsrValA,
                   const int*               bsrRowPtrA,
                   const int*               bsrColIndA,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   const cusparseMatDescr_t descrC,
                   cuDoubleComplex*         csrValC,
                   int*                     csrRowPtrC,
                   int*                     csrColIndC)

该函数将由三个数组bsrValAbsrRowPtrAbsrColIndA定义的通用BSR格式稀疏矩阵转换为由数组csrValCcsrRowPtrCcsrColIndC定义的CSR格式稀疏矩阵。

m(=mb*rowBlockDim)A的行数,n(=nb*colBlockDim)A的列数,则AC都是m*n的稀疏矩阵。A的一般BSR格式包含nnzb(=bsrRowPtrA[mb] - bsrRowPtrA[0])个非零块,而稀疏矩阵A包含nnz(=nnzb*rowBlockDim*colBlockDim)个元素。用户必须为数组csrRowPtrCcsrColIndCcsrValC分配足够的空间。具体要求如下:

csrRowPtrC 包含 m+1 个元素

csrValC 包含 nnz 个元素

csrColIndC 包含 nnz 个元素

一般流程如下:

// Given general BSR format (bsrRowPtrA, bsrColIndA, bsrValA) and
// blocks of BSR format are stored in column-major order.
cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;
int m = mb*rowBlockDim;
int n = nb*colBlockDim;
int nnzb = bsrRowPtrA[mb] - bsrRowPtrA[0]; // number of blocks
int nnz  = nnzb * rowBlockDim * colBlockDim; // number of elements
cudaMalloc((void**)&csrRowPtrC, sizeof(int)*(m+1));
cudaMalloc((void**)&csrColIndC, sizeof(int)*nnz);
cudaMalloc((void**)&csrValC, sizeof(float)*nnz);
cusparseSgebsr2csr(handle, dir, mb, nb,
        descrA,
        bsrValA, bsrRowPtrA, bsrColIndA,
        rowBlockDim, colBlockDim,
        descrC,
        csrValC, csrRowPtrC, csrColIndC);
  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 该例程支持CUDA图捕获

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

mb

稀疏矩阵A的块行数。

nb

稀疏矩阵A的块列数。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

bsrValA

矩阵 Annzb*rowBlockDim*colBlockDim 个非零元素数组。

bsrRowPtrA

包含矩阵A每个块行起始位置以及最后一个块行结束位置加1的mb+1个元素的整数数组。

bsrColIndA

矩阵A非零块的nnzb列索引的整数数组。

rowBlockDim

A 块内的行数。

colBlockDim

A块中的列数。

descrC

矩阵C的描述符。支持的矩阵类型是CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

输出

csrValC

矩阵 Cnnz 个非零元素数组。

csrRowPtrC

包含矩阵C每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndC

矩阵C非零元素的nnz个列索引的整数数组。

有关返回状态的描述,请参见cusparseStatus_t

5.9.5. cusparsecsr2gebsr()

cusparseStatus_t
cusparseScsr2gebsr_bufferSize(cusparseHandle_t         handle,
                              cusparseDirection_t      dir,
                              int                      m,
                              int                      n,
                              const cusparseMatDescr_t descrA,
                              const float*             csrValA,
                              const int*               csrRowPtrA,
                              const int*               csrColIndA,
                              int                      rowBlockDim,
                              int                      colBlockDim,
                              int*                     pBufferSize)

cusparseStatus_t
cusparseDcsr2gebsr_bufferSize(cusparseHandle_t         handle,
                              cusparseDirection_t      dir,
                              int                      m,
                              int                      n,
                              const cusparseMatDescr_t descrA,
                              const double*            csrValA,
                              const int*               csrRowPtrA,
                              const int*               csrColIndA,
                              int                      rowBlockDim,
                              int                      colBlockDim,
                              int*                     pBufferSize)

cusparseStatus_t
cusparseCcsr2gebsr_bufferSize(cusparseHandle_t         handle,
                              cusparseDirection_t      dir,
                              int                      m,
                              int                      n,
                              const cusparseMatDescr_t descrA,
                              const cuComplex*         csrValA,
                              const int*               csrRowPtrA,
                              const int*               csrColIndA,
                              int                      rowBlockDim,
                              int                      colBlockDim,
                              int*                     pBufferSize)

cusparseStatus_t
cusparseZcsr2gebsr_bufferSize(cusparseHandle_t         handle,
                              cusparseDirection_t      dir,
                              int                      m,
                              int                      n,
                              const cusparseMatDescr_t descrA,
                              const cuDoubleComplex*   csrValA,
                              const int*               csrRowPtrA,
                              const int*               csrColIndA,
                              int                      rowBlockDim,
                              int                      colBlockDim,
                              int*                     pBufferSize)
cusparseStatus_t
cusparseXcsr2gebsrNnz(cusparseHandle_t         handle,
                      cusparseDirection_t      dir,
                      int                      m,
                      int                      n,
                      const cusparseMatDescr_t descrA,
                      const int*               csrRowPtrA,
                      const int*               csrColIndA,
                      const cusparseMatDescr_t descrC,
                      int*                     bsrRowPtrC,
                      int                      rowBlockDim,
                      int                      colBlockDim,
                      int*                     nnzTotalDevHostPtr,
                      void*                    pBuffer)

cusparseStatus_t
cusparseScsr2gebsr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      m,
                   int                      n,
                   const cusparseMatDescr_t descrA,
                   const float*             csrValA,
                   const int*               csrRowPtrA,
                   const int*               csrColIndA,
                   const cusparseMatDescr_t descrC,
                   float*                   bsrValC,
                   int*                     bsrRowPtrC,
                   int*                     bsrColIndC,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   void*                    pBuffer)

cusparseStatus_t
cusparseDcsr2gebsr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      m,
                   int                      n,
                   const cusparseMatDescr_t descrA,
                   const double*            csrValA,
                   const int*               csrRowPtrA,
                   const int*               csrColIndA,
                   const cusparseMatDescr_t descrC,
                   double*                  bsrValC,
                   int*                     bsrRowPtrC,
                   int*                     bsrColIndC,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   void*                    pBuffer)

cusparseStatus_t
cusparseCcsr2gebsr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      m,
                   int                      n,
                   const cusparseMatDescr_t descrA,
                   const cuComplex*         csrValA,
                   const int*               csrRowPtrA,
                   const int*               csrColIndA,
                   const cusparseMatDescr_t descrC,
                   cuComplex*               bsrValC,
                   int*                     bsrRowPtrC,
                   int*                     bsrColIndC,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   void*                    pBuffer)

cusparseStatus_t
cusparseZcsr2gebsr(cusparseHandle_t         handle,
                   cusparseDirection_t      dir,
                   int                      m,
                   int                      n,
                   const cusparseMatDescr_t descrA,
                   const cuDoubleComplex*   csrValA,
                   const int*               csrRowPtrA,
                   const int*               csrColIndA,
                   const cusparseMatDescr_t descrC,
                   cuDoubleComplex*         bsrValC,
                   int*                     bsrRowPtrC,
                   int*                     bsrColIndC,
                   int                      rowBlockDim,
                   int                      colBlockDim,
                   void*                    pBuffer)

该函数将CSR格式的稀疏矩阵A(由数组csrValAcsrRowPtrAcsrColIndA定义)转换为通用BSR格式的稀疏矩阵C(由三个数组bsrValCbsrRowPtrCbsrColIndC定义)。

矩阵A是一个 :math: m times n 稀疏矩阵,矩阵 C 是一个 (mb*rowBlockDim)*(nb*colBlockDim) 稀疏矩阵,其中 mb(=(m+rowBlockDim-1)/rowBlockDim) 表示 C 的块行数,而 nb(=(n+colBlockDim-1)/colBlockDim) 表示 C 的块列数。

C的块大小为rowBlockDim*colBlockDim。如果m不是rowBlockDim的倍数,或者n不是colBlockDim的倍数,则会填充零。

该实现采用两步法进行转换。首先,用户分配bsrRowPtrCmb+1个元素,并使用函数cusparseXcsr2gebsrNnz()确定每个块行的非零块列数。其次,用户从(nnzb=*nnzTotalDevHostPtr)(nnzb=bsrRowPtrC[mb]-bsrRowPtrC[0])中获取nnzb(矩阵C的非零块列数),并分配bsrValCnnzb*rowBlockDim*colBlockDim个元素和bsrColIndCnnzb个整数。最后调用函数cusparse[S|D|C|Z]csr2gebsr()完成转换。

用户必须通过调用csr2gebsr_bufferSize()获取csr2gebsr()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给csr2gebsr()

一般流程如下:

// Given CSR format (csrRowPtrA, csrColIndA, csrValA) and
// blocks of BSR format are stored in column-major order.
cusparseDirection_t dir = CUSPARSE_DIRECTION_COLUMN;
int base, nnzb;
int mb = (m + rowBlockDim-1)/rowBlockDim;
int nb = (n + colBlockDim-1)/colBlockDim;
int bufferSize;
void *pBuffer;
cusparseScsr2gebsr_bufferSize(handle, dir, m, n,
    descrA, csrValA, csrRowPtrA, csrColIndA,
    rowBlockDim, colBlockDim,
    &bufferSize);
cudaMalloc((void**)&pBuffer, bufferSize);
cudaMalloc((void**)&bsrRowPtrC, sizeof(int) *(mb+1));
// nnzTotalDevHostPtr points to host memory
int *nnzTotalDevHostPtr = &nnzb;
cusparseXcsr2gebsrNnz(handle, dir, m, n,
    descrA, csrRowPtrA, csrColIndA,
    descrC, bsrRowPtrC, rowBlockDim, colBlockDim,
    nnzTotalDevHostPtr,
    pBuffer);
if (NULL != nnzTotalDevHostPtr){
    nnzb = *nnzTotalDevHostPtr;
}else{
    cudaMemcpy(&nnzb, bsrRowPtrC+mb, sizeof(int), cudaMemcpyDeviceToHost);
    cudaMemcpy(&base, bsrRowPtrC, sizeof(int), cudaMemcpyDeviceToHost);
    nnzb -= base;
}
cudaMalloc((void**)&bsrColIndC, sizeof(int)*nnzb);
cudaMalloc((void**)&bsrValC, sizeof(float)*(rowBlockDim*colBlockDim)*nnzb);
cusparseScsr2gebsr(handle, dir, m, n,
        descrA,
        csrValA, csrRowPtrA, csrColIndA,
        descrC,
        bsrValC, bsrRowPtrC, bsrColIndC,
        rowBlockDim, colBlockDim,
        pBuffer);

例程 cusparseXcsr2gebsrNnz() 具有以下属性:

  • 该例程不需要额外的存储空间。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

例程 cusparsecsr2gebsr() 具有以下属性:

  • 如果pBuffer != NULL,该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dir

块的存储格式,可以是CUSPARSE_DIRECTION_ROWCUSPARSE_DIRECTION_COLUMN

m

稀疏矩阵 A 的行数。

n

稀疏矩阵 A 的列数。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

矩阵 Annz 个非零元素数组。

csrRowPtrA

一个包含矩阵A每行起始位置及最后一行末尾位置加1的m+1个元素的整数数组。

csrColIndA

矩阵A非零元素的nnz列索引整数数组。

descrC

矩阵C的描述符。支持的矩阵类型是CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

rowBlockDim

一个C块内的行数。

colBlockDim

一个块中的列数C

pBuffer

由用户分配的缓冲区,其大小由csr2gebsr_bufferSize()返回。

输出

bsrValC

矩阵 C 的非零元素数组,大小为 nnzb*rowBlockDim*colBlockDim

bsrRowPtrC

包含矩阵C每个块行起始位置及最后一个块行结束位置加1的mb+1个元素的整数数组。

bsrColIndC

矩阵C非零块的nnzb列索引的整数数组。

nnzTotalDevHostPtr

矩阵C的非零块总数。指针nnzTotalDevHostPtr可以指向设备内存或主机内存。

有关返回状态的描述,请参见cusparseStatus_t

5.9.6. cusparsecoo2csr()

cusparseStatus_t
cusparseXcoo2csr(cusparseHandle_t   handle,
                 const int*         cooRowInd,
                 int                nnz,
                 int                m,
                 int*               csrRowPtr,
                 cusparseIndexBase_t idxBase)

该函数将包含未压缩行索引(对应COO格式)的数组转换为压缩行指针数组(对应CSR格式)。

它还可用于将包含未压缩列索引的数组(对应COO格式)转换为列指针数组(对应CSC格式)。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

cooRowInd

长度为nnz的未压缩行索引整数数组。

nnz

稀疏矩阵的非零元素数量(同时也是数组cooRowInd的长度)。

m

矩阵 A 的行数。

idxBase

CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

输出

csrRowPtr

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

有关返回状态的描述,请参见cusparseStatus_t

5.9.7. cusparsecsr2coo()

cusparseStatus_t
cusparseXcsr2coo(cusparseHandle_t    handle,
                 const int*          csrRowPtr,
                 int                 nnz,
                 int                 m,
                 int*                cooRowInd,
                 cusparseIndexBase_t idxBase)

该函数将包含压缩行指针的数组(对应CSR格式)转换为未压缩行索引的数组(对应COO格式)。

它还可用于将包含压缩列索引(对应CSC格式)的数组转换为未压缩列索引(对应COO格式)的数组。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

csrRowPtr

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

nnz

稀疏矩阵的非零元素数量(同时也是数组cooRowInd的长度)。

m

矩阵 A 的行数。

idxBase

CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

输出

cooRowInd

长度为nnz的未压缩行索引整数数组。

有关返回状态的描述,请参见cusparseStatus_t

5.9.8. cusparseCsr2cscEx2()

cusparseStatus_t
cusparseCsr2cscEx2_bufferSize(cusparseHandle_t     handle,
                              int                  m,
                              int                  n,
                              int                  nnz,
                              const void*          csrVal,
                              const int*           csrRowPtr,
                              const int*           csrColInd,
                              void*                cscVal,
                              int*                 cscColPtr,
                              int*                 cscRowInd,
                              cudaDataType         valType,
                              cusparseAction_t     copyValues,
                              cusparseIndexBase_t  idxBase,
                              cusparseCsr2CscAlg_t alg,
                              size_t*              bufferSize)
cusparseStatus_t
cusparseCsr2cscEx2(cusparseHandle_t     handle,
                   int                  m,
                   int                  n,
                   int                  nnz,
                   const void*          csrVal,
                   const int*           csrRowPtr,
                   const int*           csrColInd,
                   void*                cscVal,
                   int*                 cscColPtr,
                   int*                 cscRowInd,
                   cudaDataType         valType,
                   cusparseAction_t     copyValues,
                   cusparseIndexBase_t  idxBase,
                   cusparseCsr2CscAlg_t alg,
                   void*                buffer)

该函数将CSR格式的稀疏矩阵(由三个数组csrValcsrRowPtrcsrColInd定义)转换为CSC格式的稀疏矩阵(由数组cscValcscRowIndcscColPtr定义)。结果矩阵也可以视为原始稀疏矩阵的转置。请注意,此例程也可用于将CSC格式的矩阵转换为CSR格式的矩阵。

该例程需要与非零值数量nnz成比例的额外存储空间。它在输出中始终提供相同的矩阵。

它相对于主机是异步执行的,可能在结果准备就绪之前就将控制权返回给主机上的应用程序。

函数 cusparseCsr2cscEx2_bufferSize() 返回 cusparseCsr2cscEx2() 所需工作空间的大小。用户需要分配一个此大小的缓冲区,并将该缓冲区作为参数传递给 cusparseCsr2cscEx2()

如果 nnz == 0,那么 csrColIndcsrValcscValcscRowInd 可能为 NULL 值。在这种情况下,cscColPtr 的所有值都将被设置为 idxBase

如果m == 0n == 0,则不会检查指针,并且该例程返回CUSPARSE_STATUS_SUCCESS

输入

handle

cuSPARSE库上下文的句柄

m

CSR输入矩阵的行数;CSC输出矩阵的列数

n

CSR输入矩阵的列数;CSC输出矩阵的行数

nnz

CSR和CSC矩阵的非零元素数量

csrVal

CSR矩阵的大小为nnz的值数组;类型与valType相同

csrRowPtr

大小为m + 1的整数数组,包含CSR行偏移量

csrColInd

大小为nnz的整数数组,包含CSR列索引

cscVal

CSC矩阵的大小为nnz的值数组;与valType类型相同

cscColPtr

大小为n + 1的整数数组,包含CSC列偏移量

cscRowInd

大小为nnz的整数数组,包含CSC行索引

valType

CSR和CSC矩阵的值类型

copyValues

CUSPARSE_ACTION_SYMBOLICCUSPARSE_ACTION_NUMERIC

idxBase

索引基准 CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

alg

算法实现。有关可能的值,请参见cusparseCsr2CscAlg_t

bufferSize

cusparseCsr2cscEx2() 所需的暂存空间字节数

buffer

指向工作区缓冲区的指针

cusparseCsr2cscEx2() 支持以下数据类型:

X/Y

CUDA_R_8I

CUDA_R_16F

CUDA_R_16BF

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

cusparseCsr2cscEx2() 支持以下算法 (cusparseCsr2CscAlg_t):

算法

备注

CUSPARSE_CSR2CSC_ALG_DEFAULT, CUSPARSE_CSR2CSC_ALG1

默认算法

操作

备注

CUSPARSE_ACTION_SYMBOLIC

计算CSC输出矩阵的"结构"(偏移量、行索引)

CUSPARSE_ACTION_NUMERIC

计算CSC输出矩阵的"结构"并复制数值

cusparseCsr2cscEx2() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

cusparseCsr2cscEx2() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

5.9.9. cusparsennz()

cusparseStatus_t
cusparseSnnz(cusparseHandle_t        handle,
             cusparseDirection_t     dirA,
             int                      m,
             int                      n,
             const cusparseMatDescr_t descrA,
             const float*             A,
             int                      lda,
             int*                     nnzPerRowColumn,
             int*                     nnzTotalDevHostPtr)

cusparseStatus_t
cusparseDnnz(cusparseHandle_t        handle,
             cusparseDirection_t     dirA,
             int                      m,
             int                      n,
             const cusparseMatDescr_t descrA,
             const double*            A,
             int                      lda,
             int*                     nnzPerRowColumn,
             int*                     nnzTotalDevHostPtr)

cusparseStatus_t
cusparseCnnz(cusparseHandle_t        handle,
             cusparseDirection_t     dirA,
             int                      m,
             int                      n,
             const cusparseMatDescr_t descrA,
             const cuComplex*         A,
             int                      lda,
             int*                     nnzPerRowColumn,
             int*                     nnzTotalDevHostPtr)

cusparseStatus_t
cusparseZnnz(cusparseHandle_t        handle,
             cusparseDirection_t     dirA,
             int                      m,
             int                      n,
             const cusparseMatDescr_t descrA,
             const cuDoubleComplex*   A,
             int                      lda,
             int*                     nnzPerRowColumn,
             int*                     nnzTotalDevHostPtr)

该函数计算稠密矩阵中每行或每列的非零元素数量以及非零元素的总数。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

dirA

指定按CUSPARSE_DIRECTION_ROW还是按CUSPARSE_DIRECTION_COLUMN计算非零元素的方向。

m

矩阵 A 的行数。

n

矩阵 A 的列数。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

A

维度数组 (lda, n)

lda

稠密数组A的主维度。

输出

nnzPerRowColumn

大小为mn的数组,分别包含每行或每列的非零元素数量

nnzTotalDevHostPtr

设备或主机内存中的非零元素总数

有关返回状态的描述,请参见cusparseStatus_t

5.9.10. cusparseCreateIdentityPermutation() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateIdentityPermutation(cusparseHandle_t handle,
                                  int              n,
                                  int*             p);

此函数创建一个恒等映射。输出参数 p 通过 p = 0:1:(n-1) 表示这样的映射。

该函数通常与coosortcsrsortcscsort配合使用。

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

n

host

地图的大小。

输出

parameter

device or host

描述

p

device

维度为 n 的整数数组。

有关返回状态的描述,请参见cusparseStatus_t

5.9.11. cusparseXcoosort()

cusparseStatus_t
cusparseXcoosort_bufferSizeExt(cusparseHandle_t handle,
                               int              m,
                               int              n,
                               int              nnz,
                               const int*       cooRows,
                               const int*       cooCols,
                               size_t*          pBufferSizeInBytes)
cusparseStatus_t
cusparseXcoosortByRow(cusparseHandle_t handle,
                      int              m,
                      int              n,
                      int              nnz,
                      int*             cooRows,
                      int*             cooCols,
                      int*             P,
                      void*            pBuffer)

cusparseStatus_t
cusparseXcoosortByColumn(cusparseHandle_t handle,
                         int              m,
                         int              n,
                         int              nnz,
                         int*             cooRows,
                         int*             cooCols,
                         int*             P,
                         void*            pBuffer);

该函数对COO格式进行排序。排序是原地进行的。用户还可以选择按行或按列排序。

A 是一个 \(m \times n\) 稀疏矩阵,通过三个数组 cooValscooRowscooCols 以COO存储格式定义。

矩阵的基索引没有假设。coosort 对有符号整数使用稳定排序,因此 cooRowscooCols 的值可以是负数。

此函数coosort()需要由coosort_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

参数 P 既是输入也是输出。如果用户想要计算排序后的 cooVal,必须在 coosort() 之前将 P 设为 0:1:(nnz-1),而在 coosort() 之后,新的排序值数组满足 cooVal_sorted = cooVal(P)

备注:维度mn未被使用。如果用户不知道mn的值,只需传入一个正数值。这种情况通常发生在用户先读取COO数组后,需要稍后确定维度mn时。

  • 如果pBuffer != NULL,该例程不需要额外存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

nnz

host

矩阵A的非零元素数量。

cooRows

device

nnz个未排序行索引的整数数组,对应于矩阵A

cooCols

device

nnz个未排序的列索引的整数数组,对应于矩阵A

P

device

长度为nnz的未排序映射索引整数数组。要构建cooVal,用户需要设置P=0:1:(nnz-1)

pBuffer

device

由用户分配的缓冲区;大小由coosort_bufferSizeExt()返回。

输出

parameter

device or host

描述

cooRows

device

nnz个整数的数组,表示A已排序的行索引。

cooCols

device

nnz 的整数数组,表示 A 的已排序列索引。

P

device

nnz个已排序映射索引组成的整数数组。

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseXcoosortByRow查看代码示例。

5.9.12. cusparseXcsrsort()

cusparseStatus_t
cusparseXcsrsort_bufferSizeExt(cusparseHandle_t handle,
                               int              m,
                               int              n,
                               int              nnz,
                               const int*       csrRowPtr,
                               const int*       csrColInd,
                               size_t*          pBufferSizeInBytes)
cusparseStatus_t
cusparseXcsrsort(cusparseHandle_t         handle,
                 int                      m,
                 int                      n,
                 int                      nnz,
                 const cusparseMatDescr_t descrA,
                 const int*               csrRowPtr,
                 int*                     csrColInd,
                 int*                     P,
                 void*                    pBuffer)

该函数对CSR格式进行排序。稳定的排序是原地进行的。

矩阵类型隐式被视为CUSPARSE_MATRIX_TYPE_GENERAL。换句话说,任何对称属性都将被忽略。

此函数csrsort()需要由csrsort_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

参数 P 既是输入也是输出。如果用户想要计算排序后的 csrVal,在调用 csrsort() 之前必须将 P 设为 0:1:(nnz-1),而在 csrsort() 之后,新的排序值数组满足 csrVal_sorted = csrVal(P)

一般流程如下:

// A is a 3x3 sparse matrix, base-0
//     | 1 2 3 |
// A = | 4 5 6 |
//     | 7 8 9 |
const int m = 3;
const int n = 3;
const int nnz = 9;
csrRowPtr[m+1] = { 0, 3, 6, 9}; // on device
csrColInd[nnz] = { 2, 1, 0, 0, 2,1, 1, 2, 0}; // on device
csrVal[nnz] = { 3, 2, 1, 4, 6, 5, 8, 9, 7}; // on device
size_t pBufferSizeInBytes = 0;
void *pBuffer = NULL;
int *P = NULL;

// step 1: allocate buffer
cusparseXcsrsort_bufferSizeExt(handle, m, n, nnz, csrRowPtr, csrColInd, &pBufferSizeInBytes);
cudaMalloc( &pBuffer, sizeof(char)* pBufferSizeInBytes);

// step 2: setup permutation vector P to identity
cudaMalloc( (void**)&P, sizeof(int)*nnz);
cusparseCreateIdentityPermutation(handle, nnz, P);

// step 3: sort CSR format
cusparseXcsrsort(handle, m, n, nnz, descrA, csrRowPtr, csrColInd, P, pBuffer);

// step 4: gather sorted csrVal
cusparseDgthr(handle, nnz, csrVal, csrVal_sorted, P, CUSPARSE_INDEX_BASE_ZERO);
  • 如果pBuffer != NULL,该例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

nnz

host

矩阵A的非零元素数量。

csrRowsPtr

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColInd

device

nnz 个未排序的 A 列索引的整数数组。

P

device

长度为nnz的未排序映射索引整型数组。要构建csrVal,用户需设置P=0:1:(nnz-1)

pBuffer

device

由用户分配的缓冲区;大小由csrsort_bufferSizeExt()返回。

输出

parameter

device or host

描述

csrColInd

device

Annz个已排序列索引的整数数组。

P

device

长度为nnz的整数数组,包含已排序的映射索引。

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.9.13. cusparseXcscsort()

cusparseStatus_t
cusparseXcscsort_bufferSizeExt(cusparseHandle_t handle,
                               int              m,
                               int              n,
                               int              nnz,
                               const int*       cscColPtr,
                               const int*       cscRowInd,
                               size_t*          pBufferSizeInBytes)
cusparseStatus_t
cusparseXcscsort(cusparseHandle_t         handle,
                 int                      m,
                 int                      n,
                 int                      nnz,
                 const cusparseMatDescr_t descrA,
                 const int*               cscColPtr,
                 int*                     cscRowInd,
                 int*                     P,
                 void*                    pBuffer)

该函数对CSC格式进行排序。稳定的排序是原地进行的。

矩阵类型隐式被视为CUSPARSE_MATRIX_TYPE_GENERAL。换句话说,任何对称属性都将被忽略。

此函数cscsort()需要由cscsort_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE

参数 P 既是输入也是输出。如果用户想要计算排序后的 cscVal,在调用 cscsort() 之前必须将 P 设为 0:1:(nnz-1),而在调用 cscsort() 之后,新的排序值数组满足 cscVal_sorted = cscVal(P)

一般流程如下:

// A is a 3x3 sparse matrix, base-0
//     | 1 2  |
// A = | 4 0  |
//     | 0 8  |
const int m = 3;
const int n = 2;
const int nnz = 4;
cscColPtr[n+1] = { 0, 2, 4}; // on device
cscRowInd[nnz] = { 1, 0, 2, 0}; // on device
cscVal[nnz]    = { 4.0, 1.0, 8.0, 2.0 }; // on device
size_t pBufferSizeInBytes = 0;
void *pBuffer = NULL;
int *P = NULL;

// step 1: allocate buffer
cusparseXcscsort_bufferSizeExt(handle, m, n, nnz, cscColPtr, cscRowInd, &pBufferSizeInBytes);
cudaMalloc( &pBuffer, sizeof(char)* pBufferSizeInBytes);

// step 2: setup permutation vector P to identity
cudaMalloc( (void**)&P, sizeof(int)*nnz);
cusparseCreateIdentityPermutation(handle, nnz, P);

// step 3: sort CSC format
cusparseXcscsort(handle, m, n, nnz, descrA, cscColPtr, cscRowInd, P, pBuffer);

// step 4: gather sorted cscVal
cusparseDgthr(handle, nnz, cscVal, cscVal_sorted, P, CUSPARSE_INDEX_BASE_ZERO);
  • 如果pBuffer != NULL,该例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

nnz

host

矩阵A的非零元素数量。

cscColPtr

device

包含每列起始位置及最后一列结束位置加1的n+1个元素的整数数组。

cscRowInd

device

nnz个未排序的A行索引的整数数组。

P

device

长度为nnz的未排序映射索引整型数组。要构建cscVal,用户需要设置P=0:1:(nnz-1)

pBuffer

device

由用户分配的缓冲区;大小由cscsort_bufferSizeExt()返回。

输出

parameter

device or host

描述

cscRowInd

device

nnz个整数的数组,表示A已排序的行索引。

P

device

长度为nnz的整数数组,包含已排序的映射索引。

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.9.14. cusparseXcsru2csr() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseCreateCsru2csrInfo(csru2csrInfo_t *info);

cusparseStatus_t
cusparseDestroyCsru2csrInfo(csru2csrInfo_t info);

cusparseStatus_t
cusparseScsru2csr_bufferSizeExt(cusparseHandle_t handle,
                                int              m,
                                int              n,
                                int              nnz,
                                float*           csrVal,
                                const int*       csrRowPtr,
                                int*             csrColInd,
                                csru2csrInfo_t   info,
                                size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseDcsru2csr_bufferSizeExt(cusparseHandle_t handle,
                                int              m,
                                int              n,
                                int              nnz,
                                double*          csrVal,
                                const int*       csrRowPtr,
                                int*             csrColInd,
                                csru2csrInfo_t   info,
                                size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseCcsru2csr_bufferSizeExt(cusparseHandle_t handle,
                                int              m,
                                int              n,
                                int              nnz,
                                cuComplex*       csrVal,
                                const int*       csrRowPtr,
                                int*             csrColInd,
                                csru2csrInfo_t   info,
                                size_t*          pBufferSizeInBytes)

cusparseStatus_t
cusparseZcsru2csr_bufferSizeExt(cusparseHandle_t handle,
                                int              m,
                                int              n,
                                int              nnz,
                                cuDoubleComplex* csrVal,
                                const int*       csrRowPtr,
                                int*             csrColInd,
                                csru2csrInfo_t   info,
                                size_t*          pBufferSizeInBytes)
cusparseStatus_t
cusparseScsru2csr(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  float*                   csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

cusparseStatus_t
cusparseDcsru2csr(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  double*                  csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

cusparseStatus_t
cusparseCcsru2csr(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  cuComplex*               csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

cusparseStatus_t
cusparseZcsru2csr(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  cuDoubleComplex*         csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)
cusparseStatus_t
cusparseScsr2csru(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  float*                   csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

cusparseStatus_t
cusparseDcsr2csru(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  double*                  csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

cusparseStatus_t
cusparseCcsr2csru(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  cuComplex*               csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

cusparseStatus_t
cusparseZcsr2csru(cusparseHandle_t         handle,
                  int                      m,
                  int                      n,
                  int                      nnz,
                  const cusparseMatDescr_t descrA,
                  cuDoubleComplex*         csrVal,
                  const int*               csrRowPtr,
                  int*                     csrColInd,
                  csru2csrInfo_t           info,
                  void*                    pBuffer)

该函数将未排序的CSR格式转换为CSR格式,反之亦然。此操作是原地进行的。

该函数是csrsortgthr的封装器。使用场景如下所示。

如果用户有一个未排序的CSR格式矩阵A,并基于这种特殊顺序(例如先对角线,再下三角,最后上三角)实现了自己的代码(可以是CPU或GPU内核),希望在调用CUSPARSE库时将其转换为CSR格式,然后在内核上进行其他操作时再转换回来。例如,假设用户想通过以下迭代方案求解线性系统Ax=b

\[x^{(k+1)} = x^{(k)} + L^{(-1)}*(b - Ax^{(k)})\]

该代码大量使用了稀疏矩阵向量乘法(SpMV)和三角求解。假设用户基于A的特殊排序拥有自研的稀疏矩阵向量乘法实现,但希望使用cuSPARSE库进行三角求解。那么以下代码可以工作:

do

步骤1: 计算残差向量

\(r = b - A x^k\) 通过内部SpMV实现

步骤2: B := 对A进行排序,L是B的下三角部分

(只需对A排序一次并保留置换向量)

步骤3:求解

\(z = L (-1) * ( b - A x^k )\) 通过 cusparseXcsrsv

步骤4:添加修正项

\(x^{k+1} = x^k+z\)

步骤5: A := unsort(B)

(使用置换向量恢复未排序的CSR格式)

直到收敛

步骤2和步骤5的要求是

  1. 原地操作。

  2. 置换向量 P 被隐藏在一个不透明的结构中。

  3. 在转换例程内部不使用cudaMalloc。相反,用户必须显式提供缓冲区。

  4. 在未排序的CSR和已排序的CSR之间进行转换可能需要多次操作,但该函数仅生成一次置换向量P

  5. 该函数基于csrsortgatherscatter操作。

该操作名为csru2csr,表示将未排序的CSR转换为排序后的CSR。同时我们也提供逆向操作,名为csr2csru

为了保持排列向量不可见,我们需要一个名为csru2csrInfo的不透明结构体。然后使用两个函数(cusparseCreateCsru2csrInfo, cusparseDestroyCsru2csrInfo)来初始化和销毁这个不透明结构体。

cusparse[S|D|C|Z]csru2csr_bufferSizeExt 返回缓冲区的大小。置换向量 P 也分配在 csru2csrInfo 内部。该置换向量的生命周期与 csru2csrInfo 的生命周期相同。

cusparse[S|D|C|Z]csru2csr 执行从无序CSR到有序CSR的正向转换。首次调用使用csrsort生成置换向量P,后续调用使用P进行转换。

cusparse[S|D|C|Z]csr2csru 执行从排序后的CSR到未排序CSR的逆向转换。P 用于恢复未排序形式。

例程 cusparsecsru2csr() 具有以下属性:

  • 如果pBuffer != NULL,该例程不需要额外的存储空间

  • 如果流序内存分配器可用,该例程支持异步执行

  • 如果流序内存分配器可用,该例程支持CUDA图捕获

如果pBuffer != NULL,则例程cusparsecsr2csru()具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 该例程支持CUDA图捕获

以下表格描述了csr2csru_bufferSizeExtcsr2csru的参数。

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

nnz

host

矩阵A的非零元素数量。

描述A

host

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrVal

device

矩阵 A 中 nnz 个未排序非零元素的数组。

csrRowsPtr

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColInd

device

nnz 个未排序的 A 列索引的整数数组。

信息

host

使用cusparseCreateCsru2csrInfo()初始化的不透明结构体。

pBuffer

device

由用户分配的缓冲区;大小由csru2csr_bufferSizeExt()返回。

输出

parameter

device or host

描述

csrVal

device

矩阵 A 已排序的 nnz 个非零元素数组。

csrColInd

device

Annz个已排序列索引的整数数组。

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.9.15. cusparseXpruneDense2csr() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseHpruneDense2csr_bufferSizeExt(cusparseHandle_t          handle,
                                       int                      m,
                                       int                      n,
                                       const __half*            A,
                                       int                      lda,
                                       const __half*            threshold,
                                       const cusparseMatDescr_t descrC,
                                       const __half*            csrValC,
                                       const int*               csrRowPtrC,
                                       const int*               csrColIndC,
                                       size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseSpruneDense2csr_bufferSizeExt(cusparseHandle_t          handle,
                                       int                      m,
                                       int                      n,
                                       const float*             A,
                                       int                      lda,
                                       const float*             threshold,
                                       const cusparseMatDescr_t descrC,
                                       const float*             csrValC,
                                       const int*               csrRowPtrC,
                                       const int*               csrColIndC,
                                       size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseDpruneDense2csr_bufferSizeExt(cusparseHandle_t          handle,
                                       int                      m,
                                       int                      n,
                                       const double*            A,
                                       int                      lda,
                                       const double*            threshold,
                                       const cusparseMatDescr_t descrC,
                                       const double*            csrValC,
                                       const int*               csrRowPtrC,
                                       const int*               csrColIndC,
                                       size_t*                  pBufferSizeInBytes)
cusparseStatus_t
cusparseHpruneDense2csrNnz(cusparseHandle_t         handle,
                           int                      m,
                           int                      n,
                           const __half*            A,
                           int                      lda,
                           const __half*            threshold,
                           const cusparseMatDescr_t descrC,
                           int*                     csrRowPtrC,
                           int*                     nnzTotalDevHostPtr,
                           void*                    pBuffer)

cusparseStatus_t
cusparseSpruneDense2csrNnz(cusparseHandle_t         handle,
                           int                      m,
                           int                      n,
                           const float*             A,
                           int                      lda,
                           const float*             threshold,
                           const cusparseMatDescr_t descrC,
                           int*                     csrRowPtrC,
                           int*                     nnzTotalDevHostPtr,
                           void*                    pBuffer)

cusparseStatus_t
cusparseDpruneDense2csrNnz(cusparseHandle_t         handle,
                           int                      m,
                           int                      n,
                           const double*            A,
                           int                      lda,
                           const double*            threshold,
                           const cusparseMatDescr_t descrC,
                           int*                     csrRowPtrC,
                           int*                     nnzTotalDevHostPtr,
                           void*                    pBuffer)
cusparseStatus_t
cusparseHpruneDense2csr(cusparseHandle_t         handle,
                        int                      m,
                        int                      n,
                        const __half*            A,
                        int                      lda,
                        const __half*            threshold,
                        const cusparseMatDescr_t descrC,
                        __half*                  csrValC,
                        const int*               csrRowPtrC,
                        int*                     csrColIndC,
                        void*                    pBuffer)

cusparseStatus_t
cusparseSpruneDense2csr(cusparseHandle_t         handle,
                        int                      m,
                        int                      n,
                        const float*             A,
                        int                      lda,
                        const float*             threshold,
                        const cusparseMatDescr_t descrC,
                        float*                   csrValC,
                        const int*               csrRowPtrC,
                        int*                     csrColIndC,
                        void*                    pBuffer)

cusparseStatus_t
cusparseDpruneDense2csr(cusparseHandle_t         handle,
                        int                      m,
                        int                      n,
                        const double*            A,
                        int                      lda,
                        const double*            threshold,
                        const cusparseMatDescr_t descrC,
                        double*                  csrValC,
                        const int*               csrRowPtrC,
                        int*                     csrColIndC,
                        void*                    pBuffer)

该函数将稠密矩阵修剪为CSR格式的稀疏矩阵。

给定一个稠密矩阵 A 和一个非负值 threshold,该函数返回一个稀疏矩阵 C,其定义为

\[\begin{split}\begin{matrix} {{C(i,j)} = {A(i,j)}} & \text{当\ |A(i,j)|\ 大于\ 阈值时} \\ \end{matrix}\end{split}\]

该实现采用两步法进行转换。首先,用户分配csrRowPtrCm+1个元素,并使用函数pruneDense2csrNnz()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中获取nnzC(矩阵C的非零元素数量),并分配csrValCnnzC个元素和csrColIndCnnzC个整数。最后调用函数pruneDense2csr()完成转换。

用户必须通过调用pruneDense2csr_bufferSizeExt()获取pruneDense2csr()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneDense2csr()

例程 cusparsepruneDense2csrNnz() 具有以下属性:

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

例程 cusparseDpruneDense2csr() 具有以下特性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

A

device

维度为(lda, n)的数组。

lda

device

A的主维度。必须至少为max(1, m)。

threshold

host or device

一个用于删除A条目的值。threshold可以指向设备内存或主机内存。

descrC

host

矩阵C的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

pBuffer

device

由用户分配的缓冲区;大小由pruneDense2csr_bufferSizeExt()返回。

输出

parameter

device or host

描述

nnzTotalDevHostPtr

device or host

矩阵C的非零元素总数。nnzTotalDevHostPtr可以指向设备内存或主机内存。

csrValC

device

矩阵 CnnzC 个非零元素数组。

csrRowsPtrC

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndC

device

nnzC列索引的整数数组,对应矩阵C

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.9.16. cusparseXpruneCsr2csr() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseHpruneCsr2csr_bufferSizeExt(cusparseHandle_t         handle,
                                    int                      m,
                                    int                      n,
                                    int                      nnzA,
                                    const cusparseMatDescr_t descrA,
                                    const __half*            csrValA,
                                    const int*               csrRowPtrA,
                                    const int*               csrColIndA,
                                    const __half*            threshold,
                                    const cusparseMatDescr_t descrC,
                                    const __half*            csrValC,
                                    const int*               csrRowPtrC,
                                    const int*               csrColIndC,
                                    size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseSpruneCsr2csr_bufferSizeExt(cusparseHandle_t         handle,
                                    int                      m,
                                    int                      n,
                                    int                      nnzA,
                                    const cusparseMatDescr_t descrA,
                                    const float*             csrValA,
                                    const int*               csrRowPtrA,
                                    const int*               csrColIndA,
                                    const float*             threshold,
                                    const cusparseMatDescr_t descrC,
                                    const float*             csrValC,
                                    const int*               csrRowPtrC,
                                    const int*               csrColIndC,
                                    size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseDpruneCsr2csr_bufferSizeExt(cusparseHandle_t         handle,
                                    int                      m,
                                    int                      n,
                                    int                      nnzA,
                                    const cusparseMatDescr_t descrA,
                                    const double*            csrValA,
                                    const int*               csrRowPtrA,
                                    const int*               csrColIndA,
                                    const double*            threshold,
                                    const cusparseMatDescr_t descrC,
                                    const double*            csrValC,
                                    const int*               csrRowPtrC,
                                    const int*               csrColIndC,
                                    size_t*                  pBufferSizeInBytes)
cusparseStatus_t
cusparseHpruneCsr2csrNnz(cusparseHandle_t         handle,
                         int                      m,
                         int                      n,
                         int                      nnzA,
                         const cusparseMatDescr_t descrA,
                         const __half*            csrValA,
                         const int*               csrRowPtrA,
                         const int*               csrColIndA,
                         const __half*            threshold,
                         const cusparseMatDescr_t descrC,
                         int*                     csrRowPtrC,
                         int*                     nnzTotalDevHostPtr,
                         void*                    pBuffer)

cusparseStatus_t
cusparseSpruneCsr2csrNnz(cusparseHandle_t         handle,
                         int                      m,
                         int                      n,
                         int                      nnzA,
                         const cusparseMatDescr_t descrA,
                         const float*             csrValA,
                         const int*               csrRowPtrA,
                         const int*               csrColIndA,
                         const float*             threshold,
                         const cusparseMatDescr_t descrC,
                         int*                     csrRowPtrC,
                         int*                     nnzTotalDevHostPtr,
                         void*                    pBuffer)

cusparseStatus_t
cusparseDpruneCsr2csrNnz(cusparseHandle_t         handle,
                         int                      m,
                         int                      n,
                         int                      nnzA,
                         const cusparseMatDescr_t descrA,
                         const double*            csrValA,
                         const int*               csrRowPtrA,
                         const int*               csrColIndA,
                         const double*            threshold,
                         const cusparseMatDescr_t descrC,
                         int*                     csrRowPtrC,
                         int*                     nnzTotalDevHostPtr,
                         void*                    pBuffer)
cusparseStatus_t
cusparseHpruneCsr2csr(cusparseHandle_t         handle,
                      int                      m,
                      int                      n,
                      int                      nnzA,
                      const cusparseMatDescr_t descrA,
                      const __half*            csrValA,
                      const int*               csrRowPtrA,
                      const int*               csrColIndA,
                      const __half*            threshold,
                      const cusparseMatDescr_t descrC,
                      __half*                  csrValC,
                      const int*               csrRowPtrC,
                      int*                     csrColIndC,
                      void*                    pBuffer)

cusparseStatus_t
cusparseSpruneCsr2csr(cusparseHandle_t         handle,
                      int                      m,
                      int                      n,
                      int                      nnzA,
                      const cusparseMatDescr_t descrA,
                      const float*             csrValA,
                      const int*               csrRowPtrA,
                      const int*               csrColIndA,
                      const float*             threshold,
                      const cusparseMatDescr_t descrC,
                      float*                   csrValC,
                      const int*               csrRowPtrC,
                      int*                     csrColIndC,
                      void*                    pBuffer)

cusparseStatus_t
cusparseDpruneCsr2csr(cusparseHandle_t         handle,
                      int                      m,
                      int                      n,
                      int                      nnzA,
                      const cusparseMatDescr_t descrA,
                      const double*            csrValA,
                      const int*               csrRowPtrA,
                      const int*               csrColIndA,
                      const double*            threshold,
                      const cusparseMatDescr_t descrC,
                      double*                  csrValC,
                      const int*               csrRowPtrC,
                      int*                     csrColIndC,
                      void*                    pBuffer)

该函数将稀疏矩阵修剪为采用CSR格式的稀疏矩阵。

给定一个稀疏矩阵 A 和一个非负值 threshold,该函数返回一个稀疏矩阵 C,其定义为

\[\begin{split}\begin{matrix} {{C(i,j)} = {A(i,j)}} & \text{如果 |A(i,j)| > 阈值} \\ \end{matrix}\end{split}\]

该实现采用两步法进行转换。首先,用户分配csrRowPtrCm+1个元素,并使用函数pruneCsr2csrNnz()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中获取nnzC(矩阵C的非零元素数量),然后分配csrValCnnzC个元素和csrColIndCnnzC个整数。最后调用函数pruneCsr2csr()完成转换。

用户必须通过调用pruneCsr2csr_bufferSizeExt()获取pruneCsr2csr()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneCsr2csr()

例程 cusparsepruneCsr2csrNnz() 具有以下特性:

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

例程 cusparsepruneCsr2csr() 具有以下特性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

nnzA

host

矩阵 A 的非零元素数量。

描述A

host

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

device

矩阵 AnnzA 个非零元素数组。

csrRowsPtrA

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndA

device

nnzA 的整数数组,表示 A 的列索引。

threshold

host device

一个用于删除A条目的值。threshold可以指向设备内存或主机内存。

descrC

host

矩阵C的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

pBuffer

device

由用户分配的缓冲区;大小由pruneCsr2csr_bufferSizeExt()返回。

输出

parameter

device or host

描述

nnzTotalDevHostPtr

device or host

矩阵C的非零元素总数。nnzTotalDevHostPtr可以指向设备内存或主机内存。

csrValC

device

矩阵 CnnzC 个非零元素数组。

csrRowsPtrC

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndC

device

nnzC列索引的整数数组,对应矩阵C

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.9.17. cusparseXpruneDense2csrPercentage() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseHpruneDense2csrByPercentage_bufferSizeExt(cusparseHandle_t         handle,
                                                  int                      m,
                                                  int                      n,
                                                  const __half*            A,
                                                  int                      lda,
                                                  float                    percentage,
                                                  const cusparseMatDescr_t descrC,
                                                  const __half*            csrValC,
                                                  const int*               csrRowPtrC,
                                                  const int*               csrColIndC,
                                                  pruneInfo_t              info,
                                                  size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseSpruneDense2csrByPercentage_bufferSizeExt(cusparseHandle_t         handle,
                                                  int                      m,
                                                  int                      n,
                                                  const float*             A,
                                                  int                      lda,
                                                  float                    percentage,
                                                  const cusparseMatDescr_t descrC,
                                                  const float*             csrValC,
                                                  const int*               csrRowPtrC,
                                                  const int*               csrColIndC,
                                                  pruneInfo_t              info,
                                                  size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseDpruneDense2csrByPercentage_bufferSizeExt(cusparseHandle_t         handle,
                                                  int                      m,
                                                  int                      n,
                                                  const double*            A,
                                                  int                      lda,
                                                  float                    percentage,
                                                  const cusparseMatDescr_t descrC,
                                                  const double*            csrValC,
                                                  const int*               csrRowPtrC,
                                                  const int*               csrColIndC,
                                                  pruneInfo_t              info,
                                                  size_t*                  pBufferSizeInBytes)
cusparseStatus_t
cusparseHpruneDense2csrNnzByPercentage(cusparseHandle_t         handle,
                                       int                      m,
                                       int                      n,
                                       const __half*            A,
                                       int                      lda,
                                       float                    percentage,
                                       const cusparseMatDescr_t descrC,
                                       int*                     csrRowPtrC,
                                       int*                     nnzTotalDevHostPtr,
                                       pruneInfo_t              info,
                                       void*                    pBuffer)

cusparseStatus_t
cusparseSpruneDense2csrNnzByPercentage(cusparseHandle_t         handle,
                                       int                      m,
                                       int                      n,
                                       const float*             A,
                                       int                      lda,
                                       float                    percentage,
                                       const cusparseMatDescr_t descrC,
                                       int*                     csrRowPtrC,
                                       int*                     nnzTotalDevHostPtr,
                                       pruneInfo_t              info,
                                       void*                    pBuffer)

cusparseStatus_t
cusparseDpruneDense2csrNnzByPercentage(cusparseHandle_t         handle,
                                       int                      m,
                                       int                      n,
                                       const double*            A,
                                       int                      lda,
                                       float                    percentage,
                                       const cusparseMatDescr_t descrC,
                                       int*                     csrRowPtrC,
                                       int*                     nnzTotalDevHostPtr,
                                       pruneInfo_t              info,
                                       void*                    pBuffer)
cusparseStatus_t
cusparseHpruneDense2csrByPercentage(cusparseHandle_t         handle,
                                    int                      m,
                                    int                      n,
                                    const __half*            A,
                                    int                      lda,
                                    float                    percentage,
                                    const cusparseMatDescr_t descrC,
                                    __half*                  csrValC,
                                    const int*               csrRowPtrC,
                                    int*                     csrColIndC,
                                    pruneInfo_t              info,
                                    void*                    pBuffer)

cusparseStatus_t
cusparseSpruneDense2csrByPercentage(cusparseHandle_t         handle,
                                    int                      m,
                                    int                      n,
                                    const float*             A,
                                    int                      lda,
                                    float                    percentage,
                                    const cusparseMatDescr_t descrC,
                                    float*                   csrValC,
                                    const int*               csrRowPtrC,
                                    int*                     csrColIndC,
                                    pruneInfo_t              info,
                                    void*                    pBuffer)

cusparseStatus_t
cusparseDpruneDense2csrByPercentage(cusparseHandle_t         handle,
                                    int                      m,
                                    int                      n,
                                    const double*            A,
                                    int                      lda,
                                    float                    percentage,
                                    const cusparseMatDescr_t descrC,
                                    double*                  csrValC,
                                    const int*               csrRowPtrC,
                                    int*                     csrColIndC,
                                    pruneInfo_t              info,
                                    void*                    pBuffer)

该函数通过百分比将稠密矩阵修剪为稀疏矩阵。

给定一个稠密矩阵 A 和一个非负值 percentage,该函数通过以下三个步骤计算稀疏矩阵 C

步骤1:按升序对A的绝对值进行排序。

\[\begin{split}\begin{matrix} {key\ :=\ sort(\ |A|\ )} \\ \end{matrix}\end{split}\]

步骤2:通过参数percentage选择阈值

\[\begin{split}\begin{matrix} {pos\ =\ ceil(m*n*(percentage/100))\ -\ 1} \\ {pos\ =\ min(pos,\ m*n-1)} \\ {pos\ =\ max(pos,\ 0)} \\ {threshold\ =\ key\lbrack pos\rbrack} \\ \end{matrix}\end{split}\]

步骤3:调用pruneDense2csr()函数并传入参数threshold

该实现采用两步法进行转换。首先,用户分配csrRowPtrCm+1个元素,并使用函数pruneDense2csrNnzByPercentage()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中收集nnzC(矩阵C的非零元素数量),并分配csrValCnnzC个元素和csrColIndCnnzC个整数。最后调用函数pruneDense2csrByPercentage()完成转换。

用户必须通过调用pruneDense2csrByPercentage_bufferSizeExt()获取pruneDense2csrByPercentage()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneDense2csrByPercentage()

备注1: percentage 的值必须不大于100。否则将返回 CUSPARSE_STATUS_INVALID_VALUE

备注2:A中的零值不会被忽略。所有条目都会被排序,包括零值。这与pruneCsr2csrByPercentage()的处理方式不同

该例程 cusparsepruneDense2csrNnzByPercentage() 具有以下特性:

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

例程 cusparsepruneDense2csrByPercentage() 具有以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

A

device

维度为 (lda, n) 的数组。

lda

device

A的主维度。必须至少为max(1, m)。

percentage

host

百分比 <=100 且百分比 >= 0

descrC

host

矩阵C的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

pBuffer

device

由用户分配的缓冲区;其大小由pruneDense2csrByPercentage_bufferSizeExt()返回。

输出

parameter

device or host

描述

nnzTotalDevHostPtr

device or host

矩阵C的非零元素总数。nnzTotalDevHostPtr可以指向设备内存或主机内存。

csrValC

device

<type> 矩阵 CnnzC 个非零元素数组。

csrRowsPtrC

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndC

device

nnzC列索引的整数数组,对应矩阵C

pBufferSizeInBytes

host

缓冲区的字节数。

有关返回状态的描述,请参见cusparseStatus_t

5.9.18. cusparseXpruneCsr2csrByPercentage() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseHpruneCsr2csrByPercentage_bufferSizeExt(cusparseHandle_t         handle,
                                                int                      m,
                                                int                      n,
                                                int                      nnzA,
                                                const cusparseMatDescr_t descrA,
                                                const __half*            csrValA,
                                                const int*               csrRowPtrA,
                                                const int*               csrColIndA,
                                                float                    percentage,
                                                const cusparseMatDescr_t descrC,
                                                const __half*            csrValC,
                                                const int*               csrRowPtrC,
                                                const int*               csrColIndC,
                                                pruneInfo_t              info,
                                                size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseSpruneCsr2csrByPercentage_bufferSizeExt(cusparseHandle_t         handle,
                                                int                      m,
                                                int                      n,
                                                int                      nnzA,
                                                const cusparseMatDescr_t descrA,
                                                const float*             csrValA,
                                                const int*               csrRowPtrA,
                                                const int*               csrColIndA,
                                                float                    percentage,
                                                const cusparseMatDescr_t descrC,
                                                const float*             csrValC,
                                                const int*               csrRowPtrC,
                                                const int*               csrColIndC,
                                                pruneInfo_t              info,
                                                size_t*                  pBufferSizeInBytes)

cusparseStatus_t
cusparseDpruneCsr2csrByPercentage_bufferSizeExt(cusparseHandle_t         handle,
                                                int                      m,
                                                int                      n,
                                                int                      nnzA,
                                                const cusparseMatDescr_t descrA,
                                                const double*            csrValA,
                                                const int*               csrRowPtrA,
                                                const int*               csrColIndA,
                                                float                    percentage,
                                                const cusparseMatDescr_t descrC,
                                                const double*            csrValC,
                                                const int*               csrRowPtrC,
                                                const int*               csrColIndC,
                                                pruneInfo_t              info,
                                                size_t*                  pBufferSizeInBytes)
cusparseStatus_t
cusparseHpruneCsr2csrNnzByPercentage(cusparseHandle_t        handle,
                                    int                      m,
                                    int                      n,
                                    int                      nnzA,
                                    const cusparseMatDescr_t descrA,
                                    const __half*            csrValA,
                                    const int*               csrRowPtrA,
                                    const int*               csrColIndA,
                                    float                    percentage,
                                    const cusparseMatDescr_t descrC,
                                    int*                     csrRowPtrC,
                                    int*                     nnzTotalDevHostPtr,
                                    pruneInfo_t              info,
                                    void*                    pBuffer)

cusparseStatus_t
cusparseSpruneCsr2csrNnzByPercentage(cusparseHandle_t        handle,
                                    int                      m,
                                    int                      n,
                                    int                      nnzA,
                                    const cusparseMatDescr_t descrA,
                                    const float*             csrValA,
                                    const int*               csrRowPtrA,
                                    const int*               csrColIndA,
                                    float                    percentage,
                                    const cusparseMatDescr_t descrC,
                                    int*                     csrRowPtrC,
                                    int*                     nnzTotalDevHostPtr,
                                    pruneInfo_t              info,
                                    void*                    pBuffer)

cusparseStatus_t
cusparseDpruneCsr2csrNnzByPercentage(cusparseHandle_t        handle,
                                    int                      m,
                                    int                      n,
                                    int                      nnzA,
                                    const cusparseMatDescr_t descrA,
                                    const double*            csrValA,
                                    const int*               csrRowPtrA,
                                    const int*               csrColIndA,
                                    float                    percentage,
                                    const cusparseMatDescr_t descrC,
                                    int*                     csrRowPtrC,
                                    int*                     nnzTotalDevHostPtr,
                                    pruneInfo_t              info,
                                    void*                    pBuffer)
cusparseStatus_t
cusparseHpruneCsr2csrByPercentage(cusparseHandle_t         handle,
                                  int                      m,
                                  int                      n,
                                  int                      nnzA,
                                  const cusparseMatDescr_t descrA,
                                  const __half*            csrValA,
                                  const int*               csrRowPtrA,
                                  const int*               csrColIndA,
                                  float                    percentage,
                                  const cusparseMatDescr_t descrC,
                                  __half*                  csrValC,
                                  const int*               csrRowPtrC,
                                  int*                     csrColIndC,
                                  pruneInfo_t              info,
                                  void*                    pBuffer)

cusparseStatus_t
cusparseSpruneCsr2csrByPercentage(cusparseHandle_t         handle,
                                  int                      m,
                                  int                      n,
                                  int                      nnzA,
                                  const cusparseMatDescr_t descrA,
                                  const float*             csrValA,
                                  const int*               csrRowPtrA,
                                  const int*               csrColIndA,
                                  float                    percentage,
                                  const cusparseMatDescr_t descrC,
                                  float*                   csrValC,
                                  const int*               csrRowPtrC,
                                  int*                     csrColIndC,
                                  pruneInfo_t              info,
                                  void*                    pBuffer)

cusparseStatus_t
cusparseDpruneCsr2csrByPercentage(cusparseHandle_t         handle,
                                  int                      m,
                                  int                      n,
                                  int                      nnzA,
                                  const cusparseMatDescr_t descrA,
                                  const double*            csrValA,
                                  const int*               csrRowPtrA,
                                  const int*               csrColIndA,
                                  float                    percentage,
                                  const cusparseMatDescr_t descrC,
                                  double*                  csrValC,
                                  const int*               csrRowPtrC,
                                  int*                     csrColIndC,
                                  pruneInfo_t              info,
                                  void*                    pBuffer)

该函数通过百分比将稀疏矩阵修剪为稀疏矩阵。

给定一个稀疏矩阵 A 和一个非负值 percentage,该函数通过以下三个步骤计算稀疏矩阵 C

步骤1:按升序对A的绝对值进行排序:

\[\begin{split}\begin{matrix} {key\ :=\ sort(\ \|csrValA\|\ )} \\ \end{matrix}\end{split}\]

步骤2:通过参数percentage选择阈值:

\[\begin{split}\begin{matrix} {pos\ =\ ceil(nnzA*(percentage/100))\ -\ 1} \\ {pos\ =\ min(pos,\ nnzA-1)} \\ {pos\ =\ max(pos,\ 0)} \\ {threshold\ =\ key\lbrack pos\rbrack} \\ \end{matrix}\end{split}\]

步骤3:调用pruneCsr2csr()并传入参数threshold

该实现采用两步法进行转换。首先,用户分配csrRowPtrCm+1个元素,并使用函数pruneCsr2csrNnzByPercentage()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中收集nnzC(矩阵C的非零元素数量),并分配csrValCnnzC个元素和csrColIndCnnzC个整数。最后调用函数pruneCsr2csrByPercentage()完成转换。

用户必须通过调用pruneCsr2csrByPercentage_bufferSizeExt()获取pruneCsr2csrByPercentage()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneCsr2csrByPercentage()

备注1: percentage的值不得超过100。否则将返回CUSPARSE_STATUS_INVALID_VALUE

例程 cusparsepruneCsr2csrNnzByPercentage() 具有以下特性:

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

例程 cusparsepruneCsr2csrByPercentage() 具有以下属性:

  • 该例程不需要额外的存储空间。

  • 该例程支持异步执行。

  • 该例程支持CUDA图捕获。

输入

parameter

device or host

描述

handle

host

cuSPARSE库上下文的句柄。

m

host

矩阵 A 的行数。

n

host

矩阵 A 的列数。

nnzA

host

矩阵 A 的非零元素数量。

描述A

host

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

device

<type> 矩阵 AnnzA 个非零元素数组。

csrRowsPtrA

device

包含每行起始位置及最后一行末尾加1的m+1个元素的整数数组。

csrColIndA

device

nnzA 的整数数组,表示 A 的列索引。

percentage

host

百分比 <=100 且百分比 >= 0

descrC

host

矩阵C的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL,同时支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

pBuffer

device

由用户分配的缓冲区;大小由pruneCsr2csrByPercentage_bufferSizeExt()返回。

输出

parameter

device or host

描述

nnzTotalDevHostPtr

device or host

矩阵C的非零元素总数。nnzTotalDevHostPtr可以指向设备内存或主机内存

csrValC

device

<type> 矩阵 CnnzC 个非零元素数组。

csrRowsPtrC

device

包含每行起始位置及最后一行末尾加1的m+1元素整数数组

csrColIndC

device

nnzC 的整型数组,表示 C 的列索引

pBufferSizeInBytes

host

缓冲区的字节数

有关返回状态的描述,请参见cusparseStatus_t

5.9.19. cusparsennz_compress() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseSnnz_compress(cusparseHandle_t         handle,
                      int                      m,
                      const cusparseMatDescr_t descr,
                      const float*             csrValA,
                      const int*               csrRowPtrA,
                      int*                     nnzPerRow,
                      int*                     nnzC,
                      float                    tol)

cusparseStatus_t
cusparseDnnz_compress(cusparseHandle_t         handle,
                      int                      m,
                      const cusparseMatDescr_t descr,
                      const double*            csrValA,
                      const int*               csrRowPtrA,
                      int*                     nnzPerRow,
                      int*                     nnzC,
                      double                   tol)

cusparseStatus_t
cusparseCnnz_compress(cusparseHandle_t         handle,
                      int                      m,
                      const cusparseMatDescr_t descr,
                      const cuComplex*         csrValA,
                      const int*               csrRowPtrA,
                      int*                     nnzPerRow,
                      int*                     nnzC,
                      cuComplex                tol)

cusparseStatus_t
cusparseZnnz_compress(cusparseHandle_t         handle,
                      int                      m,
                      const cusparseMatDescr_t descr,
                      const cuDoubleComplex*   csrValA,
                      const int*               csrRowPtrA,
                      int*                     nnzPerRow,
                      int*                     nnzC,
                      cuDoubleComplex          tol)

此函数是将数据从csr格式转换为压缩csr格式的第一步。

给定一个稀疏矩阵A和一个非负阈值,该函数返回稀疏矩阵C的nnzPerRow(每行的非零列数)和nnzC(非零元素总数),其中矩阵C的定义如下:

\[\begin{split}\begin{matrix} {{C(i,j)} = {A(i,j)}} & \text{当\ |A(i,j)|\ 大于\ 阈值时} \\ \end{matrix}\end{split}\]

对于cuComplex和cuDoubleComplex情况的一个关键假设是,这个容差值以实部形式给出。例如tol = 1e-8 + 0*i,我们提取的是cureal,也就是这个结构体的x分量。

  • 此函数需要临时额外存储空间,该空间在内部分配。

  • 如果流序内存分配器可用,该例程支持异步执行。

  • 如果流序内存分配器可用,该例程支持CUDA图捕获。

输入

handle

cuSPARSE库上下文的句柄。

m

矩阵 A 的行数。

描述A

矩阵A的描述符。支持的矩阵类型为CUSPARSE_MATRIX_TYPE_GENERAL。同时,支持的索引基数为CUSPARSE_INDEX_BASE_ZEROCUSPARSE_INDEX_BASE_ONE

csrValA

CSR非压缩值数组

csrRowPtrA

对应的输入未压缩行指针。

tol

非负容差,用于判断一个数是否小于或等于该值。

输出

nnzPerRow

该数组包含每行中绝对值大于tol的元素数量。

nnzC

绝对值大于tol的元素总数的host/device指针。

有关返回状态的描述,请参见cusparseStatus_t


6. cuSPARSE通用API

cuSPARSE通用API允许以灵活的方式计算最常见的稀疏线性代数运算,例如稀疏矩阵-向量乘法(SpMV)和稀疏矩阵-矩阵乘法(SpMM)。新API具有以下功能和特点:

  • 设置矩阵数据布局、批次数以及存储格式(例如CSR、COO等)。

  • 设置输入/输出/计算数据类型。这也支持混合数据类型的计算。

  • 设置稀疏向量/矩阵索引的类型(例如32位、64位)。

  • 选择用于计算的算法。

  • 为内部操作确保外部设备内存。

  • 对输入矩阵和向量提供全面的数据一致性检查。包括验证尺寸、数据类型、布局、允许的操作等。

  • 为向量和矩阵输入提供常量描述符,以支持常量安全接口,并确保API不会修改其输入。

6.1. 通用类型参考

本节描述了cuSPARSE通用类型的引用。

6.1.1. cusparseFormat_t

此类型表示稀疏矩阵的格式。 有关其描述,请参阅cuSPARSE存储格式

含义

CUSPARSE_FORMAT_COO

矩阵以坐标(COO)格式存储,采用数组结构(SoA)布局

CUSPARSE_FORMAT_CSR

矩阵以压缩稀疏行(CSR)格式存储

CUSPARSE_FORMAT_CSC

该矩阵以压缩稀疏列(CSC)格式存储

CUSPARSE_FORMAT_BLOCKED_ELL

矩阵以分块Ellpack(Blocked-ELL)格式存储

CUSPARSE_FORMAT_SLICED_ELL

矩阵以切片椭圆压缩(Sliced-ELL)格式存储

CUSPARSE_FORMAT_BSR

矩阵以块稀疏行(BSR)格式存储


6.1.2. cusparseOrder_t

该类型表示稠密矩阵的内存布局。

含义

CUSPARSE_ORDER_ROW

矩阵以行优先方式存储

CUSPARSE_ORDER_COL

矩阵以列优先方式存储


6.1.3. cusparseIndexType_t

此类型表示用于表示稀疏矩阵索引的索引类型。

含义

CUSPARSE_INDEX_32I

32位有符号整数 [0, 2^31 - 1]

CUSPARSE_INDEX_64I

64位有符号整数 [0, 2^63 - 1]



6.2. 密集向量API

本节介绍了用于稠密向量描述符的cuSPARSE辅助函数。

有关存储格式的详细描述,请参阅Dense Vector Format部分。


6.2.1. cusparseCreateDnVec()

cusparseStatus_t
cusparseCreateDnVec(cusparseDnVecDescr_t* dnVecDescr,
                    int64_t               size,
                    void*                 values,
                    cudaDataType          valueType)

cusparseStatus_t
cusparseCreateConstDnVec(cusparseConstDnVecDescr_t* dnVecDescr,
                         int64_t                    size,
                         const void*                values,
                         cudaDataType               valueType)

该函数用于初始化稠密向量描述符 dnVecDescr

参数

内存

输入/输出

含义

dnVecDescr

主机

输出

密集向量描述符

size

主机

IN

稠密向量的大小

values

设备

IN

稠密向量的值。包含size个元素的数组

valueType

主机

IN

指定values数据类型的枚举器

cusparseCreateDnVec() 有以下限制:

  • values 必须按照 valueType 指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参考cusparseStatus_t


6.2.2. cusparseDestroyDnVec()

cusparseStatus_t
cusparseDestroyDnVec(cusparseConstDnVecDescr_t dnVecDescr) // non-const descriptor supported

该函数释放为主机内存分配的稠密向量描述符dnVecDescr

参数

内存

输入/输出

含义

dnVecDescr

主机

IN

密集向量描述符

有关返回状态的描述,请参考cusparseStatus_t


6.2.3. cusparseDnVecGet()

cusparseStatus_t
cusparseDnVecGet(cusparseDnVecDescr_t dnVecDescr,
                 int64_t*             size,
                 void**               values,
                 cudaDataType*        valueType)

cusparseStatus_t
cusparseConstDnVecGet(cusparseConstDnVecDescr_t dnVecDescr,
                      int64_t*                  size,
                      const void**              values,
                      cudaDataType*             valueType)

该函数返回稠密向量描述符dnVecDescr的字段。

参数

内存

输入/输出

含义

dnVecDescr

主机

IN

密集向量描述符

size

主机

输出

稠密向量的大小

values

设备

输出

稠密向量的值。包含nnz个元素的数组

valueType

主机

输出

指定values数据类型的枚举器

有关返回状态的描述,请参考cusparseStatus_t


6.2.4. cusparseDnVecGetValues()

cusparseStatus_t
cusparseDnVecGetValues(cusparseDnVecDescr_t dnVecDescr,
                       void**               values)

cusparseStatus_t
cusparseConstDnVecGetValues(cusparseConstDnVecDescr_t dnVecDescr,
                            const void**              values)

该函数返回稠密向量描述符dnVecDescrvalues字段。

参数

内存

输入/输出

含义

dnVecDescr

主机

IN

稠密向量描述符

values

设备

输出

稠密向量的值

有关返回状态的描述,请参考cusparseStatus_t


6.2.5. cusparseDnVecSetValues()

cusparseStatus_t
cusparseDnVecSetValues(cusparseDnVecDescr_t dnVecDescr,
                       void*                values)

此函数设置稠密向量描述符dnVecDescrvalues字段。

参数

内存

输入/输出

含义

dnVecDescr

主机

IN

密集向量描述符

values

设备

IN

稠密向量的值。包含size个元素的数组

cusparseDnVecSetValues() 有以下限制条件:

  • values 必须按照 dnVecDescr 中指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参考cusparseStatus_t



6.3. 稀疏向量API

本节介绍用于稀疏向量描述符的cuSPARSE辅助函数。

有关存储格式的详细描述,请参阅稀疏向量格式部分。

6.3.1. cusparseCreateSpVec()

cusparseStatus_t
cusparseCreateSpVec(cusparseSpVecDescr_t* spVecDescr,
                    int64_t               size,
                    int64_t               nnz,
                    void*                 indices,
                    void*                 values,
                    cusparseIndexType_t   idxType,
                    cusparseIndexBase_t   idxBase,
                    cudaDataType          valueType)

cusparseStatus_t
cusparseCreateConstSpVec(cusparseConstSpVecDescr_t* spVecDescr,
                         int64_t                    size,
                         int64_t                    nnz,
                         const void*                indices,
                         const void*                values,
                         cusparseIndexType_t        idxType,
                         cusparseIndexBase_t        idxBase,
                         cudaDataType               valueType)

该函数用于初始化稀疏矩阵描述符 spVecDescr

参数

内存

输入/输出

含义

spVecDescr

主机

输出

稀疏向量描述符

size

主机

IN

稀疏向量的大小

nnz

主机

IN

稀疏向量中非零元素的数量

indices

设备

IN

稀疏向量的索引。包含nnz个元素的数组

values

设备

IN

稀疏向量的值。包含nnz个元素的数组

idxType

主机

IN

指定indices数据类型的枚举器

idxBase

主机

IN

指定indices索引基数的枚举器

valueType

主机

IN

指定values数据类型的枚举器

cusparseCreateSpVec() 有以下限制条件:

  • indicesvalues 必须分别与 idxTypevalueType 指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.3.2. cusparseDestroySpVec()

cusparseStatus_t
cusparseDestroySpVec(cusparseConstSpVecDescr_t spVecDescr) // non-const descriptor supported

该函数释放为主机内存分配的稀疏向量描述符spVecDescr

参数

内存

输入/输出

含义

spVecDescr

主机

IN

稀疏向量描述符

有关返回状态的描述,请参见cusparseStatus_t


6.3.3. cusparseSpVecGet()

cusparseStatus_t
cusparseSpVecGet(cusparseSpVecDescr_t spVecDescr,
                 int64_t*             size,
                 int64_t*             nnz,
                 void**               indices,
                 void**               values,
                 cusparseIndexType_t* idxType,
                 cusparseIndexBase_t* idxBase,
                 cudaDataType*        valueType)

cusparseStatus_t
cusparseConstSpVecGet(cusparseConstSpVecDescr_t spVecDescr,
                      int64_t*                  size,
                      int64_t*                  nnz,
                      const void**              indices,
                      const void**              values,
                      cusparseIndexType_t*      idxType,
                      cusparseIndexBase_t*      idxBase,
                      cudaDataType*             valueType)

该函数返回稀疏向量描述符spVecDescr的字段。

参数

内存

输入/输出

含义

spVecDescr

主机

IN

稀疏向量描述符

size

主机

输出

稀疏向量的大小

nnz

主机

输出

稀疏向量的非零元素数量

indices

设备

输出

稀疏向量的索引。包含nnz个元素的数组

values

设备

输出

稀疏向量的值。包含nnz个元素的数组

idxType

主机

输出

指定indices数据类型的枚举器

idxBase

主机

输出

指定indices索引基数的枚举器

valueType

主机

输出

指定values数据类型的枚举器

有关返回状态的描述,请参见cusparseStatus_t


6.3.4. cusparseSpVecGetIndexBase()

cusparseStatus_t
cusparseSpVecGetIndexBase(cusparseConstSpVecDescr_t spVecDescr, // non-const descriptor supported
                          cusparseIndexBase_t*      idxBase)

该函数返回稀疏向量描述符spVecDescr中的idxBase字段。

参数

内存

输入/输出

含义

spVecDescr

主机

IN

稀疏向量描述符

idxBase

主机

输出

指定indices索引基数的枚举器

有关返回状态的描述,请参见cusparseStatus_t


6.3.5. cusparseSpVecGetValues()

cusparseStatus_t
cusparseSpVecGetValues(cusparseSpVecDescr_t spVecDescr,
                       void**               values)

cusparseStatus_t
cusparseConstSpVecGetValues(cusparseConstSpVecDescr_t spVecDescr,
                            const void**              values)

该函数返回稀疏向量描述符spVecDescrvalues字段。

参数

内存

输入/输出

含义

spVecDescr

主机

IN

稀疏向量描述符

values

设备

输出

稀疏向量的值。包含nnz个元素的数组

有关返回状态的描述,请参见cusparseStatus_t


6.3.6. cusparseSpVecSetValues()

cusparseStatus_t
cusparseSpVecSetValues(cusparseSpVecDescr_t spVecDescr,
                       void*                values)

此函数用于设置稀疏向量描述符spVecDescr中的values字段。

参数

内存

输入/输出

含义

spVecDescr

主机

IN

稀疏向量描述符

values

设备

IN

稀疏向量的值。包含nnz个元素的数组

cusparseDnVecSetValues() 有以下限制条件:

  • values 必须按照 spVecDescr 中指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t



6.4. 密集矩阵API

本节介绍用于稠密矩阵描述符的cuSPARSE辅助函数。

有关存储格式的详细描述,请参阅Dense Matrix Format部分。

6.4.1. cusparseCreateDnMat()

cusparseStatus_t
cusparseCreateDnMat(cusparseDnMatDescr_t* dnMatDescr,
                    int64_t               rows,
                    int64_t               cols,
                    int64_t               ld,
                    void*                 values,
                    cudaDataType          valueType,
                    cusparseOrder_t       order)

cusparseStatus_t
cusparseCreateConstDnMat(cusparseConstDnMatDescr_t* dnMatDescr,
                         int64_t                    rows,
                         int64_t                    cols,
                         int64_t                    ld,
                         const void*                values,
                         cudaDataType               valueType,
                         cusparseOrder_t            order)

该函数用于初始化稠密矩阵描述符 dnMatDescr

参数

内存

输入/输出

含义

dnMatDescr

主机

输出

稠密矩阵描述符

rows

主机

IN

稠密矩阵的行数

cols

主机

IN

稠密矩阵的列数

ld

主机

IN

稠密矩阵的主维度

values

设备

IN

稠密矩阵的值。包含size个元素的数组

valueType

主机

IN

指定values数据类型的枚举器

order

主机

IN

指定稠密矩阵内存布局的枚举器

cusparseCreateDnMat() 有以下限制条件:

  • values 必须按照 valueType 指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参考cusparseStatus_t


6.4.2. cusparseDestroyDnMat()

cusparseStatus_t
cusparseDestroyDnMat(cusparseConstDnMatDescr_t dnMatDescr) // non-const descriptor supported

该函数释放为主机内存分配的稠密矩阵描述符dnMatDescr

参数

内存

输入/输出

含义

dnMatDescr

主机

IN

稠密矩阵描述符

有关返回状态的描述,请参考cusparseStatus_t


6.4.3. cusparseDnMatGet()

cusparseStatus_t
cusparseDnMatGet(cusparseDnMatDescr_t dnMatDescr,
                 int64_t*             rows,
                 int64_t*             cols,
                 int64_t*             ld,
                 void**               values,
                 cudaDataType*        type,
                 cusparseOrder_t*     order)

cusparseStatus_t
cusparseConstDnMatGet(cusparseConstDnMatDescr_t dnMatDescr,
                      int64_t*             rows,
                      int64_t*             cols,
                      int64_t*             ld,
                      const void**         values,
                      cudaDataType*        type,
                      cusparseOrder_t*     order)

该函数返回稠密矩阵描述符dnMatDescr的字段。

参数

内存

输入/输出

含义

dnMatDescr

主机

IN

稠密矩阵描述符

rows

主机

输出

稠密矩阵的行数

cols

主机

输出

稠密矩阵的列数

ld

主机

输出

稠密矩阵的主维度

values

设备

输出

稠密矩阵的值。包含ld * cols个元素的数组

valueType

主机

输出

指定values数据类型的枚举器

order

主机

输出

指定稠密矩阵内存布局的枚举器

有关返回状态的描述,请参考cusparseStatus_t


6.4.4. cusparseDnMatGetValues()

cusparseStatus_t
cusparseDnMatGetValues(cusparseDnMatDescr_t dnMatDescr,
                       void**               values)

cusparseStatus_t
cusparseConstDnMatGetValues(cusparseConstDnMatDescr_t dnMatDescr,
                            const void**              values)

该函数返回稠密矩阵描述符dnMatDescrvalues字段。

参数

内存

输入/输出

含义

dnMatDescr

主机

IN

稠密矩阵描述符

values

设备

输出

稠密矩阵的值。包含ld * cols个元素的数组

有关返回状态的描述,请参考cusparseStatus_t


6.4.5. cusparseDnMatSetValues()

cusparseStatus_t
cusparseDnMatSetValues(cusparseDnMatDescr_t dnMatDescr,
                       void*                values)

此函数用于设置稠密矩阵描述符dnMatDescr中的values字段。

参数

内存

输入/输出

含义

dnMatDescr

主机

IN

稠密矩阵描述符

values

设备

IN

稠密矩阵的值。包含ld * cols个元素的数组

cusparseDnMatSetValues() 有以下限制条件:

  • values 必须按照 dnMatDescr 中指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参考cusparseStatus_t


6.4.6. cusparseDnMatGetStridedBatch()

cusparseStatus_t
cusparseDnMatGetStridedBatch(cusparseConstDnMatDescr_t dnMatDescr, // non-const descriptor supported
                             int*                      batchCount,
                             int64_t*                  batchStride)

该函数返回稠密矩阵描述符dnMatDescr的批次数和批次步长。

参数

内存

输入/输出

含义

dnMatDescr

主机

IN

稠密矩阵描述符

batchCount

主机

输出

稠密矩阵的批次数

batchStride

主机

输出

矩阵与批次中下一个矩阵之间的地址偏移量

有关返回状态的描述,请参考cusparseStatus_t


6.4.7. cusparseDnMatSetStridedBatch()

cusparseStatus_t
cusparseDnMatSetStridedBatch(cusparseDnMatDescr_t dnMatDescr,
                             int                  batchCount,
                             int64_t              batchStride)

该函数用于设置稠密矩阵描述符dnMatDescr的批次数和批次步长。

参数

内存

输入/输出

含义

dnMatDescr

主机

IN

稠密矩阵描述符

batchCount

主机

IN

密集矩阵的批次数

batchStride

主机

IN

矩阵与批次中下一个矩阵之间的地址偏移量。如果矩阵使用列优先布局,则batchStride ld * cols;否则batchStride ld * rows

有关返回状态的描述,请参考cusparseStatus_t

6.5. 稀疏矩阵API

本节介绍用于稀疏矩阵描述符的cuSPARSE辅助函数。

有关存储格式的详细描述,请参阅COOCSRCSCSELLBSRBlocked-Ell章节。

6.5.1. 坐标格式 (COO)

6.5.1.1. cusparseCreateCoo()

cusparseStatus_t
cusparseCreateCoo(cusparseSpMatDescr_t* spMatDescr,
                  int64_t               rows,
                  int64_t               cols,
                  int64_t               nnz,
                  void*                 cooRowInd,
                  void*                 cooColInd,
                  void*                 cooValues,
                  cusparseIndexType_t   cooIdxType,
                  cusparseIndexBase_t   idxBase,
                  cudaDataType          valueType)

cusparseStatus_t
cusparseCreateConstCoo(cusparseConstSpMatDescr_t* spMatDescr,
                       int64_t                    rows,
                       int64_t                    cols,
                       int64_t                    nnz,
                       const void*                cooRowInd,
                       const void*                cooColInd,
                       const void*                cooValues,
                       cusparseIndexType_t        cooIdxType,
                       cusparseIndexBase_t        idxBase,
                       cudaDataType               valueType)

此函数以COO格式(结构数组布局)初始化稀疏矩阵描述符spMatDescr

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

rows

主机

IN

稀疏矩阵的行数

cols

主机

IN

稀疏矩阵的列数

nnz

主机

IN

稀疏矩阵的非零元素数量

cooRowInd

设备

IN

稀疏矩阵的行索引。包含nnz个元素的数组

cooColInd

设备

IN

稀疏矩阵的列索引。包含nnz个元素的数组

cooValues

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

cooIdxType

主机

IN

cooRowIndcooColInd 的数据类型

idxBase

主机

IN

cooRowIndcooColInd 的索引基数

valueType

主机

IN

cooValues的数据类型

cusparseCreateCoo() 有以下限制条件:

  • cooRowInd, cooColIndcooValues必须按照cooIdxType, cooIdxTypevalueType指定的数据类型大小对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.1.2. cusparseCooGet()

cusparseStatus_t
cusparseCooGet(cusparseSpMatDescr_t spMatDescr,
               int64_t*             rows,
               int64_t*             cols,
               int64_t*             nnz,
               void**               cooRowInd,
               void**               cooColInd,
               void**               cooValues,
               cusparseIndexType_t* idxType,
               cusparseIndexBase_t* idxBase,
               cudaDataType*        valueType)

cusparseStatus_t
cusparseConstCooGet(cusparseConstSpMatDescr_t spMatDescr,
                    int64_t*                  rows,
                    int64_t*                  cols,
                    int64_t*                  nnz,
                    const void**              cooRowInd,
                    const void**              cooColInd,
                    const void**              cooValues,
                    cusparseIndexType_t*      idxType,
                    cusparseIndexBase_t*      idxBase,
                    cudaDataType*             valueType)

该函数返回以COO格式(结构数组布局)存储的稀疏矩阵描述符spMatDescr的字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

rows

主机

输出

稀疏矩阵的行数

cols

主机

输出

稀疏矩阵的列数

nnz

主机

输出

稀疏矩阵的非零元素数量

cooRowInd

设备

输出

稀疏矩阵的行索引。包含nnz个元素的数组

cooColInd

设备

输出

稀疏矩阵的列索引。包含nnz个元素的数组

cooValues

设备

输出

稀疏矩阵的值。包含nnz个元素的数组

cooIdxType

主机

输出

cooRowIndcooColInd 的数据类型

idxBase

主机

输出

cooRowIndcooColInd 的索引基数

valueType

主机

输出

cooValues的数据类型

有关返回状态的描述,请参见cusparseStatus_t


6.5.1.3. cusparseCooSetPointers()

cusparseStatus_t
cusparseCooSetPointers(cusparseSpMatDescr_t spMatDescr,
                       void*                cooRows,
                       void*                cooColumns,
                       void*                cooValues)

此函数用于设置稀疏矩阵描述符spMatDescr的指针。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

cooRows

设备

IN

稀疏矩阵的行索引。包含nnz个元素的数组

cooColumns

设备

IN

稀疏矩阵的列索引。包含nnz个元素的数组

cooValues

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

cusparseCooSetPointers() 有以下限制条件:

  • cooRows, cooColumnscooValues 必须按照 spMatDescr 中指定的对应数据类型大小进行对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.1.4. cusparseCooSetStridedBatch()

cusparseStatus_t
cusparseCooSetStridedBatch(cusparseSpMatDescr_t spMatDescr,
                           int                  batchCount,
                           int64_t              batchStride)

此函数用于设置稀疏矩阵描述符spMatDescr中的batchCountbatchStride字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

batchCount

主机

IN

稀疏矩阵的批次数

batchStride

主机

IN

连续批次之间的地址偏移

有关返回状态的描述,请参见cusparseStatus_t


6.5.2. 压缩稀疏行(CSR)格式

6.5.2.1. cusparseCreateCsr()

cusparseStatus_t
cusparseCreateCsr(cusparseSpMatDescr_t* spMatDescr,
                  int64_t               rows,
                  int64_t               cols,
                  int64_t               nnz,
                  void*                 csrRowOffsets,
                  void*                 csrColInd,
                  void*                 csrValues,
                  cusparseIndexType_t   csrRowOffsetsType,
                  cusparseIndexType_t   csrColIndType,
                  cusparseIndexBase_t   idxBase,
                  cudaDataType          valueType)

cusparseStatus_t
cusparseCreateConstCsr(cusparseConstSpMatDescr_t* spMatDescr,
                       int64_t                    rows,
                       int64_t                    cols,
                       int64_t                    nnz,
                       const void*                csrRowOffsets,
                       const void*                csrColInd,
                       const void*                csrValues,
                       cusparseIndexType_t        csrRowOffsetsType,
                       cusparseIndexType_t        csrColIndType,
                       cusparseIndexBase_t        idxBase,
                       cudaDataType               valueType)

此函数以CSR格式初始化稀疏矩阵描述符spMatDescr

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

rows

主机

IN

稀疏矩阵的行数

cols

主机

IN

稀疏矩阵的列数

nnz

主机

IN

稀疏矩阵的非零元素数量

csrRowOffsets

设备

IN

稀疏矩阵的行偏移量。包含rows + 1个元素的数组

csrColInd

设备

IN

稀疏矩阵的列索引。包含nnz个元素的数组

csrValues

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

csrRowOffsetsType

主机

IN

csrRowOffsets的数据类型

csrColIndType

主机

IN

csrColInd的数据类型

idxBase

主机

IN

csrRowOffsetscsrColInd 的索引基准

valueType

主机

IN

csrValues的数据类型

cusparseCreateCsr() 有以下限制条件:

  • csrRowOffsetscsrColIndcsrValues必须分别按照csrRowOffsetsTypecsrColIndTypevalueType指定的数据类型大小对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.2.2. cusparseCsrGet()

cusparseStatus_t
cusparseCsrGet(cusparseSpMatDescr_t spMatDescr,
               int64_t*             rows,
               int64_t*             cols,
               int64_t*             nnz,
               void**               csrRowOffsets,
               void**               csrColInd,
               void**               csrValues,
               cusparseIndexType_t* csrRowOffsetsType,
               cusparseIndexType_t* csrColIndType,
               cusparseIndexBase_t* idxBase,
               cudaDataType*        valueType)

cusparseStatus_t
cusparseConstCsrGet(cusparseConstSpMatDescr_t spMatDescr,
                    int64_t*                  rows,
                    int64_t*                  cols,
                    int64_t*                  nnz,
                    const void**              csrRowOffsets,
                    const void**              csrColInd,
                    const void**              csrValues,
                    cusparseIndexType_t*      csrRowOffsetsType,
                    cusparseIndexType_t*      csrColIndType,
                    cusparseIndexBase_t*      idxBase,
                    cudaDataType*             valueType)

该函数返回以CSR格式存储的稀疏矩阵描述符spMatDescr的字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

rows

主机

输出

稀疏矩阵的行数

cols

主机

输出

稀疏矩阵的列数

nnz

主机

输出

稀疏矩阵的非零元素数量

csrRowOffsets

设备

输出

稀疏矩阵的行偏移量。包含rows + 1个元素的数组

csrColInd

设备

输出

稀疏矩阵的列索引。包含nnz个元素的数组

csrValues

设备

输出

稀疏矩阵的值。包含nnz个元素的数组

csrRowOffsetsType

主机

输出

csrRowOffsets的数据类型

csrColIndType

主机

输出

csrColInd的数据类型

idxBase

主机

输出

csrRowOffsetscsrColInd 的索引基准

valueType

主机

输出

csrValues的数据类型

有关返回状态的描述,请参见cusparseStatus_t


6.5.2.3. cusparseCsrSetPointers()

cusparseStatus_t
cusparseCsrSetPointers(cusparseSpMatDescr_t spMatDescr,
                       void*                csrRowOffsets,
                       void*                csrColInd,
                       void*                csrValues)

此函数用于设置稀疏矩阵描述符spMatDescr的指针。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

csrRowOffsets

设备

IN

稀疏矩阵的行偏移量。包含rows + 1个元素的数组

csrColInd

设备

IN

稀疏矩阵的列索引。包含nnz个元素的数组

csrValues

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

cusparseCsrSetPointers() 有以下限制条件:

  • csrRowOffsetscsrColIndcsrValues必须按照spMatDescr中指定的对应数据类型大小进行对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.2.4. cusparseCsrSetStridedBatch()

cusparseStatus_t
cusparseCsrSetStridedBatch(cusparseSpMatDescr_t spMatDescr,
                           int                  batchCount,
                           int64_t              offsetsBatchStride,
                           int64_t              columnsValuesBatchStride)

此函数用于设置稀疏矩阵描述符spMatDescr中的batchCountbatchStride字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

batchCount

主机

IN

稀疏矩阵的批次数

offsetsBatchStride

主机

IN

行偏移数组中连续批次之间的地址偏移量

columnsValuesBatchStride

主机

IN

列数组与值数组之间连续批次的地址偏移量

有关返回状态的描述,请参见cusparseStatus_t


6.5.3. 压缩稀疏列(CSC)

6.5.3.1. cusparseCreateCsc()

cusparseStatus_t
cusparseCreateCsc(cusparseSpMatDescr_t* spMatDescr,
                  int64_t               rows,
                  int64_t               cols,
                  int64_t               nnz,
                  void*                 cscColOffsets,
                  void*                 cscRowInd,
                  void*                 cscValues,
                  cusparseIndexType_t   cscColOffsetsType,
                  cusparseIndexType_t   cscRowIndType,
                  cusparseIndexBase_t   idxBase,
                  cudaDataType          valueType)

cusparseStatus_t
cusparseCreateConstCsc(cusparseConstSpMatDescr_t* spMatDescr,
                       int64_t                    rows,
                       int64_t                    cols,
                       int64_t                    nnz,
                       const void*                cscColOffsets,
                       const void*                cscRowInd,
                       const void*                cscValues,
                       cusparseIndexType_t        cscColOffsetsType,
                       cusparseIndexType_t        cscRowIndType,
                       cusparseIndexBase_t        idxBase,
                       cudaDataType               valueType)

此函数以CSC格式初始化稀疏矩阵描述符spMatDescr

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

rows

主机

IN

稀疏矩阵的行数

cols

主机

IN

稀疏矩阵的列数

nnz

主机

IN

稀疏矩阵的非零元素数量

cscColOffsets

设备

IN

稀疏矩阵的列偏移量。包含cols + 1个元素的数组

cscRowInd

设备

IN

稀疏矩阵的行索引。包含nnz个元素的数组

cscValues

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

cscColOffsetsType

主机

IN

cscColOffsets的数据类型

cscRowIndType

主机

IN

cscRowInd的数据类型

idxBase

主机

IN

cscColOffsetscscRowInd 的索引基准

valueType

主机

IN

cscValues的数据类型

cusparseCreateCsc() 有以下限制条件:

  • cscColOffsetscscRowIndcscValues必须分别按照cscColOffsetsTypecscRowIndTypevalueType指定的数据类型大小对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.3.2. cusparseCscGet()

cusparseStatus_t
cusparseCscGet(cusparseSpMatDescr_t spMatDescr,
               int64_t*             rows,
               int64_t*             cols,
               int64_t*             nnz,
               void**               cscColOffsets,
               void**               cscRowInd,
               void**               cscValues,
               cusparseIndexType_t* cscColOffsetsType,
               cusparseIndexType_t* cscRowIndType,
               cusparseIndexBase_t* idxBase,
               cudaDataType*        valueType)

cusparseStatus_t
cusparseConstCscGet(cusparseConstSpMatDescr_t spMatDescr,
                    int64_t*                  rows,
                    int64_t*                  cols,
                    int64_t*                  nnz,
                    const void**              cscColOffsets,
                    const void**              cscRowInd,
                    const void**              cscValues,
                    cusparseIndexType_t*      cscColOffsetsType,
                    cusparseIndexType_t*      cscRowIndType,
                    cusparseIndexBase_t*      idxBase,
                    cudaDataType*             valueType)

该函数返回以CSC格式存储的稀疏矩阵描述符spMatDescr的字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

rows

主机

输出

稀疏矩阵的行数

cols

主机

输出

稀疏矩阵的列数

nnz

主机

输出

稀疏矩阵的非零元素数量

cscColOffsets

设备

输出

稀疏矩阵的列偏移量。包含cols + 1个元素的数组

cscRowInd

设备

输出

稀疏矩阵的行索引。包含nnz个元素的数组

cscValues

设备

输出

稀疏矩阵的值。包含nnz个元素的数组

cscColOffsetsType

主机

输出

cscColOffsets的数据类型

cscRowIndType

主机

输出

cscRowInd的数据类型

idxBase

主机

输出

cscColOffsetscscRowInd 的索引基准

valueType

主机

输出

cscValues的数据类型

有关返回状态的描述,请参见cusparseStatus_t


6.5.3.3. cusparseCscSetPointers()

cusparseStatus_t
cusparseCscSetPointers(cusparseSpMatDescr_t spMatDescr,
                       void*                cscColOffsets,
                       void*                cscRowInd,
                       void*                cscValues)

此函数用于设置稀疏矩阵描述符spMatDescr的指针。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

cscColOffsets

设备

IN

稀疏矩阵的列偏移量。包含cols + 1个元素的数组

cscRowInd

设备

IN

稀疏矩阵的行索引。包含nnz个元素的数组

cscValues

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

cusparseCscSetPointers() 有以下限制条件:

  • cscColOffsetscscRowIndcscValues必须按照spMatDescr中指定的对应数据类型大小进行对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.4. 分块椭圆压缩存储格式(Blocked-ELL)

6.5.4.1. cusparseCreateBlockedEll()

cusparseStatus_t
cusparseCreateBlockedEll(cusparseSpMatDescr_t* spMatDescr,
                         int64_t               rows,
                         int64_t               cols,
                         int64_t               ellBlockSize,
                         int64_t               ellCols,
                         void*                 ellColInd,
                         void*                 ellValue,
                         cusparseIndexType_t   ellIdxType,
                         cusparseIndexBase_t   idxBase,
                         cudaDataType          valueType)

cusparseStatus_t
cusparseCreateConstBlockedEll(cusparseConstSpMatDescr_t* spMatDescr,
                              int64_t                    rows,
                              int64_t                    cols,
                              int64_t                    ellBlockSize,
                              int64_t                    ellCols,
                              const void*                ellColInd,
                              const void*                ellValue,
                              cusparseIndexType_t        ellIdxType,
                              cusparseIndexBase_t        idxBase,
                              cudaDataType               valueType)

此函数为块状Ellpack (ELL)格式初始化稀疏矩阵描述符spMatDescr

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

rows

主机

IN

稀疏矩阵的行数

cols

主机

IN

稀疏矩阵的列数

ellBlockSize

主机

IN

ELL块的大小

ellCols

主机

IN

Blocked-Ellpack格式的实际列数(ellValue列)

ellColInd

设备

IN

Blocked-ELL列索引。包含[ellCols / ellBlockSize][rows / ellBlockSize]个元素的数组

ellValue

设备

IN

稀疏矩阵的值。包含rows * ellCols个元素的数组

ellIdxType

主机

IN

ellColInd的数据类型

idxBase

主机

IN

ellColInd的索引基数

valueType

主机

IN

ellValue的数据类型

Blocked-ELL列索引(ellColInd)的取值范围为[0, cols / ellBlockSize -1]。该数组可能包含-1值用于表示空块。

有关返回状态的描述,请参见cusparseStatus_t


6.5.4.2. cusparseBlockedEllGet()

cusparseStatus_t
cusparseBlockedEllGet(cusparseSpMatDescr_t spMatDescr,
                      int64_t*             rows,
                      int64_t*             cols,
                      int64_t*             ellBlockSize,
                      int64_t*             ellCols,
                      void**               ellColInd,
                      void**               ellValue,
                      cusparseIndexType_t* ellIdxType,
                      cusparseIndexBase_t* idxBase,
                      cudaDataType*        valueType)

cusparseStatus_t
cusparseConstBlockedEllGet(cusparseConstSpMatDescr_t spMatDescr,
                           int64_t*                  rows,
                           int64_t*                  cols,
                           int64_t*                  ellBlockSize,
                           int64_t*                  ellCols,
                           const void**              ellColInd,
                           const void**              ellValue,
                           cusparseIndexType_t*      ellIdxType,
                           cusparseIndexBase_t*      idxBase,
                           cudaDataType*             valueType)

该函数返回以块状ELL格式存储的稀疏矩阵描述符spMatDescr的字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

rows

主机

输出

稀疏矩阵的行数

cols

主机

输出

稀疏矩阵的列数

ellBlockSize

主机

输出

ELL块的大小

ellCols

主机

输出

Blocked-Ellpack格式的实际列数

ellColInd

设备

输出

ELL块的列索引。包含[cols / ellBlockSize][rows / ellBlockSize]个元素的数组

ellValue

设备

输出

稀疏矩阵的值。包含rows * ellCols个元素的数组

ellIdxType

主机

输出

ellColInd的数据类型

idxBase

主机

输出

ellColInd的索引基准

valueType

主机

输出

ellValue的数据类型

有关返回状态的描述,请参见cusparseStatus_t


6.5.5. 切片椭圆打包格式 (SELL)

6.5.5.1. cusparseCreateSlicedEll()

cusparseStatus_t
cusparseCreateSlicedEll(cusparseSpMatDescr_t*   spMatDescr,
                        int64_t                 rows,
                        int64_t                 cols,
                        int64_t                 nnz,
                        int64_t                 sellValuesSize,
                        int64_t                 sliceSize,
                        void*                   sellSliceOffsets,
                        void*                   sellColInd,
                        void*                   sellValues,
                        cusparseIndexType_t     sellSliceOffsetsType,
                        cusparseIndexType_t     sellColIndType,
                        cusparseIndexBase_t     idxBase,
                        cudaDataType            valueType)

cusparseStatus_t
cusparseCreateConstSlicedEll(cusparseConstSpMatDescr_t* spMatDescr,
                             int64_t                    rows,
                             int64_t                    cols,
                             int64_t                    nnz,
                             int64_t                    sellValuesSize,
                             int64_t                    sliceSize,
                             const void*                sellSliceOffsets,
                             const void*                sellColInd,
                             const void*                sellValues,
                             cusparseIndexType_t        sellSliceOffsetsType,
                             cusparseIndexType_t        sellColIndType,
                             cusparseIndexBase_t        idxBase,
                             cudaDataType               valueType)

此函数为切片椭圆打包(SELL)格式初始化稀疏矩阵描述符spMatDescr

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

rows

主机

IN

稀疏矩阵的行数

cols

主机

IN

稀疏矩阵的列数

nnz

主机

IN

稀疏矩阵中的非零元素数量

sellValuesSize

主机

IN

sellValues 数组中的元素总数(非零值和填充值)

sliceSize

主机

IN

每个切片中的行数

sellSliceOffsets

设备

IN

稀疏矩阵的切片偏移量。大小为\(\left \lceil{\frac{rows}{sliceSize}}\right \rceil + 1\)的数组

sellColInd

设备

IN

稀疏矩阵的列索引。大小为sellValuesSize的数组

sellValues

设备

IN

稀疏矩阵的值。大小为sellValuesSize个元素的数组

sellSliceOffsetsType

主机

IN

sellSliceOffsets的数据类型

sellColIndType

主机

IN

sellColInd的数据类型

idxBase

主机

IN

sellColInd的索引基数

valueType

主机

IN

sellValues的数据类型

注意

Sliced Ellpack列数组sellColInd包含-1值用于指示填充条目。

cusparseCreateSlicedEll() 有以下限制条件:

  • sellSliceOffsetssellColIndsellValues必须分别与sellSliceOffsetsTypesellColIndTypevalueType指定的数据类型大小对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.6. 块稀疏行(BSR)格式

6.5.6.1. cusparseCreateBsr()

cusparseStatus_t
cusparseCreateBsr(cusparseSpMatDescr_t* spMatDescr,
                  int64_t               brows,
                  int64_t               bcols,
                  int64_t               bnnz,
                  int64_t               rowBlockSize,
                  int64_t               colBlockSize,
                  void*                 bsrRowOffsets,
                  void*                 bsrColInd,
                  void*                 bsrValues,
                  cusparseIndexType_t   bsrRowOffsetsType,
                  cusparseIndexType_t   bsrColIndType,
                  cusparseIndexBase_t   idxBase,
                  cudaDataType          valueType,
                  cusparseOrder_t       order)

cusparseStatus_t
cusparseCreateConstBsr(cusparseConstSpMatDescr_t* spMatDescr,
                       int64_t                    brows,
                       int64_t                    bcols,
                       int64_t                    bnnz,
                       int64_t                    rowBlockSize,
                       int64_t                    colBlockSize,
                       const void*                bsrRowOffsets,
                       const void*                bsrColInd,
                       const void*                bsrValues,
                       cusparseIndexType_t        bsrRowOffsetsType,
                       cusparseIndexType_t        bsrColIndType,
                       cusparseIndexBase_t        idxBase,
                       cudaDataType               valueType,
                       cusparseOrder_t            order)

此函数为块压缩行(BSR)格式初始化稀疏矩阵描述符spMatDescr

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

brows

主机

IN

稀疏矩阵的块行数

bcols

主机

IN

稀疏矩阵的块列数

bnnz

主机

IN

稀疏矩阵的块数

rowBlockSize

主机

IN

每个块的行数

colBlockSize

主机

IN

每个块的列数

bsrRowOffsets

设备

IN

稀疏矩阵的行块偏移量。大小为brows + 1的数组

bsrColInd

设备

IN

稀疏矩阵的块列索引。大小为bnnz的数组

bsrValues

设备

IN

稀疏矩阵的值。大小为bnnz * rowBlockSize * colBlockSize的数组

bsrRowOffsetsType

主机

IN

bsrRowOffsets的数据类型

bsrColIndType

主机

IN

bsrColInd的数据类型

idxBase

主机

IN

bsrRowOffsetsbsrColInd 的基础索引

valueType

主机

IN

bsrValues的数据类型

order

主机

IN

指定每个块中值的内存布局的枚举器

cusparseCreateBsr() 有以下限制条件:

  • bsrRowOffsetsbsrColIndbsrValues必须分别与bsrRowOffsetsTypebsrColIndTypevalueType指定的数据类型大小对齐。有关数据类型的描述,请参阅cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.6.2. cusparseBsrSetStridedBatch()

cusparseStatus_t
cusparseBsrSetStridedBatch(cusparseSpMatDescr_t spMatDescr,
                           int                  batchCount,
                           int64_t              offsetsBatchStride,
                           int64_t              columnsBatchStride,
                           int64_t              valuesBatchStride)

此函数用于设置稀疏矩阵描述符spMatDescr中的batchCountbatchStride字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

batchCount

主机

IN

稀疏矩阵的批次数

offsetsBatchStride

主机

IN

行偏移数组中连续批次之间的地址偏移量

columnsBatchStride

主机

IN

列数组连续批次之间的地址偏移量

valuesBatchStride

主机

IN

值数组中连续批次之间的地址偏移量

有关返回状态的描述,请参见cusparseStatus_t


6.5.7. 所有稀疏格式

6.5.7.1. cusparseDestroySpMat()

cusparseStatus_t
cusparseDestroySpMat(cusparseConstSpMatDescr_t spMatDescr) // non-const descriptor supported

该函数释放为稀疏矩阵描述符spMatDescr分配的主机内存。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.2. cusparseSpMatGetSize()

cusparseStatus_t
cusparseSpMatGetSize(cusparseConstSpMatDescr_t spMatDescr,  // non-const descriptor supported
                     int64_t*                  rows,
                     int64_t*                  cols,
                     int64_t*                  nnz)

该函数返回稀疏矩阵spMatDescr的尺寸。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

rows

主机

输出

稀疏矩阵的行数

cols

主机

输出

稀疏矩阵的列数

nnz

主机

输出

稀疏矩阵的非零元素数量

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.3. cusparseSpMatGetFormat()

cusparseStatus_t
cusparseSpMatGetFormat(cusparseConstSpMatDescr_t spMatDescr, // non-const descriptor supported
                       cusparseFormat_t*         format)

该函数返回稀疏矩阵描述符spMatDescrformat字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

format

主机

输出

稀疏矩阵的存储格式

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.4. cusparseSpMatGetIndexBase()

cusparseStatus_t
cusparseSpMatGetIndexBase(cusparseConstSpMatDescr_t spMatDescr, // non-const descriptor supported
                          cusparseIndexBase_t*      idxBase)

该函数返回稀疏矩阵描述符spMatDescr中的idxBase字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

idxBase

主机

输出

稀疏矩阵的索引基数

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.5. cusparseSpMatGetValues()

cusparseStatus_t
cusparseSpMatGetValues(cusparseSpMatDescr_t spMatDescr,
                       void**               values)

cusparseStatus_t
cusparseConstSpMatGetValues(cusparseConstSpMatDescr_t spMatDescr,
                            const void**              values)

该函数返回稀疏矩阵描述符spMatDescrvalues字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

values

设备

输出

稀疏矩阵的值。包含nnz个元素的数组

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.6. cusparseSpMatSetValues()

cusparseStatus_t
cusparseSpMatSetValues(cusparseSpMatDescr_t spMatDescr,
                       void*                values)

此函数用于设置稀疏矩阵描述符spMatDescr中的values字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

values

设备

IN

稀疏矩阵的值。包含nnz个元素的数组

cusparseSpMatSetValues() 有以下限制条件:

  • values 必须与其在 spMatDescr 中指定的对应数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.7. cusparseSpMatGetStridedBatch()

cusparseStatus_t
cusparseSpMatGetStridedBatch(cusparseConstSpMatDescr_t spMatDescr, // non-const descriptor supported
                             int*                      batchCount)

该函数返回稀疏矩阵描述符spMatDescr中的batchCount字段。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

batchCount

主机

输出

稀疏矩阵的批次数

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.8. cusparseSpMatGetAttribute()

cusparseStatus_t
cusparseSpMatGetAttribute(cusparseConstSpMatDescr_t spMatDescr, // non-const descriptor supported
                          cusparseSpMatAttribute_t  attribute,
                          void*                     data,
                          size_t                    dataSize)

该函数用于获取稀疏矩阵描述符spMatDescr的属性。

参数

内存

输入/输出

含义

spMatDescr

主机

IN

稀疏矩阵描述符

attribute

主机

IN

属性枚举器

data

主机

输出

属性值

dataSize

主机

IN

属性的安全字节大小

属性

含义

可选值

CUSPARSE_SPMAT_FILL_MODE

指示矩阵的下三角或上三角部分是否以稀疏存储方式存储

CUSPARSE_FILL_MODE_LOWER   CUSPARSE_FILL_MODE_UPPER

CUSPARSE_SPMAT_DIAG_TYPE

指示矩阵对角线元素是否为1

CUSPARSE_DIAG_TYPE_NON_UNIT   CUSPARSE_DIAG_TYPE_UNIT

有关返回状态的描述,请参见cusparseStatus_t


6.5.7.9. cusparseSpMatSetAttribute()

cusparseStatus_t
cusparseSpMatSetAttribute(cusparseSpMatDescr_t     spMatDescr,
                          cusparseSpMatAttribute_t attribute,
                          const void*              data,
                          size_t                   dataSize)

该函数用于设置稀疏矩阵描述符spMatDescr的属性

参数

内存

输入/输出

含义

spMatDescr

主机

输出

稀疏矩阵描述符

attribute

主机

IN

属性枚举器

data

主机

IN

属性值

dataSize

主机

IN

属性的安全字节大小

属性

含义

可选值

CUSPARSE_SPMAT_FILL_MODE

指示矩阵的下三角或上三角部分是否以稀疏存储方式存储

CUSPARSE_FILL_MODE_LOWER   CUSPARSE_FILL_MODE_UPPER

CUSPARSE_SPMAT_DIAG_TYPE

指示矩阵对角线元素是否为1

CUSPARSE_DIAG_TYPE_NON_UNIT   CUSPARSE_DIAG_TYPE_UNIT

有关返回状态的描述,请参见cusparseStatus_t



6.6. 通用API函数

6.6.1. cusparseAxpby() [已弃用]

> 此例程将在未来的主要版本中移除。

cusparseStatus_t
cusparseAxpby(cusparseHandle_t          handle,
              const void*               alpha,
              cusparseConstSpVecDescr_t vecX,  // non-const descriptor supported
              const void*               beta,
              cusparseDnVecDescr_t      vecY)

该函数计算稀疏向量vecX与稠密向量vecY的和。

\[\mathbf{Y} = \alpha\mathbf{X} + \beta\mathbf{Y}\]

换句话说,

for i=0 to n-1
    Y[i] = beta * Y[i]
for i=0 to nnz-1
    Y[X_indices[i]] += alpha * X_values[i]

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

alpha

主机或设备

IN

\(\alpha\) 用于计算类型乘法的标量

vecX

主机

IN

稀疏向量 X

beta

主机或设备

IN

\(\beta\) 用于计算类型乘法的标量

vecY

主机

输入/输出

密集向量 Y

cusparseAxpby 支持以下索引类型来表示稀疏向量 vecX

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseAxpby 支持以下数据类型:

统一精度计算:

X/Y/compute

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

X/Y

compute

CUDA_R_16F

CUDA_R_32F

CUDA_R_16BF

CUDA_C_16F

CUDA_C_32F

[已弃用]

CUDA_C_16BF

[已弃用]

cusparseAxpby() 有以下限制条件:

  • 表示稀疏向量vecX的数组必须按16字节对齐

cusparseAxpby() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 如果稀疏向量vecX的索引各不相同,则为每次运行提供确定性(逐位)结果

  • 该例程允许indicesvecX无需排序

cusparseAxpby() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseAxpby查看代码示例。


6.6.2. cusparseGather()

cusparseStatus_t
cusparseGather(cusparseHandle_t          handle,
               cusparseConstDnVecDescr_t vecY,  // non-const descriptor supported
               cusparseSpVecDescr_t      vecX)

该函数将稠密向量vecY的元素收集到稀疏向量vecX

换句话说,

for i=0 to nnz-1
    X_values[i] = Y[X_indices[i]]

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

vecX

主机

输出

稀疏向量 X

vecY

主机

IN

密集向量 Y

cusparseGather 支持以下索引类型来表示稀疏向量 vecX

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseGather 支持以下数据类型:

X/Y

CUDA_R_16F

CUDA_R_16BF

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

cusparseGather() 有以下限制条件:

  • 表示稀疏向量vecX的数组必须按16字节对齐

cusparseGather() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 如果稀疏向量vecX的索引各不相同,则为每次运行提供确定性(逐位)结果

  • 该例程允许indicesvecX进行无序排列

cusparseGather() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseGather查看代码示例。


6.6.3. cusparseScatter()

cusparseStatus_t
cusparseScatter(cusparseHandle_t          handle,
                cusparseConstSpVecDescr_t vecX,  // non-const descriptor supported
                cusparseDnVecDescr_t      vecY)

该函数将稀疏向量vecX的元素分散到密集向量vecY

换句话说,

for i=0 to nnz-1
    Y[X_indices[i]] = X_values[i]

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

vecX

主机

IN

稀疏向量 X

vecY

主机

输出

密集向量 Y

cusparseScatter 支持以下索引类型来表示稀疏向量 vecX

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseScatter 支持以下数据类型:

X/Y

CUDA_R_8I

CUDA_R_16F

CUDA_R_16BF

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

cusparseScatter() 有以下限制条件:

  • 表示稀疏向量vecX的数组必须16字节对齐

cusparseScatter() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 如果稀疏向量vecX的索引各不相同,则为每次运行提供确定性(逐位)结果

  • 该例程允许indicesvecX进行无序排列

cusparseScatter() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseScatter查看代码示例。


6.6.4. cusparseRot() [已弃用]

> 该例程将在下一个主要版本中移除

cusparseStatus_t
cusparseRot(cusparseHandle_t     handle,
            const void*          c_coeff,
            const void*          s_coeff,
            cusparseSpVecDescr_t vecX,
            cusparseDnVecDescr_t vecY)

该函数计算吉文斯旋转矩阵

\[\begin{split}G = \begin{bmatrix} c & s \\ {- s} & c \\ \end{bmatrix}\end{split}\]

转换为稀疏向量 vecX 和密集向量 vecY

换句话说,

for i=0 to nnz-1
    Y[X_indices[i]] = c * Y[X_indices[i]] - s * X_values[i]
    X_values[i]     = c * X_values[i]     + s * Y[X_indices[i]]

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

c_coeff

主机或设备

IN

旋转矩阵的余弦元素

vecX

主机

输入/输出

稀疏向量 X

s_coeff

主机或设备

IN

旋转矩阵的正弦元素

vecY

主机

输入/输出

密集向量 Y

cusparseRot 支持以下索引类型来表示稀疏向量 vecX

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseRot 支持以下数据类型:

统一精度计算:

X/Y/compute

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

X/Y

compute

CUDA_R_16F

CUDA_R_32F

CUDA_R_16BF

CUDA_C_16F

CUDA_C_32F

[已弃用]

CUDA_C_16BF

[已弃用]

cusparseRot() 有以下限制条件:

  • 表示稀疏向量vecX的数组必须按16字节对齐

cusparseRot() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 如果稀疏向量vecX的索引各不相同,则为每次运行提供确定性(逐位)结果

cusparseRot() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseRot查看代码示例。


6.6.5. cusparseSpVV() [已弃用]

> 此例程将在未来的主要版本中移除。

cusparseStatus_t
cusparseSpVV_bufferSize(cusparseHandle_t          handle,
                        cusparseOperation_t       opX,
                        cusparseConstSpVecDescr_t vecX,  // non-const descriptor supported
                        cusparseConstDnVecDescr_t vecY,  // non-const descriptor supported
                        void*                     result,
                        cudaDataType              computeType,
                        size_t*                   bufferSize)
cusparseStatus_t
cusparseSpVV(cusparseHandle_t          handle,
             cusparseOperation_t       opX,
             cusparseConstSpVecDescr_t vecX,  // non-const descriptor supported
             cusparseConstDnVecDescr_t vecY,  // non-const descriptor supported
             void*                     result,
             cudaDataType              computeType,
             void*                     externalBuffer)

该函数计算稀疏向量vecX与稠密向量vecY的内积

\[result = op\left(\mathbf{X}\right) \cdot \mathbf{Y}\]

换句话说,

result = 0;
for i=0 to nnz-1
    result += op(X_values[i]) * Y[X_indices[i]]

image10

函数 cusparseSpVV_bufferSize() 返回 cusparseSpVV() 所需工作空间的大小

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opX

主机

IN

操作 op(X) 表示非转置或共轭转置

vecX

主机

IN

稀疏向量 X

vecY

主机

IN

密集向量 Y

result

主机或设备

输出

结果的点积

computeType

主机

IN

执行计算所用的数据类型

bufferSize

主机

输出

cusparseSpVV 所需的暂存空间字节数

externalBuffer

设备

IN

指向至少bufferSize字节的工作区缓冲区的指针

cusparseSpVV 支持以下索引类型来表示稀疏向量 vecX

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

当前cusparseSpVV支持的数据类型组合如下:

统一精度计算:

X/Y/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

X/Y

computeType/result

注意事项

CUDA_R_8I

CUDA_R_32I

CUDA_R_8I

CUDA_R_32F

CUDA_R_16F

CUDA_R_32F

CUDA_R_16BF

CUDA_R_32F

CUDA_C_16F

CUDA_C_32F

[已弃用]

CUDA_C_16BF

CUDA_C_32F

[已弃用]

cusparseSpVV() 有以下限制条件:

  • 表示稀疏向量vecX的数组必须16字节对齐

cusparseSpVV() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 如果稀疏向量vecX的索引各不相同,则为每次运行提供确定性(逐位)结果

  • 该例程允许indicesvecX进行无序排列

cusparseSpVV() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseSpVV查看代码示例。


6.6.6. cusparseSpMV()

cusparseStatus_t
cusparseSpMV_bufferSize(cusparseHandle_t          handle,
                        cusparseOperation_t       opA,
                        const void*               alpha,
                        cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                        cusparseConstDnVecDescr_t vecX,  // non-const descriptor supported
                        const void*               beta,
                        cusparseDnVecDescr_t      vecY,
                        cudaDataType              computeType,
                        cusparseSpMVAlg_t         alg,
                        size_t*                   bufferSize)
cusparseStatus_t
cusparseSpMV_preprocess(cusparseHandle_t          handle,
                        cusparseOperation_t       opA,
                        const void*               alpha,
                        cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                        cusparseConstDnVecDescr_t vecX,  // non-const descriptor supported
                        const void*               beta,
                        cusparseDnVecDescr_t      vecY,
                        cudaDataType              computeType,
                        cusparseSpMVAlg_t         alg,
                        void*                     externalBuffer)
cusparseStatus_t
cusparseSpMV(cusparseHandle_t          handle,
             cusparseOperation_t       opA,
             const void*               alpha,
             cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
             cusparseConstDnVecDescr_t vecX,  // non-const descriptor supported
             const void*               beta,
             cusparseDnVecDescr_t      vecY,
             cudaDataType              computeType,
             cusparseSpMVAlg_t         alg,
             void*                     externalBuffer)

该函数执行稀疏矩阵matA与稠密向量vecX的乘法运算

\[\mathbf{Y} = \alpha op\left( \mathbf{A} \right) \cdot \mathbf{X} + \beta\mathbf{Y}\]

其中

  • op(A) 是一个大小为 \(m \times k\) 的稀疏矩阵

  • X 是一个大小为 \(k\) 的密集向量

  • Y 是一个大小为 \(m\) 的密集向量

  • \(\alpha\)\(\beta\) 是标量

同样,对于矩阵 A

image11

函数 cusparseSpMV_bufferSize() 返回 cusparseSpMV_preprocess()cusparseSpMV() 所需工作空间的大小

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

alpha

主机或设备

IN

\(\alpha\) 用于与类型 computeType 相乘的标量

matA

主机

IN

稀疏矩阵 A

vecX

主机

IN

密集向量 X

beta

主机或设备

IN

\(\beta\) 用于与类型 computeType 相乘的标量

vecY

主机

输入/输出

密集向量 Y

computeType

主机

IN

执行计算所用的数据类型

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseSpMV所需的暂存空间字节数

externalBuffer

设备

IN

指向至少bufferSize字节的工作区缓冲区的指针

当前支持的稀疏矩阵格式如下:

  • CUSPARSE_FORMAT_COO

  • CUSPARSE_FORMAT_CSR

  • CUSPARSE_FORMAT_CSC

  • CUSPARSE_FORMAT_SLICED_ELL

cusparseSpMV 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseSpMV 支持以下数据类型:

统一精度计算:

A/X/ Y/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

A/X

Y

computeType

注意事项

CUDA_R_8I

CUDA_R_32I

CUDA_R_32I

CUDA_R_8I

CUDA_R_32F

CUDA_R_32F

CUDA_R_16F

CUDA_R_16BF

CUDA_R_16F

CUDA_R_16F

CUDA_R_16BF

CUDA_R_16BF

CUDA_C_32F

CUDA_C_32F

CUDA_C_32F

CUDA_C_16F

CUDA_C_16F

[已弃用]

CUDA_C_16BF

CUDA_C_16BF

[已弃用]

A

X/Y/computeType

CUDA_R_32F

CUDA_R_64F

混合常规/复杂计算:

A

X/Y/computeType

CUDA_R_32F

CUDA_C_32F

CUDA_R_64F

CUDA_C_64F

注意:CUDA_R_16FCUDA_R_16BFCUDA_C_16FCUDA_C_16BF数据类型始终意味着混合精度计算。

cusparseSpMV() 支持以下算法:

算法

备注

CUSPARSE_SPMV_ALG_DEFAULT

适用于任何稀疏矩阵格式的默认算法。

CUSPARSE_SPMV_COO_ALG1

COO稀疏矩阵格式的默认算法。使用相同输入参数的不同运行过程中可能会产生略微不同的结果。

CUSPARSE_SPMV_COO_ALG2

为每次运行提供确定性(逐位)结果。如果opA != CUSPARSE_OPERATION_NON_TRANSPOSE,则与CUSPARSE_SPMV_COO_ALG1相同。

CUSPARSE_SPMV_CSR_ALG1

CSR/CSC稀疏矩阵格式的默认算法。使用相同的输入参数在不同运行时可能会产生略微不同的结果。

CUSPARSE_SPMV_CSR_ALG2

为每次运行提供确定性(逐位)结果。如果opA != CUSPARSE_OPERATION_NON_TRANSPOSE,则与CUSPARSE_SPMV_CSR_ALG1相同。

CUSPARSE_SPMV_SELL_ALG1

Sliced Ellpack稀疏矩阵格式的默认算法。每次运行提供确定性(按位)结果。

调用cusparseSpMV_preprocess()是可选的。 它可以加速后续对cusparseSpMV()的调用。 当需要多次使用相同的稀疏模式(matA)调用cusparseSpMV()时,这个预处理函数会很有用。

调用cusparseSpMV_preprocess()时使用buffer会使该缓冲区在matA的SpMV调用中处于"激活"状态。 后续使用matA和激活缓冲区调用cusparseSpMV()时, 所有参数值必须与调用cusparseSpMV_preprocess()时保持一致。 例外情况是:alphabetavecXvecY以及matA的值(但不包括索引)可以不同。 重要的是,自调用cusparseSpMV_preprocess()以来,缓冲区内容必须保持未修改状态。 当使用matA及其激活缓冲区调用cusparseSpMV()时,可能会从缓冲区读取加速数据。

再次调用cusparseSpMV_preprocess()并传入matA和新缓冲区时,将使新缓冲区变为活动状态,同时遗忘先前活动的缓冲区并将其置为非活动状态。对于cusparseSpMV(),每个稀疏矩阵同一时间只能有一个活动缓冲区。若要实现单个稀疏矩阵拥有多个活动缓冲区的效果,可创建多个矩阵句柄(这些句柄都指向相同的索引和值缓冲区),然后为每个句柄使用不同的工作区缓冲区各调用一次cusparseSpMV_preprocess()

调用cusparseSpMV()时使用非活动缓冲区始终是被允许的。但在这种情况下,预处理可能不会带来加速效果。

出于线程安全的考虑, cusparseSpMV_preprocess()正在写入matA的内部状态。

性能说明:

  • CUSPARSE_SPMV_COO_ALG1CUSPARSE_SPMV_CSR_ALG1 相比 CUSPARSE_SPMV_COO_ALG2CUSPARSE_SPMV_CSR_ALG2 能提供更高的性能。

  • 通常来说,opA == CUSPARSE_OPERATION_NON_TRANSPOSEopA != CUSPARSE_OPERATION_NON_TRANSPOSE快3倍。

  • 使用cusparseSpMV_preprocess()有助于提升CSR格式下cusparseSpMV()的性能。当我们需要用同一个矩阵多次运行cusparseSpMV()时特别有益(cusparseSpMV_preprocess()只需执行一次)。

cusparseSpMV() 具有以下特性:

  • 该例程需要为CSR/CSC格式(所有算法)以及使用CUSPARSE_SPMV_COO_ALG2算法的COO格式提供额外存储空间。

  • 仅为CUSPARSE_SPMV_COO_ALG2CUSPARSE_SPMV_CSR_ALG2算法,以及opA == CUSPARSE_OPERATION_NON_TRANSPOSE的情况,提供每次运行的确定性(逐位)结果。

  • 该例程支持异步执行。

  • beta == 0时,compute-sanitizer可能会对此例程报告虚假的竞态条件。这是出于优化目的,不会影响计算的正确性。

  • 该例程允许matA的索引不排序。

cusparseSpMV() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseSpMV CSRcusparseSpMV COO查看代码示例。


6.6.7. cusparseSpSV()

cusparseStatus_t
cusparseSpSV_createDescr(cusparseSpSVDescr_t* spsvDescr);

cusparseStatus_t
cusparseSpSV_destroyDescr(cusparseSpSVDescr_t spsvDescr);
cusparseStatus_t
cusparseSpSV_bufferSize(cusparseHandle_t          handle,
                        cusparseOperation_t       opA,
                        const void*               alpha,
                        cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                        cusparseConstDnVecDescr_t vecX,  // non-const descriptor supported
                        cusparseDnVecDescr_t      vecY,
                        cudaDataType              computeType,
                        cusparseSpSVAlg_t         alg,
                        cusparseSpSVDescr_t       spsvDescr,
                        size_t*                   bufferSize)
cusparseStatus_t
cusparseSpSV_analysis(cusparseHandle_t          handle,
                      cusparseOperation_t       opA,
                      const void*               alpha,
                      cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                      cusparseConstDnVecDescr_t vecX,  // non-const descriptor supported
                      cusparseDnVecDescr_t      vecY,
                      cudaDataType              computeType,
                      cusparseSpSVAlg_t         alg,
                      cusparseSpSVDescr_t       spsvDescr
                      void*                     externalBuffer)
cusparseStatus_t
cusparseSpSV_solve(cusparseHandle_t          handle,
                   cusparseOperation_t       opA,
                   const void*               alpha,
                   cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                   cusparseConstDnVecDescr_t vecX,  // non-const descriptor supported
                   cusparseDnVecDescr_t      vecY,
                   cudaDataType              computeType,
                   cusparseSpSVAlg_t         alg,
                   cusparseSpSVDescr_t       spsvDescr)
cusparseStatus_t
cusparseSpSV_updateMatrix(cusparseHandle_t     handle,
                          cusparseSpSVDescr_t  spsvDescr,
                          void*                newValues,
                          cusparseSpSVUpdate_t updatePart)

该函数用于求解一个线性方程组,其系数以稀疏三角矩阵的形式表示:

\[op\left( \mathbf{A} \right) \cdot \mathbf{Y} = \alpha\mathbf{X}\]

其中

  • op(A) 是一个大小为 \(m \times m\) 的稀疏方阵

  • X 是一个大小为 \(m\) 的密集向量

  • Y 是一个大小为 \(m\) 的密集向量

  • \(\alpha\) 是一个标量

同样,对于矩阵 A

image11

函数 cusparseSpSV_bufferSize() 返回 cusparseSpSV_analysis()cusparseSpSV_solve() 所需的工作空间大小。 函数 cusparseSpSV_analysis() 执行分析阶段,而 cusparseSpSV_solve() 则执行稀疏三角线性系统的求解阶段。 不透明数据结构 spsvDescr 用于在所有函数之间共享信息。 函数 cusparseSpSV_updateMatrix() 用新的矩阵值更新 spsvDescr

该例程支持输入矩阵的任意稀疏性,但在计算中仅考虑上三角或下三角部分。

注意:所有参数在cusparseSpSV API调用之间必须保持一致,且在cusparseSpSV_analysis()cusparseSpSV_solve()之间不得修改矩阵描述和externalBuffer。函数cusparseSpSV_updateMatrix()可用于更新存储在spsvDescr不透明数据结构中的稀疏矩阵值。

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

alpha

主机或设备

IN

\(\alpha\) 用于与类型 computeType 相乘的标量

matA

主机

IN

稀疏矩阵 A

vecX

主机

IN

密集向量 X

vecY

主机

输入/输出

密集向量 Y

computeType

主机

IN

执行计算所用的数据类型

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseSpSV_analysis()cusparseSpSV_solve() 所需的暂存空间字节数

externalBuffer

设备

输入/输出

指向至少bufferSize字节的工作区缓冲区的指针。它被cusparseSpSV_analysiscusparseSpSV_solve()使用

spsvDescr

主机

输入/输出

用于存储三个步骤间使用的内部数据的不透明描述符

当前支持的稀疏矩阵格式如下:

  • CUSPARSE_FORMAT_CSR

  • CUSPARSE_FORMAT_COO

  • CUSPARSE_FORMAT_SLICED_ELL

cusparseSpSV() 支持以下形状和属性:

  • CUSPARSE_FILL_MODE_LOWERCUSPARSE_FILL_MODE_UPPER 填充模式

  • CUSPARSE_DIAG_TYPE_NON_UNITCUSPARSE_DIAG_TYPE_UNIT 对角线类型

填充模式和对角线类型可以通过cusparseSpMatSetAttribute()进行设置。

cusparseSpSV() 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseSpSV() 支持以下数据类型:

统一精度计算:

A/X/ Y/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

cusparseSpSV() 支持以下算法:

算法

备注

CUSPARSE_SPSV_ALG_DEFAULT

默认算法

cusparseSpSV() 具有以下特性:

  • 该例程在分析阶段需要额外的存储空间,其大小与稀疏矩阵的非零元素数量成正比

  • 为求解阶段cusparseSpSV_solve()的每次运行提供确定性(逐位)结果

  • 该例程支持原地操作

  • cusparseSpSV_solve() 例程支持异步执行

  • cusparseSpSV_bufferSize()cusparseSpSV_analysis() 例程允许为 vecXvecY 传入 NULL

  • 该例程允许matA的索引不排序

cusparseSpSV() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

cusparseSpSV_updateMatrix() 在调用分析阶段后更新稀疏矩阵。该函数支持以下更新策略 (updatePart):

策略

备注

CUSPARSE_SPSV_UPDATE_GENERAL

使用newValues数组中的值更新稀疏矩阵值

CUSPARSE_SPSV_UPDATE_DIAGONAL

使用存储在newValues数组中的对角线值更新矩阵的对角线部分。也就是说,newValues仅包含新的对角线值

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE Library Samples - cusparseSpSV CSRcuSPARSE Library Samples - cusparseSpSV COO查看代码示例。


6.6.8. cusparseSpMM()

cusparseStatus_t
cusparseSpMM_bufferSize(cusparseHandle_t          handle,
                        cusparseOperation_t       opA,
                        cusparseOperation_t       opB,
                        const void*               alpha,
                        cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                        cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                        const void*               beta,
                        cusparseDnMatDescr_t      matC,
                        cudaDataType              computeType,
                        cusparseSpMMAlg_t         alg,
                        size_t*                   bufferSize)
cusparseStatus_t
cusparseSpMM_preprocess(cusparseHandle_t          handle,
                        cusparseOperation_t       opA,
                        cusparseOperation_t       opB,
                        const void*               alpha,
                        cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                        cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                        const void*               beta,
                        cusparseDnMatDescr_t      matC,
                        cudaDataType              computeType,
                        cusparseSpMMAlg_t         alg,
                        void*                     externalBuffer)
cusparseStatus_t
cusparseSpMM(cusparseHandle_t          handle,
             cusparseOperation_t       opA,
             cusparseOperation_t       opB,
             const void*               alpha,
             cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
             cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
             const void*               beta,
             cusparseDnMatDescr_t      matC,
             cudaDataType              computeType,
             cusparseSpMMAlg_t         alg,
             void*                     externalBuffer)

该函数执行稀疏矩阵matA与稠密矩阵matB的乘法运算。

\[\mathbf{C} = \alpha op\left( \mathbf{A} \right) \cdot op\left( \mathbf{B} \right) + \beta\mathbf{C}\]

其中

  • op(A) 是一个大小为 \(m \times k\) 的稀疏矩阵

  • op(B) 是一个大小为 \(k \times n\) 的稠密矩阵

  • C 是一个大小为 \(m \times n\) 的密集矩阵

  • \(\alpha\)\(\beta\) 是标量

该例程也可用于执行稠密矩阵与稀疏矩阵的乘法,只需切换稠密矩阵的布局:

\[\begin{split}\begin{array}{l} \left. \mathbf{C}_{C} = \mathbf{B}_{C} \cdot \mathbf{A} + \beta\mathbf{C}_{C}\rightarrow \right. \\ {\mathbf{C}_{R} = \mathbf{A}^{T} \cdot \mathbf{B}_{R} + \beta\mathbf{C}_{R}} \\ \end{array}\end{split}\]

其中 \(\mathbf{B}_{C}\)\(\mathbf{C}_{C}\) 表示列优先布局,而 \(\mathbf{B}_{R}\)\(\mathbf{C}_{R}\) 表示行优先布局

同样地,对于矩阵 AB

image11

image12

当使用稀疏矩阵A的(共轭)转置时,该例程在相同输入参数的不同运行中可能会产生略微不同的结果。

函数 cusparseSpMM_bufferSize() 返回 cusparseSpMM() 所需工作空间的大小

调用cusparseSpMM_preprocess()是可选的。 它可以加速后续对cusparseSpMM()的调用。 当使用相同的稀疏模式(matA)多次调用cusparseSpMM()时,这个函数很有用。 它对CUSPARSE_SPMM_CSR_ALG1CUSPARSE_SPMM_CSR_ALG3能提供性能优势。 对于所有其他格式和算法则没有效果。

调用cusparseSpMM_preprocess()时使用buffer会使该缓冲区在matA的SpMM调用中处于"激活"状态。 后续使用matA和激活缓冲区调用cusparseSpMM()时, 所有参数值必须与调用cusparseSpMM_preprocess()时保持一致。 例外情况包括:alphabetamatXmatY以及matA的值(但不包括索引)可以不同。 重要的是,自调用cusparseSpMM_preprocess()后,缓冲区内容必须保持未被修改。 当使用matA及其激活缓冲区调用cusparseSpMM()时,可能会从缓冲区读取加速数据。

再次调用cusparseSpMM_preprocess()并传入matA和新缓冲区时,将使新缓冲区变为活动状态,同时遗忘先前活动的缓冲区并将其置为非活动状态。对于cusparseSpMM(),每个稀疏矩阵同一时间只能有一个活动缓冲区。若要实现单个稀疏矩阵拥有多个活动缓冲区的效果,可创建多个矩阵句柄(这些句柄都指向相同的索引和值缓冲区),然后为每个句柄使用不同的工作区缓冲区各调用一次cusparseSpMM_preprocess()

调用cusparseSpMM()时使用非活动缓冲区始终是被允许的。但在这种情况下,预处理可能不会带来加速效果。

出于线程安全的考虑, cusparseSpMM_preprocess()会写入matA的内部状态。

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

opB

主机

IN

操作 op(B)

alpha

主机或设备

IN

\(\alpha\) 用于与类型 computeType 相乘的标量

matA

主机

IN

稀疏矩阵 A

matB

主机

IN

稠密矩阵 B

beta

主机或设备

IN

\(\beta\) 用于与类型 computeType 相乘的标量

matC

主机

输入/输出

稠密矩阵 C

computeType

主机

IN

执行计算所用的数据类型

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseSpMM 所需的暂存空间字节数

externalBuffer

设备

IN

指向至少bufferSize字节的工作空间缓冲区的指针

cusparseSpMM 支持以下稀疏矩阵格式:

  • CUSPARSE_FORMAT_COO

  • CUSPARSE_FORMAT_CSR

  • CUSPARSE_FORMAT_CSC

  • CUSPARSE_FORMAT_BSR

  • CUSPARSE_FORMAT_BLOCKED_ELL

(1)

COO/CSR/CSC/BSR格式

cusparseSpMM 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseSpMM 支持以下数据类型:

统一精度计算:

A/B/ C/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

A/B

C

computeType

CUDA_R_8I

CUDA_R_32I

CUDA_R_32I

CUDA_R_8I

CUDA_R_32F

CUDA_R_32F

CUDA_R_16F

CUDA_R_16BF

CUDA_R_16F

CUDA_R_16F

CUDA_R_16BF

CUDA_R_16BF

CUDA_C_16F

CUDA_C_16F

CUDA_C_32F

[已弃用]

CUDA_C_16BF

CUDA_C_16BF

[已弃用]

注意:CUDA_R_16FCUDA_R_16BFCUDA_C_16FCUDA_C_16BF数据类型始终意味着混合精度计算。

cusparseSpMM 支持以下算法:

算法

备注

CUSPARSE_SPMM_ALG_DEFAULT

适用于任何稀疏矩阵格式的默认算法

CUSPARSE_SPMM_COO_ALG1

COO稀疏矩阵格式的算法1

  • 对于少量非零元素可能提供更好的性能

  • 在列主序布局下提供最佳性能

  • 它支持批量计算

  • 使用相同的输入参数在不同运行中可能会产生略微不同的结果

CUSPARSE_SPMM_COO_ALG2

COO稀疏矩阵格式的算法2

  • 它提供确定性的结果

  • 在列主序布局下提供最佳性能

  • 总体而言,比算法1慢

  • 它支持批量计算

  • 它需要额外的内存

  • 如果 opA != CUSPARSE_OPERATION_NON_TRANSPOSE,则等同于 CUSPARSE_SPMM_COO_ALG1

CUSPARSE_SPMM_COO_ALG3

COO稀疏矩阵格式的算法3

  • 对于大量非零元素(nnz)可能提供更好的性能

  • 使用相同的输入参数时,不同运行可能会产生略微不同的结果

CUSPARSE_SPMM_COO_ALG4

COO稀疏矩阵格式的算法4

  • 为行主序布局提供更优性能

  • 它支持批量计算

  • 使用相同的输入参数在不同运行时可能产生略微不同的结果

CUSPARSE_SPMM_CSR_ALG1

CSR/CSC稀疏矩阵格式的算法1

  • 在列主序布局下提供最佳性能

  • 它支持批量计算

  • 它需要额外的内存

  • 使用相同的输入参数在不同运行中可能会产生略微不同的结果

CUSPARSE_SPMM_CSR_ALG2

针对CSR/CSC稀疏矩阵格式的算法2

  • 为行优先布局提供最佳性能

  • 它支持批量计算

  • 它需要额外的内存

  • 使用相同的输入参数在不同运行中可能会产生略微不同的结果

CUSPARSE_SPMM_CSR_ALG3

针对CSR/CSC稀疏矩阵格式的算法3

  • 它提供确定性的结果

  • 它需要额外的内存

  • 它仅支持 opA == CUSPARSE_OPERATION_NON_TRANSPOSE

  • 它不支持 opB == CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE

  • 它不支持CUDA_C_16F and CUDA_C_16BF数据类型

CUSPARSE_SPMM_BSR_ALG1

BSR稀疏矩阵格式的算法1

  • 它提供确定性的结果

  • 它不需要额外的内存

  • 它仅支持 opA == CUSPARSE_OPERATION_NON_TRANSPOSE

  • 它不支持 CUDA_C_16FCUDA_C_16BF 数据类型

  • 它不支持A中的列主序块

性能说明:

  • 行优先布局比列优先布局提供更高的性能

  • CUSPARSE_SPMM_COO_ALG4CUSPARSE_SPMM_CSR_ALG2 应与行优先布局一起使用,而 CUSPARSE_SPMM_COO_ALG1CUSPARSE_SPMM_COO_ALG2CUSPARSE_SPMM_COO_ALG3CUSPARSE_SPMM_CSR_ALG1 应与列优先布局一起使用

  • beta != 1 时,大多数算法会在主计算之前对输出矩阵进行缩放

  • n == 1 时,该例程可能会使用 cusparseSpMV()

cusparseSpMM() 支持以下所有批处理模式,除了 CUSPARSE_SPMM_CSR_ALG3

  • \(C_{i} = A \cdot B_{i}\)

  • \(C_{i} = A_{i} \cdot B\)

  • \(C_{i} = A_{i} \cdot B_{i}\)

批次数及其步长可以通过使用cusparseCooSetStridedBatchcusparseCsrSetStridedBatchcusparseDnMatSetStridedBatch来设置。cusparseSpMM()的最大批次数为65,535。

cusparseSpMM() 具有以下特性:

  • 该例程对于CUSPARSE_SPMM_COO_ALG1CUSPARSE_SPMM_COO_ALG3CUSPARSE_SPMM_COO_ALG4CUSPARSE_SPMM_BSR_ALG1不需要额外的存储空间

  • 该例程支持异步执行

  • 仅为CUSPARSE_SPMM_COO_ALG2CUSPARSE_SPMM_CSR_ALG3CUSPARSE_SPMM_BSR_ALG1算法提供每次运行的确定性(逐位)结果

  • compute-sanitizer 可能会报告此例程的虚假竞争条件。这是出于优化目的,不会影响计算的正确性

  • 该例程允许matA的索引不排序

cusparseSpMM() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

请访问cuSPARSE库示例 - cusparseSpMM CSRcusparseSpMM COO查看代码示例。如需批量计算,请访问cusparseSpMM CSR批量版cusparseSpMM COO批量版

(2)

分块ELLPACK格式

cusparseSpMM 支持以下数据类型用于 CUSPARSE_FORMAT_BLOCKED_ELL 格式,以及以下GPU架构以利用NVIDIA Tensor Cores:

A/B

C

computeType

opB

计算 能力

CUDA_R_16F

CUDA_R_16F

CUDA_R_16F

N, T

70

CUDA_R_16F

CUDA_R_16F

CUDA_R_32F

N, T

70

CUDA_R_16F

CUDA_R_32F

CUDA_R_32F

N, T

70

CUDA_R_8I

CUDA_R_32I

CUDA_R_32I

N 列优先

75

T 行优先

CUDA_R_16BF

CUDA_R_16BF

CUDA_R_32F

N, T

80

CUDA_R_16BF

CUDA_R_32F

CUDA_R_32F

N, T

80

CUDA_R_32F

CUDA_R_32F

CUDA_R_32F

N, T

80

CUDA_R_64F

CUDA_R_64F

CUDA_R_64F

N, T

80

cusparseSpMM 支持以下使用 CUSPARSE_FORMAT_BLOCKED_ELL 格式的算法:

算法

备注

CUSPARSE_SPMM_ALG_DEFAULT

适用于任何稀疏矩阵格式的默认算法

CUSPARSE_SPMM_BLOCKED_ELL_ALG1

Blocked-ELL格式的默认算法

性能说明:

  • Blocked-ELL SpMM 在使用2的幂次方块大小时能提供最佳性能。

  • 较大的块大小(例如≥64)能提供最佳性能。

该函数有以下限制:

  • 指针模式必须等于 CUSPARSE_POINTER_MODE_HOST

  • 仅支持 opA == CUSPARSE_OPERATION_NON_TRANSPOSE

  • opB == CUSPARSE_OPERATION_CONJUGATE_TRANSPOSE 不支持该操作。

  • 仅支持 CUSPARSE_INDEX_32I

请访问cuSPARSE库示例 - cusparseSpMM Blocked-ELL查看代码示例。

有关返回状态的描述,请参见cusparseStatus_t


6.6.9. cusparseSpMMOp()

cusparseStatus_t CUSPARSEAPI
cusparseSpMMOp_createPlan(cusparseHandle_t          handle,
                          cusparseSpMMOpPlan_t*     plan,
                          cusparseOperation_t       opA,
                          cusparseOperation_t       opB,
                          cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                          cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                          cusparseDnMatDescr_t      matC,
                          cudaDataType              computeType,
                          cusparseSpMMOpAlg_t       alg,
                          const void*               addOperationNvvmBuffer,
                          size_t                    addOperationBufferSize,
                          const void*               mulOperationNvvmBuffer,
                          size_t                    mulOperationBufferSize,
                          const void*               epilogueNvvmBuffer,
                          size_t                    epilogueBufferSize,
                          size_t*                   SpMMWorkspaceSize)

cusparseStatus_t
cusparseSpMMOp_destroyPlan(cusparseSpMMOpPlan_t plan)
cusparseStatus_t
cusparseSpMMOp(cusparseSpMMOpPlan_t plan,
               void*                externalBuffer)

注意1: NVRTC和nvJitLink目前在Arm64 Android平台上不可用。

注意2: 该例程不支持除Judy (sm87)之外的Android和Tegra平台。

实验性功能:该函数使用自定义运算符执行稀疏矩阵matA与稠密矩阵matB的乘法运算。

\[{C^{\prime}}_{ij} = \text{epilogue}\left( {\sum_{k}^{\oplus}{op\left( A_{ik} \right) \otimes op\left( B_{kj} \right),C_{ij}}} \right)\]

其中

  • op(A) 是一个大小为 \(m \times k\) 的稀疏矩阵

  • op(B) 是一个大小为 \(k \times n\) 的稠密矩阵

  • C 是一个大小为 \(m \times n\) 的密集矩阵

  • \(\oplus\)\(\otimes\)\(\text{epilogue}\)分别是自定义的加法乘法收尾运算符。

同样地,对于矩阵 AB

image13

image7

目前仅支持 opA == CUSPARSE_OPERATION_NON_TRANSPOSE

函数 cusparseSpMMOp_createPlan() 返回 cusparseSpMMOp() 所需的工作空间大小和编译后的内核

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

opB

主机

IN

操作 op(B)

matA

主机

IN

稀疏矩阵 A

matB

主机

IN

稠密矩阵 B

matC

主机

输入/输出

稠密矩阵 C

computeType

主机

IN

执行计算所用的数据类型

alg

主机

IN

计算算法

addOperationNvvmBuffer

主机

IN

指向包含自定义add运算符的NVVM缓冲区的指针

addOperationBufferSize

主机

IN

addOperationNvvmBuffer 的大小(以字节为单位)

mulOperationNvvmBuffer

主机

IN

指向包含自定义mul运算符的NVVM缓冲区的指针

mulOperationBufferSize

主机

IN

mulOperationNvvmBuffer的大小(以字节为单位)

epilogueNvvmBuffer

主机

IN

指向包含自定义尾声运算符的NVVM缓冲区的指针

epilogueBufferSize

主机

IN

epilogueNvvmBuffer 的大小(以字节为单位)

SpMMWorkspaceSize

主机

输出

cusparseSpMMOp 所需的字节数工作空间

操作符必须具有以下签名和返回类型

__device__ <computetype> add_op(<computetype> value1, <computetype> value2);

__device__ <computetype> mul_op(<computetype> value1, <computetype> value2);

__device__ <computetype> epilogue(<computetype> value1, <computetype> value2);

可以是 floatdoublecuComplexcuDoubleComplexint 类型之一,

cusparseSpMMOp 支持以下稀疏矩阵格式:

  • CUSPARSE_FORMAT_CSR

cusparseSpMMOp 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseSpMMOp 支持以下数据类型:

统一精度计算:

A/B/ C/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

A/B

C

computeType

CUDA_R_8I

CUDA_R_32I

CUDA_R_32I

CUDA_R_8I

CUDA_R_32F

CUDA_R_32F

CUDA_R_16F

CUDA_R_16BF

CUDA_R_16F

CUDA_R_16F

CUDA_R_16BF

CUDA_R_16BF

cusparseSpMMOp 支持以下算法:

算法

备注

CUSPARSE_SPMM_OP_ALG_DEFAULT

适用于任何稀疏矩阵格式的默认算法

性能说明:

  • 行优先布局比列优先布局提供更高的性能。

cusparseSpMMOp() 具有以下特性:

  • 该例程需要额外的存储空间

  • 该例程支持异步执行

  • 每次运行提供确定性(逐位)结果

  • 该例程允许matA的索引不排序

cusparseSpMMOp() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

请访问 cuSPARSE Library Samples - cusparseSpMMOp

有关返回状态的描述,请参见cusparseStatus_t


6.6.10. cusparseSpSM()

cusparseStatus_t
cusparseSpSM_createDescr(cusparseSpSMDescr_t* spsmDescr);
cusparseStatus_t
cusparseSpSM_destroyDescr(cusparseSpSMDescr_t spsmDescr);
cusparseStatus_t
cusparseSpSM_bufferSize(cusparseHandle_t     handle,
                        cusparseOperation_t  opA,
                        cusparseOperation_t  opB,
                        const void*          alpha,
                        cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                        cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                        cusparseDnMatDescr_t matC,
                        cudaDataType         computeType,
                        cusparseSpSMAlg_t    alg,
                        cusparseSpSMDescr_t  spsmDescr,
                        size_t*              bufferSize)
cusparseStatus_t
cusparseSpSM_analysis(cusparseHandle_t          handle,
                      cusparseOperation_t       opA,
                      cusparseOperation_t       opB,
                      const void*               alpha,
                      cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                      cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                      cusparseDnMatDescr_t      matC,
                      cudaDataType              computeType,
                      cusparseSpSMAlg_t         alg,
                      cusparseSpSMDescr_t       spsmDescr,
                      void*                     externalBuffer)
cusparseStatus_t
cusparseSpSM_solve(cusparseHandle_t          handle,
                   cusparseOperation_t       opA,
                   cusparseOperation_t       opB,
                   const void*               alpha,
                   cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                   cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                   cusparseDnMatDescr_t      matC,
                   cudaDataType              computeType,
                   cusparseSpSMAlg_t         alg,
                   cusparseSpSMDescr_t       spsmDescr)
cusparseStatus_t
cusparseSpSM_updateMatrix(cusparseHandle_t     handle,
                          cusparseSpSMDescr_t  spsmDescr,
                          void*                newValues,
                          cusparseSpSMUpdate_t updatePart)

该函数用于求解一个线性方程组,其系数以稀疏三角矩阵的形式表示:

\[op\left( \mathbf{A} \right) \cdot \mathbf{C} = \mathbf{\alpha}op\left( \mathbf{B} \right)\]

其中

  • op(A) 是一个大小为 \(m \times m\) 的稀疏方阵

  • op(B) 是一个大小为 \(m \times n\) 的密集矩阵

  • C 是一个大小为 \(m \times n\) 的密集矩阵

  • \(\alpha\) 是一个标量

同样,对于矩阵 A

image11

image14

函数 cusparseSpSM_bufferSize() 返回 cusparseSpSM_analysis()cusparseSpSM_solve() 所需的工作空间大小。 函数 cusparseSpSM_analysis() 执行分析阶段,而 cusparseSpSM_solve() 执行稀疏三角线性系统的求解阶段。 不透明数据结构 spsmDescr 用于在所有函数之间共享信息。 函数 cusparseSpSM_updateMatrix() 使用新的矩阵值更新 spsmDescr

该例程支持输入矩阵的任意稀疏性,但在计算中仅考虑上三角或下三角部分。

cusparseSpSM_bufferSize() 需要一个缓冲区大小用于分析阶段,该大小与稀疏矩阵的非零元素数量成正比

externalBuffer被存储到spsmDescr中,并由cusparseSpSM_solve()使用。因此,设备内存缓冲区只能在cusparseSpSM_solve()执行完毕后才能释放。

注意:所有参数在cusparseSpSM API调用之间必须保持一致,且在cusparseSpSM_analysis()cusparseSpSM_solve()之间不得修改矩阵描述和externalBuffer

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

opB

主机

IN

操作 op(B)

alpha

主机或设备

IN

\(\alpha\) 用于与类型 computeType 相乘的标量

matA

主机

IN

稀疏矩阵 A

matB

主机

IN

稠密矩阵 B

matC

主机

输入/输出

稠密矩阵 C

computeType

主机

IN

执行计算所用的数据类型

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseSpSM_analysis()cusparseSpSM_solve() 所需的暂存空间字节数

externalBuffer

设备

输入/输出

指向至少bufferSize字节的工作区缓冲区的指针。它被cusparseSpSM_analysiscusparseSpSM_solve()使用

spsmDescr

主机

输入/输出

用于存储三个步骤间使用的内部数据的不透明描述符

当前支持的稀疏矩阵格式如下:

  • CUSPARSE_FORMAT_CSR

  • CUSPARSE_FORMAT_COO

cusparseSpSM() 支持以下形状和属性:

  • CUSPARSE_FILL_MODE_LOWERCUSPARSE_FILL_MODE_UPPER 填充模式

  • CUSPARSE_DIAG_TYPE_NON_UNITCUSPARSE_DIAG_TYPE_UNIT 对角线类型

填充模式和对角线类型可以通过cusparseSpMatSetAttribute()进行设置。

cusparseSpSM() 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseSpSM() 支持以下数据类型:

统一精度计算:

A/B/ C/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

cusparseSpSM() 支持以下算法:

算法

备注

CUSPARSE_SPSM_ALG_DEFAULT

默认算法

cusparseSpSM() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 为求解阶段cusparseSpSM_solve()的每次运行提供确定性(逐位)结果

  • cusparseSpSM_solve() 例程支持异步执行

  • 该例程支持原地操作。必须为稠密矩阵matBmatCvalues参数提供相同的设备指针。所有其他稠密矩阵描述符参数(例如order)可以独立设置

  • cusparseSpSM_bufferSize()cusparseSpSM_analysis() 例程接受 matBmatCNULL 值描述符。这两个例程不接受 NULL 描述符

  • 该例程允许matA的索引不排序

cusparseSpSM() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

cusparseSpSM_updateMatrix() 在调用分析阶段后更新稀疏矩阵。该函数支持以下更新策略 (updatePart):

策略

备注

CUSPARSE_SPSM_UPDATE_GENERAL

使用newValues数组中的值更新稀疏矩阵值

CUSPARSE_SPSM_UPDATE_DIAGONAL

使用存储在newValues数组中的对角线值更新矩阵的对角线部分。也就是说,newValues仅包含新的对角线值

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE Library Samples - cusparseSpSM CSRcuSPARSE Library Samples - cusparseSpSM COO查看代码示例。


6.6.11. cusparseSDDMM()

cusparseStatus_t
cusparseSDDMM_bufferSize(cusparseHandle_t          handle,
                         cusparseOperation_t       opA,
                         cusparseOperation_t       opB,
                         const void*               alpha,
                         cusparseConstDnMatDescr_t matA,  // non-const descriptor supported
                         cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                         const void*               beta,
                         cusparseSpMatDescr_t      matC,
                         cudaDataType              computeType,
                         cusparseSDDMMAlg_t        alg,
                         size_t*                   bufferSize)
cusparseStatus_t
cusparseSDDMM_preprocess(cusparseHandle_t          handle,
                         cusparseOperation_t       opA,
                         cusparseOperation_t       opB,
                         const void*               alpha,
                         cusparseConstDnMatDescr_t matA,  // non-const descriptor supported
                         cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
                         const void*               beta,
                         cusparseSpMatDescr_t      matC,
                         cudaDataType              computeType,
                         cusparseSDDMMAlg_t        alg,
                         void*                     externalBuffer)
cusparseStatus_t
cusparseSDDMM(cusparseHandle_t          handle,
              cusparseOperation_t       opA,
              cusparseOperation_t       opB,
              const void*               alpha,
              cusparseConstDnMatDescr_t matA,  // non-const descriptor supported
              cusparseConstDnMatDescr_t matB,  // non-const descriptor supported
              const void*               beta,
              cusparseSpMatDescr_t      matC,
              cudaDataType              computeType,
              cusparseSDDMMAlg_t        alg,
              void*                     externalBuffer)

该函数执行matAmatB的乘法运算,然后与matC的稀疏模式进行逐元素相乘。形式上,它执行以下操作:

\[\mathbf{C} = \alpha({op}(\mathbf{A}) \cdot {op}(\mathbf{B})) \circ {spy}(\mathbf{C}) + \beta\mathbf{C}\]

其中

  • op(A) 是一个大小为 \(m \times k\) 的稠密矩阵

  • op(B) 是一个大小为 \(k \times n\) 的稠密矩阵

  • C 是一个大小为 \(m \times n\) 的稀疏矩阵

  • \(\alpha\)\(\beta\) 是标量

  • \(\circ\) 表示哈达玛(逐元素)矩阵乘积,而 \({spy}\left( \mathbf{C} \right)C 的结构稀疏模式矩阵,其定义为:

image8

同样地,对于矩阵 AB

image13

image7

函数 cusparseSDDMM_bufferSize() 返回 cusparseSDDMMcusparseSDDMM_preprocess 所需的工作空间大小。

调用cusparseSDDMM_preprocess()是可选的。 它可以加速后续对cusparseSDDMM()的调用。 当cusparseSDDMM()需要多次使用相同的稀疏模式(matC)进行调用时,这个预处理函数会很有帮助。

使用buffer调用cusparseSDDMM_preprocess()会使该缓冲区对matC的SDDMM调用变为"活跃"状态。 后续使用matC和活跃缓冲区调用cusparseSDDMM()时,所有参数值必须与调用cusparseSDDMM_preprocess()时保持一致。 例外情况是:alphabetamatAmatB以及matC的值(但不包括索引)可以不同。 重要的是,自调用cusparseSDDMM_preprocess()以来,缓冲区内容必须保持未修改状态。 当使用matC及其活跃缓冲区调用cusparseSDDMM()时,可能会从缓冲区读取加速数据。

再次调用cusparseSDDMM_preprocess()并传入matC和新缓冲区时,将使新缓冲区处于活动状态, 同时遗忘先前活动的缓冲区并将其置为非活动状态。 对于cusparseSDDMM(),每个稀疏矩阵同一时间只能有一个活动缓冲区。 若需实现单个稀疏矩阵拥有多个活动缓冲区的效果, 可创建多个指向相同索引和值缓冲区的矩阵句柄, 然后为每个句柄调用cusparseSDDMM_preprocess()并传入不同的工作区缓冲区。

使用非活跃缓冲区调用cusparseSDDMM()始终是被允许的。但在这种情况下,预处理可能不会带来加速效果。

出于线程安全的考虑, cusparseSDDMM_preprocess()正在写入matC的内部状态。

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

opB

主机

IN

操作 op(B)

alpha

主机或设备

IN

\(\alpha\) 用于与类型 computeType 相乘的标量

matA

主机

IN

密集矩阵 matA

matB

主机

IN

稠密矩阵 matB

beta

主机或设备

IN

\(\beta\) 用于与类型 computeType 相乘的标量

matC

主机

输入/输出

稀疏矩阵 matC

computeType

主机

IN

执行计算所用的数据类型

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseSDDMM 所需的暂存空间字节数

externalBuffer

设备

IN

指向至少bufferSize字节的工作区缓冲区的指针

当前支持的稀疏矩阵格式:

  • CUSPARSE_FORMAT_CSR

  • CUSPARSE_FORMAT_BSR

cusparseSDDMM() 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

当前cusparseSDDMM支持的数据类型组合如下:

统一精度计算:

A/X/ Y/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_32F

CUDA_C_64F

混合精度计算:

A/B

C

computeType

CUDA_R_16F

CUDA_R_32F

CUDA_R_32F

CUDA_R_16F

CUDA_R_16F

cusparseSDDMM 针对 CUSPARSE_FORMAT_BSR 格式还支持以下混合精度计算:

A/B

C

computeType

CUDA_R_16BF

CUDA_R_32F

CUDA_R_32F

CUDA_R_16BF

CUDA_R_16BF

注意:CUDA_R_16FCUDA_R_16BF数据类型始终意味着混合精度计算。

cusparseSDDMM() 对于 CUSPASRE_FORMAT_BSR 格式支持2、4、8、16、32、64和128的块大小。

cusparseSDDMM() 支持以下算法:

算法

备注

CUSPARSE_SDDMM_ALG_DEFAULT

默认算法。它支持批量计算。

性能说明:当matAmatB满足以下条件时,cuspaseSDDMM()针对CUSPARSE_FORMAT_CSR格式能提供最佳性能:

  • matA:

    • matA 是行优先顺序且 opACUSPARSE_OPERATION_NON_TRANSPOSE,或者

    • matA 采用列优先存储顺序且 opA 不是 CUSPARSE_OPERATION_NON_TRANSPOSE

  • matB:

    • matB 是列优先顺序且 opBCUSPARSE_OPERATION_NON_TRANSPOSE,或者

    • matB 是行优先顺序且 opB 不是 CUSPARSE_OPERATION_NON_TRANSPOSE

cuspaseSDDMM() 针对 CUSPARSE_FORMAT_BSR 格式时,当 matAmatB 满足以下条件时可提供最佳性能:

  • matA:

    • matA 是行优先顺序且 opACUSPARSE_OPERATION_NON_TRANSPOSE,或者

    • matA 采用列优先存储顺序且 opA 不是 CUSPARSE_OPERATION_NON_TRANSPOSE

  • matB:

    • matB 是行优先顺序且 opBCUSPARSE_OPERATION_NON_TRANSPOSE,或者

    • matB 采用列优先存储顺序且 opB 不是 CUSPARSE_OPERATION_NON_TRANSPOSE

cusparseSDDMM() 支持以下批处理模式:

  • \(C_{i} = (A \cdot B) \circ C_{i}\)

  • \(C_{i} = \left( A_{i} \cdot B \right) \circ C_{i}\)

  • \(C_{i} = \left( A \cdot B_{i} \right) \circ C_{i}\)

  • \(C_{i} = \left( A_{i} \cdot B_{i} \right) \circ C_{i}\)

批处理的数量及其步长可以通过使用cusparseCsrSetStridedBatchcusparseDnMatSetStridedBatch来设置。cusparseSDDMM()的最大批处理数为65,535。

cusparseSDDMM() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 每次运行提供确定性(逐位)结果

  • 该例程支持异步执行

  • 该例程允许matC的索引不排序

cusparseSDDMM() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseSDDMM查看代码示例。如需批量计算,请访问cusparseSDDMM CSR批量处理


6.6.12. cusparseSpGEMM()

cusparseStatus_t
cusparseSpGEMM_createDescr(cusparseSpGEMMDescr_t* descr)

cusparseStatus_t
cusparseSpGEMM_destroyDescr(cusparseSpGEMMDescr_t descr)
cusparseStatus_t
cusparseSpGEMM_workEstimation(cusparseHandle_t          handle,
                              cusparseOperation_t       opA,
                              cusparseOperation_t       opB,
                              const void*               alpha,
                              cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                              cusparseConstSpMatDescr_t matB,  // non-const descriptor supported
                              const void*               beta,
                              cusparseSpMatDescr_t      matC,
                              cudaDataType              computeType,
                              cusparseSpGEMMAlg_t       alg,
                              cusparseSpGEMMDescr_t     spgemmDescr,
                              size_t*                   bufferSize1,
                              void*                     externalBuffer1)

cusparseStatus_t
cusparseSpGEMM_getNumProducts(cusparseSpGEMMDescr_t spgemmDescr,
                              int64_t*              num_prods)

cusparseStatus_t
cusparseSpGEMM_estimateMemory(cusparseHandle_t          handle,
                              cusparseOperation_t       opA,
                              cusparseOperation_t       opB,
                              const void*               alpha,
                              cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                              cusparseConstSpMatDescr_t matB,  // non-const descriptor supported
                              const void*               beta,
                              cusparseSpMatDescr_t      matC,
                              cudaDataType              computeType,
                              cusparseSpGEMMAlg_t       alg,
                              cusparseSpGEMMDescr_t     spgemmDescr,
                              float                     chunk_fraction,
                              size_t*                   bufferSize3,
                              void*                     externalBuffer3,
                              size_t*                   bufferSize2)

cusparseStatus_t
cusparseSpGEMM_compute(cusparseHandle_t          handle,
                       cusparseOperation_t       opA,
                       cusparseOperation_t       opB,
                       const void*               alpha,
                       cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                       cusparseConstSpMatDescr_t matB,  // non-const descriptor supported
                       const void*               beta,
                       cusparseSpMatDescr_t      matC,
                       cudaDataType              computeType,
                       cusparseSpGEMMAlg_t       alg,
                       cusparseSpGEMMDescr_t     spgemmDescr,
                       size_t*                   bufferSize2,
                       void*                     externalBuffer2)

cusparseStatus_t
cusparseSpGEMM_copy(cusparseHandle_t          handle,
                    cusparseOperation_t       opA,
                    cusparseOperation_t       opB,
                    const void*               alpha,
                    cusparseConstSpMatDescr_t matA,  // non-const descriptor supported
                    cusparseConstSpMatDescr_t matB,  // non-const descriptor supported
                    const void*               beta,
                    cusparseSpMatDescr_t      matC,
                    cudaDataType              computeType,
                    cusparseSpGEMMAlg_t       alg,
                    cusparseSpGEMMDescr_t     spgemmDescr)

该函数执行两个稀疏矩阵matAmatB的乘法运算。

\[\mathbf{C^{\prime}} = \alpha op\left( \mathbf{A} \right) \cdot op\left( \mathbf{B} \right) + \beta\mathbf{C}\]

其中 \(\alpha,\) \(\beta\) 为标量,且 \(\mathbf{C},\) \(\mathbf{C^{\prime}}\) 具有相同的稀疏模式。

函数 cusparseSpGEMM_workEstimation()cusparseSpGEMM_estimateMemory()cusparseSpGEMM_compute() 用于确定缓冲区大小和执行实际计算。

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

opA

主机

IN

操作 op(A)

opB

主机

IN

操作 op(B)

alpha

主机或设备

IN

\(\alpha\) 用于乘法的标量

matA

主机

IN

稀疏矩阵 A

matB

主机

IN

稀疏矩阵 B

beta

主机或设备

IN

\(\beta\) 用于乘法的标量

matC

主机

输入/输出

稀疏矩阵 C

computeType

主机

IN

指定计算执行数据类型的枚举器

alg

主机

IN

指定计算算法的枚举器

spgemmDescr

主机

输入/输出

用于存储三个步骤间使用的内部数据的不透明描述符

num_prods

主机

输出

指向64位整数的指针,用于存储由cusparseSpGEMM_workEstimation计算的中间产品数量

chunk_fraction

主机

IN

计算块中中间产物占总产出的比例。仅由CUSPARSE_SPGEMM_ALG3使用。取值范围为(0,1]。

bufferSize1

主机

输入/输出

cusparseSpGEMM_workEstimation请求的工作空间字节数

bufferSize2

主机

输入/输出

cusparseSpGEMM_compute请求的工作空间字节数

bufferSize3

主机

输入/输出

cusparseSpGEMM_estimateMemory请求的工作空间字节数

externalBuffer1

设备

IN

指向cusparseSpGEMM_workEstimationcusparseSpGEMM_compute所需工作区缓冲区的指针

externalBuffer2

设备

IN

指向cusparseSpGEMM_computecusparseSpGEMM_copy所需工作空间缓冲区的指针

externalBuffer3

设备

IN

指向cusparseSpGEMM_estimateMemory所需工作区缓冲区的指针

当前,该功能存在以下限制:

  • 仅支持32位索引 CUSPARSE_INDEX_32I

  • 仅支持CSR格式 CUSPARSE_FORMAT_CSR

  • 仅支持opAopB等于CUSPARSE_OPERATION_NON_TRANSPOSE的情况

当前cusparseSpGEMM支持的数据类型组合如下:

统一精度计算:

A/B/ C/computeType

CUDA_R_16F [已弃用]

CUDA_R_16BF [已弃用]

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

cusparseSpGEMM 例程适用于以下算法:

算法

备注

CUSPARSE_SPGEMM_DEFAULT

默认算法。当前为CUSPARSE_SPGEMM_ALG1

CUSPARSE_SPGEMM_ALG1

算法 1

  • 调用cusparseSpGEMM_compute两次。第一次调用会提供计算所需内存的上限。

  • 所需内存通常是实际使用内存的几倍大。

  • The user can provide an arbitrary buffer size bufferSize2 in the second invocation. If it is not sufficient, the routine will returns CUSPARSE_STATUS_INSUFFICIENT_RESOURCES status.

  • 相比其他算法提供更优的性能表现。

  • 每次运行提供确定性(逐位)结果。

CUSPARSE_SPGEMM_ALG2

算法 2

  • 调用 cusparseSpGEMM_estimateMemory 来获取计算所需的内存量。

  • 相比算法1,计算所需内存更少。

  • 性能低于算法1,高于算法3。

  • 每次运行都提供确定性(逐位)结果。

CUSPARSE_SPGEMM_ALG3

算法3

  • 分块计算中间产物,每次处理一个数据块。

  • 调用cusparseSpGEMM_estimateMemory来获取计算所需的内存量。

  • 用户可以通过调整chunk_fraction参数来控制所需内存的大小。

  • 块大小是中间产物总量的一部分:chunk_fraction * (*num_prods)

  • 每次运行提供确定性(逐位)结果。

cusparseSpGEMM() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 该例程允许matAmatB的索引不排序

  • 该例程保证matC的索引是有序的

cusparseSpGEMM() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseSpGEMM查看CUSPARSE_SPGEMM_DEFAULTCUSPARSE_SPGEMM_ALG1的代码示例,以及访问cuSPARSE库示例 - 内存优化的cusparseSpGEMM查看CUSPARSE_SPGEMM_ALG2CUSPARSE_SPGEMM_ALG3的代码示例。


6.6.13. cusparseSpGEMMreuse()

cusparseStatus_t
cusparseSpGEMM_createDescr(cusparseSpGEMMDescr_t* descr)

cusparseStatus_t
cusparseSpGEMM_destroyDescr(cusparseSpGEMMDescr_t descr)
cusparseStatus_t
cusparseSpGEMMreuse_workEstimation(cusparseHandle_t      handle,
                                   cusparseOperation_t   opA,
                                   cusparseOperation_t   opB,
                                   cusparseSpMatDescr_t  matA,  // non-const descriptor supported
                                   cusparseSpMatDescr_t  matB,  // non-const descriptor supported
                                   cusparseSpMatDescr_t  matC,
                                   cusparseSpGEMMAlg_t   alg,
                                   cusparseSpGEMMDescr_t spgemmDescr,
                                   size_t*               bufferSize1,
                                   void*                 externalBuffer1)

cusparseStatus_t
cusparseSpGEMMreuse_nnz(cusparseHandle_t      handle,
                        cusparseOperation_t   opA,
                        cusparseOperation_t   opB,
                        cusparseSpMatDescr_t  matA,  // non-const descriptor supported
                        cusparseSpMatDescr_t  matB,  // non-const descriptor supported
                        cusparseSpMatDescr_t  matC,
                        cusparseSpGEMMAlg_t   alg,
                        cusparseSpGEMMDescr_t spgemmDescr,
                        size_t*               bufferSize2,
                        void*                 externalBuffer2,
                        size_t*               bufferSize3,
                        void*                 externalBuffer3,
                        size_t*               bufferSize4,
                        void*                 externalBuffer4)

cusparseStatus_t CUSPARSEAPI
cusparseSpGEMMreuse_copy(cusparseHandle_t      handle,
                         cusparseOperation_t   opA,
                         cusparseOperation_t   opB,
                         cusparseSpMatDescr_t  matA,  // non-const descriptor supported
                         cusparseSpMatDescr_t  matB,  // non-const descriptor supported
                         cusparseSpMatDescr_t  matC,
                         cusparseSpGEMMAlg_t   alg,
                         cusparseSpGEMMDescr_t spgemmDescr,
                         size_t*               bufferSize5,
                         void*                 externalBuffer5)

cusparseStatus_t CUSPARSEAPI
cusparseSpGEMMreuse_compute(cusparseHandle_t      handle,
                            cusparseOperation_t   opA,
                            cusparseOperation_t   opB,
                            const void*           alpha,
                            cusparseSpMatDescr_t  matA,  // non-const descriptor supported
                            cusparseSpMatDescr_t  matB,  // non-const descriptor supported
                            const void*           beta,
                            cusparseSpMatDescr_t  matC,
                            cudaDataType          computeType,
                            cusparseSpGEMMAlg_t   alg,
                            cusparseSpGEMMDescr_t spgemmDescr)

该函数执行两个稀疏矩阵matAmatB的乘法运算,其中输出矩阵matC的结构可重复用于不同值的多次计算。

\[\mathbf{C^{\prime}} = \alpha op\left( \mathbf{A} \right) \cdot op\left( \mathbf{B} \right) + \beta\mathbf{C}\]

其中 \(\alpha\)\(\beta\) 是标量。

函数 cusparseSpGEMMreuse_workEstimation()cusparseSpGEMMreuse_nnz()cusparseSpGEMMreuse_copy() 用于确定缓冲区大小并执行实际计算。

注意:cusparseSpGEMMreuse()输出的CSR矩阵(matC)是按列索引排序的。

内存需求:cusparseSpGEMMreuse需要将所有中间结果保留在内存中以复用输出矩阵的结构。另一方面,中间结果的数量通常比非零元素的数量高出几个数量级。为了最小化内存需求,该例程使用多个缓冲区,这些缓冲区在不再需要后可以被释放。如果中间结果的数量超过2^31-1,该例程将返回CUSPARSE_STATUS_INSUFFICIENT_RESOURCES状态。

当前,该功能存在以下限制:

  • 仅支持32位索引 CUSPARSE_INDEX_32I

  • 仅支持CSR格式 CUSPARSE_FORMAT_CSR

  • 仅支持 opAopB 等于 CUSPARSE_OPERATION_NON_TRANSPOSE 的情况

当前cusparseSpGEMMreuse支持的数据类型组合如下所示。

统一精度计算:

A/B/ C/computeType

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

混合精度计算:[已弃用]

A/B

C

computeType

CUDA_R_16F

CUDA_R_16F

CUDA_R_32F

CUDA_R_16BF

CUDA_R_16BF

CUDA_R_32F

cusparseSpGEMMreuse 例程适用于以下算法:

算法

备注

CUSPARSE_SPGEMM_DEFAULT

CUSPARSE_SPGEMM_CSR_ALG_NONDETERMINITIC

默认算法。为每次运行的输出矩阵提供确定性(按位)结构,但数值计算不具有确定性。

CUSPARSE_SPGEMM_CSR_ALG_DETERMINITIC

为输出矩阵和每次运行的值计算提供确定性(逐位)结构。

cusparseSpGEMMreuse() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 该例程允许matAmatB的索引不排序

  • 该例程保证matC的索引会被排序

cusparseSpGEMMreuse() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参考cusparseStatus_t

请访问cuSPARSE库示例 - cusparseSpGEMMreuse查看代码示例。


6.6.14. cusparseSparseToDense()

cusparseStatus_t
cusparseSparseToDense_bufferSize(cusparseHandle_t           handle,
                                 cusparseConstSpMatDescr_t  matA,  // non-const descriptor supported
                                 cusparseDnMatDescr_t       matB,
                                 cusparseSparseToDenseAlg_t alg,
                                 size_t*                    bufferSize)
cusparseStatus_t
cusparseSparseToDense(cusparseHandle_t           handle,
                      cusparseConstSpMatDescr_t  matA,  // non-const descriptor supported
                      cusparseDnMatDescr_t       matB,
                      cusparseSparseToDenseAlg_t alg,
                      void*                      buffer)

该函数将CSR、CSC或COO格式的稀疏矩阵matA转换为其密集表示形式matB。目前不支持Blocked-ELL格式。

函数 cusparseSparseToDense_bufferSize() 返回 cusparseSparseToDense() 所需工作空间的大小。

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

matA

主机

IN

稀疏矩阵 A

matB

主机

输出

稠密矩阵 B

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseSparseToDense() 所需的暂存空间字节数

buffer

设备

IN

指向工作区缓冲区的指针

cusparseSparseToDense() 支持以下索引类型来表示稀疏矩阵 matA

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseSparseToDense() 支持以下数据类型:

A/B

CUDA_R_8I

CUDA_R_16F

CUDA_R_16BF

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

cusparseSparse2Dense() 支持以下算法:

算法

备注

CUSPARSE_SPARSETODENSE_ALG_DEFAULT

默认算法

cusparseSparseToDense() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 每次运行提供确定性(逐位)结果

  • 该例程允许matA的索引不排序

cusparseSparseToDense() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE库示例 - cusparseSparseToDense查看代码示例。


6.6.15. cusparseDenseToSparse()

cusparseStatus_t
cusparseDenseToSparse_bufferSize(cusparseHandle_t           handle,
                                 cusparseConstDnMatDescr_t  matA,  // non-const descriptor supported
                                 cusparseSpMatDescr_t       matB,
                                 cusparseDenseToSparseAlg_t alg,
                                 size_t*                    bufferSize)
cusparseStatus_t
cusparseDenseToSparse_analysis(cusparseHandle_t           handle,
                               cusparseConstDnMatDescr_t  matA,  // non-const descriptor supported
                               cusparseSpMatDescr_t       matB,
                               cusparseDenseToSparseAlg_t alg,
                               void*                      buffer)
cusparseStatus_t
cusparseDenseToSparse_convert(cusparseHandle_t           handle,
                              cusparseConstDnMatDescr_t  matA,  // non-const descriptor supported
                              cusparseSpMatDescr_t       matB,
                              cusparseDenseToSparseAlg_t alg,
                              void*                      buffer)

该函数将稠密矩阵matA转换为CSR、CSC、COO或Blocked-ELL格式的稀疏矩阵matB

函数 cusparseDenseToSparse_bufferSize() 返回 cusparseDenseToSparse_analysis() 所需工作空间的大小。

函数 cusparseDenseToSparse_analysis() 会更新稀疏矩阵描述符 matB 中的非零元素数量。用户需要负责分配稀疏矩阵所需的内存:

  • CSC和CSR格式对应的行/列索引及数值数组

  • COO格式的行、列、值数组

  • Blocked-ELL格式的列索引数组 (ellColInd) 和值数组 (ellValue)

最后,我们调用cusparseDenseToSparse_convert()来填充上一步骤中分配的数组。

参数

内存

输入/输出

含义

handle

主机

IN

cuSPARSE库上下文的句柄

matA

主机

IN

稠密矩阵 A

matB

主机

输出

稀疏矩阵 B

alg

主机

IN

计算算法

bufferSize

主机

输出

cusparseDenseToSparse_analysis() 所需的暂存空间字节数

buffer

设备

IN

指向工作区缓冲区的指针

cusparseDenseToSparse() 支持以下索引类型来表示稀疏向量 matB

  • 32位索引 (CUSPARSE_INDEX_32I)

  • 64位索引 (CUSPARSE_INDEX_64I)

cusparseDenseToSparse() 支持以下数据类型:

A/B

CUDA_R_*8I

CUDA_R_16F

CUDA_R_16BF

CUDA_R_32F

CUDA_R_64F

CUDA_C_16F [已弃用]

CUDA_C_16BF [已弃用]

CUDA_C_32F

CUDA_C_64F

cusparseDense2Sparse() 支持以下算法:

算法

备注

CUSPARSE_DENSETOSPARSE_ALG_DEFAULT

默认算法

cusparseDenseToSparse() 具有以下特性:

  • 该例程不需要额外的存储空间

  • 该例程支持异步执行

  • 每次运行提供确定性(逐位)结果

  • 该例程不保证matB的索引会被排序

cusparseDenseToSparse() 支持以下 优化

  • CUDA图捕获

  • 硬件内存压缩

有关返回状态的描述,请参见cusparseStatus_t

请访问cuSPARSE Library Samples - cusparseDenseToSparse (CSR)cuSPARSE Library Samples - cusparseDenseToSparse (Blocked-ELL)查看代码示例。



7. cuSPARSE Fortran接口绑定

cuSPARSE库是基于C语言的CUDA工具链实现的,因此它提供了C风格的API,可以轻松与用C或C++编写的应用程序对接。还有许多用Fortran实现的应用程序也能受益于使用cuSPARSE,因此我们还开发了cuSPARSE的Fortran接口。

遗憾的是,Fortran调用C的约定并未标准化,且因平台和工具链而异。具体差异可能体现在以下方面:

  • 符号名称(大小写、名称修饰)

  • 参数传递(按值或按引用)

  • 传递指针参数(指针的大小)

为了在处理这些差异时提供最大的灵活性,cuSPARSE Fortran接口以包装函数的形式提供,这些函数用C语言编写并位于文件cusparse_fortran.c中。该文件还包含一些额外的包装函数(用于cudaMalloc()cudaMemset等),可用于在GPU上分配内存。

cuSPARSE Fortran封装代码仅作为示例提供,需要编译成应用程序才能调用cuSPARSE API函数。提供此源代码使用户能够针对特定平台和工具链进行必要的修改。

cuSPARSE Fortran封装代码已被用于展示与g95 0.91(在32位和64位Linux上)和g95 0.92(在32位和64位Mac OS X上)编译器的互操作性。为了使用其他编译器,用户可能需要对封装代码进行必要的修改。

直接封装的包装器专为生产代码设计,在所有cuSPARSE函数中用设备指针替代向量和矩阵参数。要使用这些接口,现有应用需要稍作修改:在GPU内存空间中分配和释放数据结构(使用CUDA_MALLOC()CUDA_FREE()),并在GPU与CPU内存空间之间复制数据(使用CUDA_MEMCPY()例程)。cusparse_fortran.c中提供的示例包装器将设备指针映射到与操作系统相关的size_t类型,该类型在32位平台上为32位宽,在64位平台上为64位宽。

在Fortran代码中处理设备指针索引运算的一种方法是使用C风格的宏,并利用C预处理器来展开它们。在Linux和Mac OS X系统上,可以通过在g95或gfortran中使用'-cpp'选项进行预处理。如示例B所示,也可以使用cuSPARSE Fortran封装中提供的GET_SHIFTED_ADDRESS()函数。

示例B展示了在主机上用Fortran 77实现的示例A的C++代码。此示例应在64位操作系统上编译时将ARCH_64定义为1,在32位操作系统上则保持未定义状态。例如,在使用g95或gfortran时,可以直接在命令行使用选项-cpp -DARCH_64=1来完成此操作。

7.1. Fortran应用程序

c     #define ARCH_64 0
c     #define ARCH_64 1

      program cusparse_fortran_example
      implicit none
      integer cuda_malloc
      external cuda_free
      integer cuda_memcpy_c2fort_int
      integer cuda_memcpy_c2fort_real
      integer cuda_memcpy_fort2c_int
      integer cuda_memcpy_fort2c_real
      integer cuda_memset
      integer cusparse_create
      external cusparse_destroy
      integer cusparse_get_version
      integer cusparse_create_mat_descr
      external cusparse_destroy_mat_descr
      integer cusparse_set_mat_type
      integer cusparse_get_mat_type
      integer cusparse_get_mat_fill_mode
      integer cusparse_get_mat_diag_type
      integer cusparse_set_mat_index_base
      integer cusparse_get_mat_index_base
      integer cusparse_xcoo2csr
      integer cusparse_dsctr
      integer cusparse_dcsrmv
      integer cusparse_dcsrmm
      external get_shifted_address
#if ARCH_64
      integer*8 handle
      integer*8 descrA
      integer*8 cooRowIndex
      integer*8 cooColIndex
      integer*8 cooVal
      integer*8 xInd
      integer*8 xVal
      integer*8 y
      integer*8 z
      integer*8 csrRowPtr
      integer*8 ynp1
#else
      integer*4 handle
      integer*4 descrA
      integer*4 cooRowIndex
      integer*4 cooColIndex
      integer*4 cooVal
      integer*4 xInd
      integer*4 xVal
      integer*4 y
      integer*4 z
      integer*4 csrRowPtr
      integer*4 ynp1
#endif
      integer status
      integer cudaStat1,cudaStat2,cudaStat3
      integer cudaStat4,cudaStat5,cudaStat6
      integer n, nnz, nnz_vector
      parameter (n=4, nnz=9, nnz_vector=3)
      integer cooRowIndexHostPtr(nnz)
      integer cooColIndexHostPtr(nnz)
      real*8  cooValHostPtr(nnz)
      integer xIndHostPtr(nnz_vector)
      real*8  xValHostPtr(nnz_vector)
      real*8  yHostPtr(2*n)
      real*8  zHostPtr(2*(n+1))
      integer i, j
      integer version, mtype, fmode, dtype, ibase
      real*8  dzero,dtwo,dthree,dfive
      real*8  epsilon


      write(*,*) "testing fortran example"

c     predefined constants (need to be careful with them)
      dzero = 0.0
      dtwo  = 2.0
      dthree= 3.0
      dfive = 5.0
c     create the following sparse test matrix in COO format
c     (notice one-based indexing)
c     |1.0     2.0 3.0|
c     |    4.0        |
c     |5.0     6.0 7.0|
c     |    8.0     9.0|
      cooRowIndexHostPtr(1)=1
      cooColIndexHostPtr(1)=1
      cooValHostPtr(1)     =1.0
      cooRowIndexHostPtr(2)=1
      cooColIndexHostPtr(2)=3
      cooValHostPtr(2)     =2.0
      cooRowIndexHostPtr(3)=1
      cooColIndexHostPtr(3)=4
      cooValHostPtr(3)     =3.0
      cooRowIndexHostPtr(4)=2
      cooColIndexHostPtr(4)=2
      cooValHostPtr(4)     =4.0
      cooRowIndexHostPtr(5)=3
      cooColIndexHostPtr(5)=1
      cooValHostPtr(5)     =5.0
      cooRowIndexHostPtr(6)=3
      cooColIndexHostPtr(6)=3
      cooValHostPtr(6)     =6.0
      cooRowIndexHostPtr(7)=3
      cooColIndexHostPtr(7)=4
      cooValHostPtr(7)     =7.0
      cooRowIndexHostPtr(8)=4
      cooColIndexHostPtr(8)=2
      cooValHostPtr(8)     =8.0
      cooRowIndexHostPtr(9)=4
      cooColIndexHostPtr(9)=4
      cooValHostPtr(9)     =9.0
c     print the matrix
      write(*,*) "Input data:"
      do i=1,nnz
         write(*,*) "cooRowIndexHostPtr[",i,"]=",cooRowIndexHostPtr(i)
         write(*,*) "cooColIndexHostPtr[",i,"]=",cooColIndexHostPtr(i)
         write(*,*) "cooValHostPtr[",     i,"]=",cooValHostPtr(i)
      enddo

c     create a sparse and dense vector
c     xVal= [100.0 200.0 400.0]   (sparse)
c     xInd= [0     1     3    ]
c     y   = [10.0 20.0 30.0 40.0 | 50.0 60.0 70.0 80.0] (dense)
c     (notice one-based indexing)
      yHostPtr(1) = 10.0
      yHostPtr(2) = 20.0
      yHostPtr(3) = 30.0
      yHostPtr(4) = 40.0
      yHostPtr(5) = 50.0
      yHostPtr(6) = 60.0
      yHostPtr(7) = 70.0
      yHostPtr(8) = 80.0
      xIndHostPtr(1)=1
      xValHostPtr(1)=100.0
      xIndHostPtr(2)=2
      xValHostPtr(2)=200.0
      xIndHostPtr(3)=4
      xValHostPtr(3)=400.0
c     print the vectors
      do j=1,2
         do i=1,n
            write(*,*) "yHostPtr[",i,",",j,"]=",yHostPtr(i+n*(j-1))
         enddo
      enddo
      do i=1,nnz_vector
         write(*,*) "xIndHostPtr[",i,"]=",xIndHostPtr(i)
         write(*,*) "xValHostPtr[",i,"]=",xValHostPtr(i)
      enddo

c     allocate GPU memory and copy the matrix and vectors into it
c     cudaSuccess=0
c     cudaMemcpyHostToDevice=1
      cudaStat1 = cuda_malloc(cooRowIndex,nnz*4)
      cudaStat2 = cuda_malloc(cooColIndex,nnz*4)
      cudaStat3 = cuda_malloc(cooVal,     nnz*8)
      cudaStat4 = cuda_malloc(y,          2*n*8)
      cudaStat5 = cuda_malloc(xInd,nnz_vector*4)
      cudaStat6 = cuda_malloc(xVal,nnz_vector*8)
      if ((cudaStat1 /= 0) .OR.
     $    (cudaStat2 /= 0) .OR.
     $    (cudaStat3 /= 0) .OR.
     $    (cudaStat4 /= 0) .OR.
     $    (cudaStat5 /= 0) .OR.
     $    (cudaStat6 /= 0)) then
         write(*,*) "Device malloc failed"
         write(*,*) "cudaStat1=",cudaStat1
         write(*,*) "cudaStat2=",cudaStat2
         write(*,*) "cudaStat3=",cudaStat3
         write(*,*) "cudaStat4=",cudaStat4
         write(*,*) "cudaStat5=",cudaStat5
         write(*,*) "cudaStat6=",cudaStat6
         stop 2
      endif
      cudaStat1 = cuda_memcpy_fort2c_int(cooRowIndex,cooRowIndexHostPtr,
     $                                   nnz*4,1)
      cudaStat2 = cuda_memcpy_fort2c_int(cooColIndex,cooColIndexHostPtr,
     $                                   nnz*4,1)
      cudaStat3 = cuda_memcpy_fort2c_real(cooVal,    cooValHostPtr,
     $                                    nnz*8,1)
      cudaStat4 = cuda_memcpy_fort2c_real(y,      yHostPtr,
     $                                    2*n*8,1)
      cudaStat5 = cuda_memcpy_fort2c_int(xInd,       xIndHostPtr,
     $                                   nnz_vector*4,1)
      cudaStat6 = cuda_memcpy_fort2c_real(xVal,      xValHostPtr,
     $                                    nnz_vector*8,1)
      if ((cudaStat1 /= 0) .OR.
     $    (cudaStat2 /= 0) .OR.
     $    (cudaStat3 /= 0) .OR.
     $    (cudaStat4 /= 0) .OR.
     $    (cudaStat5 /= 0) .OR.
     $    (cudaStat6 /= 0)) then
         write(*,*) "Memcpy from Host to Device failed"
         write(*,*) "cudaStat1=",cudaStat1
         write(*,*) "cudaStat2=",cudaStat2
         write(*,*) "cudaStat3=",cudaStat3
         write(*,*) "cudaStat4=",cudaStat4
         write(*,*) "cudaStat5=",cudaStat5
         write(*,*) "cudaStat6=",cudaStat6
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         stop 1
      endif

c     initialize cusparse library
c     CUSPARSE_STATUS_SUCCESS=0
      status = cusparse_create(handle)
      if (status /= 0) then
         write(*,*) "CUSPARSE Library initialization failed"
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         stop 1
      endif
c     get version
c     CUSPARSE_STATUS_SUCCESS=0
      status = cusparse_get_version(handle,version)
      if (status /= 0) then
         write(*,*) "CUSPARSE Library initialization failed"
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cusparse_destroy(handle)
         stop 1
      endif
      write(*,*) "CUSPARSE Library version",version

c     create and setup the matrix descriptor
c     CUSPARSE_STATUS_SUCCESS=0
c     CUSPARSE_MATRIX_TYPE_GENERAL=0
c     CUSPARSE_INDEX_BASE_ONE=1
      status= cusparse_create_mat_descr(descrA)
      if (status /= 0) then
         write(*,*) "Creating matrix descriptor failed"
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cusparse_destroy(handle)
         stop 1
      endif
      status = cusparse_set_mat_type(descrA,0)
      status = cusparse_set_mat_index_base(descrA,1)
c     print the matrix descriptor
      mtype = cusparse_get_mat_type(descrA)
      fmode = cusparse_get_mat_fill_mode(descrA)
      dtype = cusparse_get_mat_diag_type(descrA)
      ibase = cusparse_get_mat_index_base(descrA)
      write (*,*) "matrix descriptor:"
      write (*,*) "t=",mtype,"m=",fmode,"d=",dtype,"b=",ibase

c     exercise conversion routines (convert matrix from COO 2 CSR format)
c     cudaSuccess=0
c     CUSPARSE_STATUS_SUCCESS=0
c     CUSPARSE_INDEX_BASE_ONE=1
      cudaStat1 = cuda_malloc(csrRowPtr,(n+1)*4)
      if (cudaStat1 /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Device malloc failed (csrRowPtr)"
         stop 2
      endif
      status= cusparse_xcoo2csr(handle,cooRowIndex,nnz,n,
     $                          csrRowPtr,1)
      if (status /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Conversion from COO to CSR format failed"
         stop 1
      endif
c     csrRowPtr = [0 3 4 7 9]

c     exercise Level 1 routines (scatter vector elements)
c     CUSPARSE_STATUS_SUCCESS=0
c     CUSPARSE_INDEX_BASE_ONE=1
      call get_shifted_address(y,n*8,ynp1)
      status= cusparse_dsctr(handle, nnz_vector, xVal, xInd,
     $                       ynp1, 1)
      if (status /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Scatter from sparse to dense vector failed"
         stop 1
      endif
c     y = [10 20 30 40 | 100 200 70 400]

c     exercise Level 2 routines (csrmv)
c     CUSPARSE_STATUS_SUCCESS=0
c     CUSPARSE_OPERATION_NON_TRANSPOSE=0
      status= cusparse_dcsrmv(handle, 0, n, n, nnz, dtwo,
     $                       descrA, cooVal, csrRowPtr, cooColIndex,
     $                       y, dthree, ynp1)
      if (status /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Matrix-vector multiplication failed"
         stop 1
      endif

c     print intermediate results (y)
c     y = [10 20 30 40 | 680 760 1230 2240]
c     cudaSuccess=0
c     cudaMemcpyDeviceToHost=2
      cudaStat1 = cuda_memcpy_c2fort_real(yHostPtr, y, 2*n*8, 2)
      if (cudaStat1 /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Memcpy from Device to Host failed"
         stop 1
      endif
      write(*,*) "Intermediate results:"
      do j=1,2
         do i=1,n
             write(*,*) "yHostPtr[",i,",",j,"]=",yHostPtr(i+n*(j-1))
         enddo
      enddo

c     exercise Level 3 routines (csrmm)
c     cudaSuccess=0
c     CUSPARSE_STATUS_SUCCESS=0
c     CUSPARSE_OPERATION_NON_TRANSPOSE=0
      cudaStat1 = cuda_malloc(z, 2*(n+1)*8)
      if (cudaStat1 /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Device malloc failed (z)"
         stop 2
      endif
      cudaStat1 = cuda_memset(z, 0, 2*(n+1)*8)
      if (cudaStat1 /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(z)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Memset on Device failed"
         stop 1
      endif
      status= cusparse_dcsrmm(handle, 0, n, 2, n, nnz, dfive,
     $                        descrA, cooVal, csrRowPtr, cooColIndex,
     $                        y, n, dzero, z, n+1)
      if (status /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(z)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Matrix-matrix multiplication failed"
         stop 1
      endif

c     print final results (z)
c     cudaSuccess=0
c     cudaMemcpyDeviceToHost=2
      cudaStat1 = cuda_memcpy_c2fort_real(zHostPtr, z, 2*(n+1)*8, 2)
      if (cudaStat1 /= 0) then
         call cuda_free(cooRowIndex)
         call cuda_free(cooColIndex)
         call cuda_free(cooVal)
         call cuda_free(xInd)
         call cuda_free(xVal)
         call cuda_free(y)
         call cuda_free(z)
         call cuda_free(csrRowPtr)
         call cusparse_destroy_mat_descr(descrA)
         call cusparse_destroy(handle)
         write(*,*) "Memcpy from Device to Host failed"
         stop 1
      endif
c     z = [950 400 2550 2600 0 | 49300 15200 132300 131200 0]
      write(*,*) "Final results:"
      do j=1,2
         do i=1,n+1
            write(*,*) "z[",i,",",j,"]=",zHostPtr(i+(n+1)*(j-1))
         enddo
      enddo

c     check the results
      epsilon = 0.00000000000001
      if ((DABS(zHostPtr(1) - 950.0)   .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(2) - 400.0)   .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(3) - 2550.0)  .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(4) - 2600.0)  .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(5) - 0.0)     .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(6) - 49300.0) .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(7) - 15200.0) .GT. epsilon)  .OR.
     $    (DABS(zHostPtr(8) - 132300.0).GT. epsilon)  .OR.
     $    (DABS(zHostPtr(9) - 131200.0).GT. epsilon)  .OR.
     $    (DABS(zHostPtr(10) - 0.0)    .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(1) - 10.0)    .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(2) - 20.0)    .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(3) - 30.0)    .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(4) - 40.0)    .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(5) - 680.0)   .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(6) - 760.0)   .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(7) - 1230.0)  .GT. epsilon)  .OR.
     $    (DABS(yHostPtr(8) - 2240.0)  .GT. epsilon)) then
          write(*,*) "fortran example test FAILED"
       else
          write(*,*) "fortran example test PASSED"
       endif

c      deallocate GPU memory and exit
       call cuda_free(cooRowIndex)
       call cuda_free(cooColIndex)
       call cuda_free(cooVal)
       call cuda_free(xInd)
       call cuda_free(xVal)
       call cuda_free(y)
       call cuda_free(z)
       call cuda_free(csrRowPtr)
       call cusparse_destroy_mat_descr(descrA)
       call cusparse_destroy(handle)

       stop 0
       end

8. 致谢

NVIDIA 谨此感谢以下个人和机构所作出的贡献:

  • cusparsegtsv 的实现源自伊利诺伊大学李雯(Li-Wen Chang)开发的版本。

  • cusparsegtsvInterleavedBatch采用了由巴塞罗那超级计算中心和BSC/UPC NVIDIA GPU卓越中心的Pedro Valero-Lara与Ivan Martínez-Pérez开发的cuThomasBatch。

  • 本产品包含 {fmt} - 一个现代化的格式化库 https://fmt.dev 版权所有 (c) 2012 - 至今,Victor Zverovich。

9. 参考文献

[1] N. Bell 和 M. Garland, 《面向吞吐量处理器的稀疏矩阵向量乘法实现》, 超级计算会议, 2009年。

[2] R. Grimes, D. Kincaid, 和 D. Young, "ITPACK 2.0 用户指南", 技术报告 CNA-150, 德克萨斯大学数值分析中心, 1979.

[3] M. Naumov, “使用cuSPARSE和cuBLAS实现的不完全LU分解与Cholesky预处理迭代方法”, 技术报告与白皮书, 2011年.

[4] Pedro Valero-Lara, Ivan Martínez-Pérez, Raül Sirvent, Xavier Martorell, 和 Antonio J. Peña。NVIDIA GPU在求解多重(批量)三对角系统时的可扩展性。cuThomasBatch的实现。收录于第12届国际并行处理与应用数学会议(PPAM),2017年。

10. 通知

10.1. 通知

本文档仅供信息参考之用,不应视为对产品功能、状态或质量的保证。NVIDIA公司(“NVIDIA”)对本文件所含信息的准确性或完整性不作任何明示或暗示的陈述或保证,并对其中可能存在的错误不承担任何责任。NVIDIA对于因使用此类信息而产生的后果、或因使用该信息导致的第三方专利或其他权利侵权概不负责。本文件不构成对开发、发布或交付任何材料(定义见下文)、代码或功能的承诺。

NVIDIA保留随时对本文件进行更正、修改、增强、改进以及任何其他变更的权利,恕不另行通知。

客户在下单前应获取最新的相关信息,并确认这些信息是最新且完整的。

除非NVIDIA与客户授权代表签署的单独销售协议中另有约定,否则NVIDIA产品的销售均以订单确认时提供的NVIDIA标准销售条款和条件为准(以下简称"销售条款")。NVIDIA特此明确反对将任何客户通用条款适用于本文件所述NVIDIA产品的采购。本文件不直接或间接构成任何合同义务。

NVIDIA产品并非设计、授权或保证适用于医疗、军事、航空、航天或生命支持设备,也不适用于那些可以合理预期NVIDIA产品故障或失灵会导致人身伤害、死亡、财产或环境损害的应用场景。NVIDIA对于在此类设备或应用中使用和/或包含NVIDIA产品不承担任何责任,因此客户需自行承担相关风险。

NVIDIA不声明或保证基于本文档的产品适用于任何特定用途。NVIDIA未必会对每个产品的所有参数进行测试。客户应全权负责评估和确定本文档所含信息的适用性,确保产品适合并满足客户计划的应用需求,并执行必要的应用测试以避免应用或产品出现故障。客户产品设计中的缺陷可能会影响NVIDIA产品的质量和可靠性,并可能导致超出本文档范围的其他或不同的条件和/或要求。对于任何因以下原因导致的故障、损坏、成本或问题,NVIDIA不承担任何责任:(i) 以违反本文档的任何方式使用NVIDIA产品或(ii) 客户产品设计。

本文档不授予任何NVIDIA专利权、版权或其他NVIDIA知识产权的明示或暗示许可。NVIDIA发布的关于第三方产品或服务的信息,不构成NVIDIA对这些产品或服务的使用许可或担保认可。使用此类信息可能需要获得第三方基于其专利或其他知识产权的许可,或需要获得NVIDIA基于其专利或其他知识产权的许可。

本文件中的信息仅可在获得NVIDIA事先书面批准、未经改动完整复制且完全符合所有适用的出口法律法规,并附带所有相关条件、限制和声明的情况下进行复制。

本文件及所有NVIDIA设计规格、参考板、文件、图纸、诊断工具、清单和其他文档(统称及单独称为"材料")均以"现状"提供。NVIDIA不对材料作出任何明示或默示的保证,包括但不限于对不侵权、适销性和特定用途适用性的默示保证免责。在法律允许的最大范围内,NVIDIA不就因使用本文件导致的任何损害承担责任,包括但不限于任何直接、间接、特殊、附带、惩罚性或后果性损害,无论损害成因如何,也无论责任理论为何,即使NVIDIA已被告知发生此类损害的可能性。不论客户因任何原因可能遭受的任何损害,NVIDIA对客户就本文所述产品的全部及累计责任应受产品销售条款的限制。

10.2. OpenCL

OpenCL是苹果公司的商标,经Khronos Group Inc.授权使用。

10.3. 商标

NVIDIA和NVIDIA标识是美国及其他国家NVIDIA公司的商标或注册商标。其他公司及产品名称可能是其各自关联公司的商标。