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++编译器。根据主机操作系统的不同,在链接行可能需要一些额外的库,如pthread或dl。在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()例程,通过分别指定cudaMemcpyDeviceToHost和cudaMemcpyHostToDevice参数,将数据从设备复制到主机或反之。在这种情况下,无需额外调用cudaDeviceSynchronize(),因为使用上述参数的cudaMemcpy()调用是阻塞式的,只有当结果在主机端准备就绪时才会完成。
2.2. 已弃用的API
cuSPARSE库文档明确标注了已弃用的API/枚举器/数据结构集合。对于已弃用的API,该库遵循以下策略:
-
API在X.Y版本(例如11.2)上被标记为
[[DEPRECATED]]如果有可用的替代方案,文档会进行索引
否则,该功能在未来将不会被维护
该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\)稠密向量。
密集向量表示
3.2.2. 稀疏向量格式
稀疏向量用两个数组表示。
values数组存储了密集格式等效数组中的非零值。
indices数组表示对应的非零值在密集格式等效数组中的位置。
例如,3.2.1节中的密集向量可以存储为使用从零开始或从一开始索引的稀疏向量。
稀疏向量表示
注意
cuSPARSE例程假设索引是按递增顺序提供的,并且每个索引仅出现一次。在相反的情况下,计算的正确性并不总是能得到保证。
3.3. 矩阵格式
本节将讨论矩阵的密集格式和几种稀疏格式。
3.3.1. 稠密矩阵格式
密集矩阵可以存储在行优先和列优先的内存布局(排序)中,它由以下参数表示。
矩阵中的行数。
矩阵中的列数。
-
主维度必须满足
大于或等于行优先布局中的列数
大于或等于列优先布局中的行数
-
指向长度为值数组的指针
\(rows \times leading\; dimension\) 在行优先布局中
\(columns \times leading\; dimension\) 在列优先布局中
下图展示了一个\(5 \times 2\)密集矩阵的两种内存布局方式
稠密矩阵表示
矩阵中的索引表示内存中的连续位置。
前导维度有助于表示原始矩阵中的一个子矩阵
子矩阵表示
3.3.2. 坐标格式 (COO)
以COO格式存储的稀疏矩阵由以下参数表示。
矩阵中的行数。
矩阵中的列数。
矩阵中的非零元素数量 (
nnz)。指向长度为
nnz的行索引数组的指针,该数组包含值数组中对应元素的行索引。指向长度为
nnz的列索引数组的指针,该数组包含值数组中对应元素的列索引。指向长度为
nnz的值数组的指针,该数组以行优先顺序存储矩阵的所有非零值。COO表示法中的每个条目由一个
<行, 列>对组成。COO格式假定为按行排序。
以下示例展示了一个以COO格式表示的\(5 \times 4\)矩阵。
注意
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\)矩阵。
注意
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的行索引数组的指针,该数组包含值数组中对应元素的行索引。指向长度为
nnz的values数组的指针,该数组以列主序存储矩阵的所有非零值。
以下示例展示了一个以CSC格式表示的\(5 \times 4\)矩阵。
注意
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表示填充。指向长度为
sellValuesSize的values数组的指针,该数组以列优先布局保存所有非零值和填充。
以下示例展示了一个以SELL格式表示的\(5 \times 4\)矩阵。
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\)矩阵。
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\)矩阵。
3.3.8. 扩展BSR格式(BSRX) [已弃用]
BSRX格式与BSR格式类似,但数组bsrRowPtrA被分为两部分。每行的第一个非零块仍由数组bsrRowPtrA指定(与BSR格式相同),但每行最后一个非零块的下一个位置由数组bsrEndPtrA指定。简而言之,BSRX格式就像是BSR格式的四向量变体。
矩阵 A 通过以下参数以BSRX格式表示。
|
(整数) |
矩阵 |
|
(整数) |
|
|
(整数) |
|
|
(整数) |
矩阵 |
|
(指针) |
指向长度为\(nnzb \ast blockDim^{2}\)的数据数组,该数组保存了 |
|
(指针) |
指向长度为 |
|
(指针) |
指向长度为 |
|
(指针) |
指向长度为 |
BSR和BSRX之间的简单转换可以按如下方式进行。假设开发者有一个\(2 \times 3\)块稀疏矩阵\(A_{b}\),其表示形式如下所示。
假设它具有以下BSR格式:
BSRX格式中的bsrRowPtrA就是BSR格式bsrRowPtrA的前两个元素。而BSRX格式的bsrEndPtrA则是BSR格式bsrRowPtrA的最后两个元素。
BSRX格式的优势在于,开发者可以通过修改bsrRowPtrA和bsrEndPtrA来指定原始BSR格式中的子矩阵,同时保持bsrColIndA和bsrValA不变。
例如,要创建一个与\(A\)略有不同的块矩阵\(\widetilde{A} = \begin{bmatrix}
O & O & O \\
O & A_{11} & O \\
\end{bmatrix}\),开发者可以保留bsrColIndA和bsrValA,但通过正确设置bsrRowPtrA和bsrEndPtrA来重构\(\widetilde{A}\)。以下4维向量描述了\(\widetilde{A}\)。
4. cuSPARSE基础API
4.1. cuSPARSE 类型参考
4.1.1. cuda数据类型_t
本节描述了多个CUDA库共享的类型,这些类型定义在头文件library_types.h中。cudaDataType类型是一个枚举器,用于指定数据精度。当数据引用本身不携带类型时(例如void*)会使用它。例如,该类型在例程cusparseSpMM()中被使用。
值 |
含义 |
数据类型 |
头信息 |
|
|---|---|---|---|---|
|
数据类型为16位IEEE-754浮点数 |
|
cuda_fp16.h |
|
|
数据类型为16位复数IEEE-754浮点数 |
|
cuda_fp16.h |
[已弃用] |
|
数据类型为16位bfloat浮点数 |
|
cuda_bf16.h |
|
|
数据类型为16位复数bfloat浮点数 |
|
cuda_bf16.h |
[已弃用] |
|
数据类型为32位IEEE-754浮点数 |
|
||
|
数据类型为32位复数IEEE-754浮点数 |
|
cuComplex.h |
|
|
该数据类型为64位IEEE-754浮点数 |
|
||
|
数据类型为64位复数IEEE-754浮点数 |
|
cuComplex.h |
|
|
数据类型为8位整数 |
|
stdint.h |
|
|
数据类型为32位整数 |
|
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库未被初始化。这通常是由于缺少先前的调用、cuSPARSE例程调用的CUDA Runtime API出错,或硬件设置错误导致的 需要修正:在调用该函数前先调用 该错误同样适用于通用API(cuSPARSE通用API),用于表示矩阵/向量描述符未初始化 |
|
cuSPARSE库内部资源分配失败。这通常由设备内存分配( 需要修正:在函数调用前,尽可能释放之前分配的内存 |
|
向函数传递了不支持的值或参数(例如负向量大小) 需要修正:确保所有传递的参数都具有有效值 |
|
该函数需要的功能在当前设备架构中缺失 需要修正:在具有适当计算能力的设备上编译并运行应用程序 |
|
GPU程序执行失败。这通常是由于GPU上的内核启动失败引起的,可能由多种原因导致 需要修正: 检查硬件、适当版本的驱动程序以及cuSPARSE库是否正确安装 |
|
内部cuSPARSE操作失败 需要修正: 检查硬件设备、适当版本的驱动程序以及cuSPARSE库是否正确安装。同时,确保作为参数传递给例程的内存在例程完成前未被释放。 |
|
该函数不支持此矩阵类型。这通常是由于向函数传递了无效的矩阵描述符所致 需要修正: 检查 |
|
该函数目前不支持此操作或数据类型组合 |
|
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()例程进行设置和获取。
值 |
含义 |
|---|---|
|
标量通过主机上的引用传递。 |
|
标量通过设备上的引用传递。 |
4.1.5. cusparseOperation_t
此类型指示对相关输入(例如稀疏矩阵或向量)应用了哪些操作。
值 |
含义 |
|---|---|
|
选择非转置操作。 |
|
已选择转置操作。 |
|
选择了共轭转置操作。 |
4.1.6. cusparseDiagType_t
此类型表示矩阵对角线元素是否为1。对角线元素始终被视为存在,但如果将CUSPARSE_DIAG_TYPE_UNIT传递给API例程,则该例程会假定所有对角线元素均为1,且不会读取或修改这些元素。请注意,在这种情况下,无论内存中实际设置的值是多少,例程都会假定对角线元素等于1。
值 |
含义 |
|---|---|
|
矩阵对角线包含非单位元素。 |
|
矩阵对角线上的元素为单位元素。 |
4.1.7. cusparseFillMode_t
该类型指示矩阵的下三角部分还是上三角部分存储在稀疏存储中。
值 |
含义 |
|---|---|
|
存储的是下三角部分。 |
|
存储的是矩阵的上三角部分。 |
4.1.8. cusparseIndexBase_t
该类型表示矩阵索引的基数是零还是一。
值 |
含义 |
|---|---|
|
基础索引从零开始(兼容C语言)。 |
|
基础索引从1开始(与Fortran兼容)。 |
4.1.9. cusparseDirection_t
该类型指示在函数cusparse[S|D|C|Z]nnz中,稠密矩阵的元素应按行还是按列进行解析(假设内存中稠密矩阵采用列优先存储)。此外,BSR格式中块的存储格式也由此类型控制。
值 |
含义 |
|---|---|
|
矩阵应按行解析。 |
|
矩阵应按列解析。 |
4.2. cuSPARSE管理API
本节介绍用于管理库的cuSPARSE函数。
4.2.1. cusparseCreate()
cusparseStatus_t
cusparseCreate(cusparseHandle_t *handle)
该函数用于初始化cuSPARSE库并创建cuSPARSE上下文句柄。在调用任何其他cuSPARSE API函数之前,必须先调用此函数。它会分配访问GPU所需的硬件资源。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
指向cuSPARSE上下文句柄的指针 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.2. cusparseDestroy()
cusparseStatus_t
cusparseDestroy(cusparseHandle_t handle)
此函数释放cuSPARSE库使用的CPU端资源。GPU端资源的释放可能会延迟到应用程序关闭时。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
cuSPARSE上下文的句柄 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.3. cusparseGetErrorName()
const char*
cusparseGetErrorString(cusparseStatus_t status)
该函数返回错误代码枚举名称的字符串表示形式。如果错误代码未被识别,则返回“无法识别的错误代码”。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
将错误代码转换为字符串 |
|
输出 |
指向以NULL结尾的字符串的指针 |
4.2.4. cusparseGetErrorString()
const char*
cusparseGetErrorString(cusparseStatus_t status)
返回错误码的描述字符串。如果错误码未被识别,则返回“无法识别的错误码”。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
将错误代码转换为字符串 |
|
输出 |
指向以NULL结尾的字符串的指针 |
4.2.5. cusparseGetProperty()
cusparseStatus_t
cusparseGetProperty(libraryPropertyType type,
int* value)
该函数返回所请求属性的值。支持的属性类型请参考libraryPropertyType。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
请求的属性 |
|
输出 |
请求属性的值 |
libraryPropertyType (定义于 library_types.h):
值 |
含义 |
|---|---|
|
用于查询主版本的枚举器 |
|
用于查询次要版本的枚举器 |
|
用于标识补丁级别的编号 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.6. cusparseGetVersion()
cusparseStatus_t
cusparseGetVersion(cusparseHandle_t handle,
int* version)
该函数返回cuSPARSE库的版本号。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
cuSPARSE 句柄 |
|
输出 |
库的版本号 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.7. cusparseGetPointerMode()
cusparseStatus_t
cusparseGetPointerMode(cusparseHandlet handle,
cusparsePointerMode_t *mode)
该函数获取cuSPARSE库使用的指针模式。详情请参阅关于cusparsePointerMode_t类型的章节。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
cuSPARSE上下文的句柄 |
|
输出 |
枚举指针模式类型之一 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.8. cusparseSetPointerMode()
cusparseStatus_t
cusparseSetPointerMode(cusparseHandle_t handle,
cusparsePointerMode_t mode)
此函数设置cuSPARSE库使用的指针模式。默认情况下,值通过主机上的引用传递。有关更多详细信息,请参阅cublasPointerMode_t类型的相关章节。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
cuSPARSE上下文的句柄 |
|
IN |
枚举指针模式类型之一 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.9. cusparseGetStream()
cusparseStatus_t
cusparseGetStream(cusparseHandle_t handle, cudaStream_t *streamId)
此函数获取当前用于执行所有cuSPARSE库函数调用的cuSPARSE库流。如果未设置cuSPARSE库流,则所有内核将使用默认的NULL流。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
cuSPARSE上下文的句柄 |
|
输出 |
该库使用的流 |
有关返回状态的描述,请参考cusparseStatus_t。
4.2.10. cusparseSetStream()
cusparseStatus_t
cusparseSetStream(cusparseHandle_t handle, cudaStream_t streamId)
此函数设置cuSPARSE库用于执行其例程的流。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
cuSPARSE上下文的句柄 |
|
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。例如。
如果未定义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)
实验性功能:该函数用于设置日志记录回调函数。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
指向回调函数的指针 |
其中 cusparseLoggerCallback_t 具有以下签名:
void (*cusparseLoggerCallback_t)(int logLevel,
const char* functionName,
const char* message)
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
选定的日志级别 |
|
IN |
记录此消息的API名称 |
|
IN |
日志消息 |
有关返回状态的描述,请参见cusparseStatus_t。
4.3.2. cusparseLoggerSetFile()
cusparseStatus_t
cusparseLoggerSetFile(FILE* file)
实验性功能: 此函数用于设置日志输出文件。注意:通过此函数调用注册后,除非再次调用该函数切换至其他文件句柄,否则不得关闭提供的文件句柄。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
指向一个已打开文件的指针。该文件应具有写入权限 |
有关返回状态的描述,请参见cusparseStatus_t。
4.3.3. cusparseLoggerOpenFile()
cusparseStatus_t
cusparseLoggerOpenFile(const char* logFile)
实验性功能:该函数会在指定路径下打开一个日志输出文件。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
日志输出文件的路径 |
有关返回状态的描述,请参见cusparseStatus_t。
4.3.4. cusparseLoggerSetLevel()
cusparseStatus_t
cusparseLoggerSetLevel(int level)
实验性功能: 该函数用于设置日志记录级别的值。路径。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
日志记录级别的值 |
有关返回状态的描述,请参见cusparseStatus_t
4.3.5. cusparseLoggerSetMask()
cusparseStatus_t
cusparseLoggerSetMask(int mask)
实验性功能: 该函数用于设置日志掩码的值。
参数 |
输入/输出 |
含义 |
|---|---|---|
|
IN |
日志掩码的值 |
有关返回状态的描述,请参见cusparseStatus_t
5. cuSPARSE传统API
5.1. 命名规范
cuSPARSE传统函数支持以下数据类型:float、double、cuComplex和cuDoubleComplex。稀疏矩阵的Level 2和Level 3函数遵循以下命名规范:
cusparse<t>[<matrix data format>]<operation>[<output matrix data format>]
其中 <t> 可以是 S、D、C、Z 或 X,分别对应数据类型 float、double、cuComplex、cuDoubleComplex 以及通用类型。
matrix data format可以是dense、coo、csr或csc,分别对应稠密矩阵、坐标格式、压缩稀疏行格式和压缩稀疏列格式。
5.2. cuSPARSE传统类型参考
5.2.1. cusparseAction_t
该类型指示操作是仅针对索引执行,还是针对数据和索引执行。
值 |
含义 |
|---|---|
|
该操作仅在索引上执行。 |
|
该操作在数据和索引上执行。 |
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。
值 |
含义 |
|---|---|
|
矩阵是通用的。 |
|
该矩阵是对称的。 |
|
该矩阵是厄米特矩阵。 |
|
该矩阵是三角矩阵。 |
5.2.4. cusparseColorInfo_t [已弃用]
这是一个指向不透明结构的指针类型,该结构保存了csrcolor()中使用的信息。
5.2.5. cusparseSolvePolicy_t [已弃用]
该类型指示是否在csrsv2, csric02, csrilu02, bsrsv2, bsric02 和 bsrilu02中生成和使用级别信息。
值 |
含义 |
|---|---|
|
未生成或使用任何层级信息。 |
|
生成并使用层级信息。 |
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结构体,将其设置为默认值。
输入
|
指向 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.2. cusparseCreateMatDescr()
cusparseStatus_t
cusparseCreateMatDescr(cusparseMatDescr_t *descrA)
该函数用于初始化矩阵描述符。它将字段MatrixType和IndexBase分别设置为默认值CUSPARSE_MATRIX_TYPE_GENERAL和CUSPARSE_INDEX_BASE_ZERO,而其他字段则保持未初始化状态。
输入
|
指向矩阵描述符的指针。 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.3. cusparseDestroyColorInfo() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseDestroyColorInfo(cusparseColorInfo_t info)
该函数销毁并释放该结构所需的任何内存。
输入
|
指向 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.4. cusparseDestroyMatDescr()
cusparseStatus_t
cusparseDestroyMatDescr(cusparseMatDescr_t descrA)
该函数释放为矩阵描述符分配的内存。
输入
|
矩阵描述符。 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.5. cusparseGetMatDiagType()
cusparseDiagType_t
cusparseGetMatDiagType(const cusparseMatDescr_t descrA)
该函数返回矩阵描述符descrA中的DiagType字段。
输入
|
矩阵描述符。 |
返回
|
枚举类型diagType中的一种。 |
5.3.6. cusparseGetMatFillMode()
cusparseFillMode_t
cusparseGetMatFillMode(const cusparseMatDescr_t descrA)
该函数返回矩阵描述符descrA的FillMode字段。
输入
|
矩阵描述符。 |
返回
|
枚举填充模式类型之一。 |
5.3.7. cusparseGetMatIndexBase()
cusparseIndexBase_t
cusparseGetMatIndexBase(const cusparseMatDescr_t descrA)
该函数返回矩阵描述符descrA的IndexBase字段。
输入
|
矩阵描述符。 |
返回
|
枚举的indexBase类型之一。 |
5.3.8. cusparseGetMatType()
cusparseMatrixType_t
cusparseGetMatType(const cusparseMatDescr_t descrA)
该函数返回矩阵描述符descrA的MatrixType字段。
输入
|
矩阵描述符。 |
返回
|
枚举矩阵类型之一。 |
5.3.9. cusparseSetMatDiagType()
cusparseStatus_t
cusparseSetMatDiagType(cusparseMatDescr_t descrA,
cusparseDiagType_t diagType)
此函数设置矩阵描述符descrA的DiagType字段。
输入
|
枚举的diagType类型之一。 |
输出
|
矩阵描述符。 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.10. cusparseSetMatFillMode()
cusparseStatus_t
cusparseSetMatFillMode(cusparseMatDescr_t descrA,
cusparseFillMode_t fillMode)
此函数设置矩阵描述符descrA的FillMode字段。
输入
|
枚举的fillMode类型之一。 |
输出
|
矩阵描述符。 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.11. cusparseSetMatIndexBase()
cusparseStatus_t
cusparseSetMatIndexBase(cusparseMatDescr_t descrA,
cusparseIndexBase_t base)
此函数设置矩阵描述符descrA的IndexBase字段。
输入
|
枚举的indexBase类型之一。 |
输出
|
矩阵描述符。 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.12. cusparseSetMatType()
cusparseStatus_t
cusparseSetMatType(cusparseMatDescr_t descrA, cusparseMatrixType_t type)
此函数设置矩阵描述符descrA的MatrixType字段。
输入
|
枚举矩阵类型之一。 |
输出
|
矩阵描述符。 |
有关返回状态的描述,请参见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);
该函数销毁并释放该结构所需的任何内存。
输入
|
求解 |
有关返回状态的描述,请参见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);
该函数销毁并释放该结构所需的任何内存。
输入
|
求解 |
有关返回状态的描述,请参见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);
该函数销毁并释放该结构所需的任何内存。
输入
|
解决 |
有关返回状态的描述,请参见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);
该函数销毁并释放该结构所需的任何内存。
输入
|
解决 |
有关返回状态的描述,请参见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);
该函数销毁并释放该结构所需的任何内存。
输入
|
求解 |
有关返回状态的描述,请参见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);
该函数销毁并释放该结构所需的任何内存。
输入
|
求解 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.25. cusparseCreatePruneInfo() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseCreatePruneInfo(pruneInfo_t *info);
该函数创建并初始化prune结构为默认值。
输入
|
指向 |
有关返回状态的描述,请参见cusparseStatus_t。
5.3.26. cusparseDestroyPruneInfo() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseDestroyPruneInfo(pruneInfo_t info);
该函数销毁并释放该结构所需的任何内存。
输入
|
|
有关返回状态的描述,请参见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)
该函数执行矩阵-向量运算
其中 \(A\text{ is an }(mb \ast blockDim) \times (nb \ast blockDim)\) 是一个稀疏矩阵,通过三个数组 bsrVal、bsrRowPtr 和 bsrColInd 以BSR存储格式定义;x 和 y 是向量;\(\alpha\text{ and }\beta\) 是标量;并且

bsrmv() 具有以下特性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
关于bsrmv()的几点说明:
仅支持
blockDim > 1仅支持
CUSPARSE_OPERATION_NON_TRANSPOSE操作,即
仅支持
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);
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
运算 \(\text{op}(A)\)。仅支持 |
|
矩阵 \(A\) 的块行数。 |
|
矩阵 \(A\) 的块列数。 |
|
矩阵\(A\)的非零块数量。 |
|
用于乘法的标量。 |
|
矩阵\(A\)的描述符。支持的矩阵类型是 |
|
|
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
长度为 |
|
稀疏矩阵\(A\)的块维度,大于零。 |
|
<类型> 包含 \(nb \ast blockDim\) 个元素的向量。 |
|
|
|
输出
|
有关返回状态的描述,请参见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和掩码操作
其中\(A\text{ 是一个 }(mb \ast blockDim) \times (nb \ast blockDim)\)稀疏矩阵,由四个数组bsrVal、bsrRowPtr、bsrEndPtr和bsrColInd以BSRX存储格式定义;x和y是向量;\(\alpha\text{~和~}\beta\)是标量;并且

掩码操作由数组bsrMaskPtr定义,该数组包含\(y\)更新后的块行索引。如果行\(i\)未在bsrMaskPtr中指定,则bsrxmv()不会触及\(A\)和\(y\)的行块\(i\)。
例如,考虑一个\(2 \times 3\)的分块矩阵\(A\):
其基于1的BSR格式(三向量形式)为:
假设我们想对矩阵\(\bar{A}\)执行以下bsrmv操作,该矩阵与\(A\)略有不同。
我们无需为新矩阵\(\bar{A}\)创建另一种BSR格式,只需保持bsrVal和bsrColInd不变,但修改bsrRowPtr并新增一个数组bsrEndPtr,该数组指向\(\bar{A}\)每行最后一个非零元素的下一个位置。
例如,以下bsrRowPtr和bsrEndPtr可以表示矩阵\(\bar{A}\):
此外,我们可以使用掩码运算符(由数组bsrMaskPtr指定)仅更新\(y\)的特定块行索引,因为\(y_{1}\)永远不会改变。在这种情况下,bsrMaskPtr\(=\) [2]且sizeOfMask=1。
mask操作符等同于以下操作:
如果某个块行不在bsrMaskPtr中,则不会对该行执行计算,并且y中的对应值保持不变。问号"?"用于表示不在bsrMaskPtr中的行块。
在这种情况下,第一行块不存在于bsrMaskPtr中,因此bsrRowPtr[0]和bsrEndPtr[0]也不会被修改。
bsrxmv() 具有以下属性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
关于bsrxmv()的一些说明:
仅支持
blockDim > 1仅支持
CUSPARSE_OPERATION_NON_TRANSPOSE和CUSPARSE_MATRIX_TYPE_GENERAL。参数
bsrMaskPtr,bsrRowPtr,bsrEndPtr和bsrColInd与基础索引保持一致,可以是一基或零基。上面的示例是一基的。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
运算 \(\text{op}(A)\)。仅支持 |
|
更新的块行数 \(y\)。 |
|
矩阵 \(A\) 的块行数。 |
|
矩阵 \(A\) 的块列数。 |
|
矩阵\(A\)的非零块数量。 |
|
用于乘法的标量。 |
|
矩阵\(A\)的描述符。支持的矩阵类型是 |
|
|
|
包含对应已更新块行索引的 |
|
包含每个块行起始位置的 |
|
包含每个块行末尾加1的 |
|
矩阵\(A\)非零块的 |
|
稀疏矩阵\(A\)的块维度,大于零。 |
|
<类型> 包含 \(nb \ast blockDim\) 个元素的向量。 |
|
<type> 用于乘法的标量。如果 |
|
<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) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;x 和 y 分别是右侧向量和解向量;\(\alpha\) 是一个标量;

尽管参数trans与矩阵A的上(下)三角部分存在六种组合情况,但bsrsv2_bufferSize()会返回这些组合中所需的最大缓冲区大小。缓冲区大小取决于维度参数mb、blockDim以及矩阵非零块数量nnzb。若用户修改了矩阵,必须重新调用bsrsv2_bufferSize()以获取正确的缓冲区大小,否则可能导致段错误。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 \(\text{op}(A)\) 。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
|
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度;必须大于零。 |
输出
|
基于不同算法的内部状态记录。 |
|
用于 |
有关返回状态的描述,请参见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) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;x 和 y 分别是右侧向量和解向量;\(\alpha\) 是一个标量;

BSR格式的块大小为blockDim*blockDim,根据参数dirA决定按列优先或行优先存储,该参数可以是CUSPARSE_DIRECTION_COLUMN或CUSPARSE_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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 \(\text{op}(A)\) 。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
|
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度,大于零。 |
|
使用 |
|
支持的策略是 |
|
由用户分配的缓冲区,其大小由 |
输出
|
在分析阶段收集的信息填充的结构(应原封不动地传递给解决阶段)。 |
有关返回状态的描述,请参见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) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;x 和 y 分别是右侧向量和解向量;\(\alpha\) 是一个标量;

BSR格式中的块大小为blockDim*blockDim,根据参数dirA决定按列优先或行优先存储,该参数可以是CUSPARSE_DIRECTION_COLUMN或CUSPARSE_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);
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 \(\text{op}(A)\)。 |
|
矩阵 |
|
用于乘法的标量。 |
|
矩阵 |
|
<type> 数组,包含矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵 |
|
包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。 |
|
|
|
支持的策略是 |
|
由用户分配的缓冲区,其大小由 |
输出
|
|
有关返回状态的描述,请参见cusparseStatus_t。
5.4.6. cusparseXbsrsv2_zeroPivot() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseXbsrsv2_zeroPivot(cusparseHandle_t handle,
bsrsv2Info_t info,
int* position)
如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOT,position=j表示A(j,j)是结构零或数值零(奇异块)。否则position=-1。
position 可以是基于0或基于1的索引,与矩阵的索引方式相同。
函数 cusparseXbsrsv2_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。
position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。
该例程不需要额外的存储空间
如果流序内存分配器可用,该例程支持异步执行
如果流序内存分配器可用,该例程支持CUDA图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
|
输出
|
如果没有结构或数值上的零值, |
有关返回状态的描述,请参见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)
该函数执行矩阵-向量运算
A 是一个 \(m \times n\) 的稠密矩阵,稀疏向量 x 通过两个长度为 nnz 的数组 xVal, xInd 以稀疏存储格式定义,y 是一个稠密向量;\(\alpha \;\) 和 \(\beta \;\) 是标量;且

为了简化实现,我们目前尚未对转置多重情况进行优化。对于对此情况感兴趣的用户,我们推荐以下方法。
使用
csr2csc()函数之一将矩阵从CSR格式转换为CSC格式。请注意,通过交换结果的行和列,您实际上是在对矩阵进行转置。-
调用
gemvi()函数,将cusparseOperation_t参数设置为CUSPARSE_OPERATION_NON_TRANSPOSE,并使用以CSC格式存储的矩阵行列互换版本。这(隐式地)实现了向量与原始CSR格式矩阵转置的乘法运算。该例程不需要额外的存储空间
该例程支持异步执行
该例程支持CUDA图捕获
函数 cusparse 返回在 cusparse 中使用的缓冲区大小。
输入
|
cuSPARSE库上下文的句柄。 |
|
操作 \(\text{op}(A)\)。 |
|
矩阵 |
|
矩阵 |
|
用于乘法的标量。 |
|
指向稠密矩阵 |
|
|
|
向量 |
|
|
|
|
|
<type> 用于乘法的标量。如果 |
|
|
|
0或1,分别表示基于0或基于1的索引。 |
|
缓冲区在 |
|
工作空间缓冲区。 |
输出
|
有关返回状态的描述,请参见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)
该函数执行以下矩阵-矩阵运算之一:
A 是一个 \(mb \times kb\) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;B 和 C 是稠密矩阵;\(\alpha\text{~和~}\beta\) 是标量;并且

和

该函数有以下限制:
仅支持
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*kb,B的维度是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,而是先调用cublas将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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 |
|
操作 |
|
稀疏矩阵 |
|
稠密矩阵 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
用于乘法的标量。 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵 |
|
维度数组 |
|
|
|
|
|
维度数组 |
|
|
输出
|
|
有关返回状态的描述,请参见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) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;B 和 X 分别是右侧矩阵和解矩阵;\(\alpha\) 是一个标量;

尽管参数trans与矩阵A的上(下)三角部分存在六种组合情况,但bsrsm2_bufferSize()会返回这些组合中所需的缓冲区最大尺寸。缓冲区大小取决于维度mb,blockDim以及矩阵非零元素数量nnzb。若用户修改了矩阵,必须重新调用bsrsm2_bufferSize()获取正确的缓冲区大小,否则可能导致段错误。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 |
|
操作 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵 |
输出
|
根据不同算法记录内部状态。 |
|
在 |
有关返回状态的描述,请参见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) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;B 和 X 分别是右侧矩阵和解矩阵;\(\alpha\) 是一个标量;

和

且 op(B) 和 op(X) 相等。
BSR格式的块大小为blockDim*blockDim,根据参数dirA决定按列优先或行优先存储,该参数可以是CUSPARSE_DIRECTION_ROW或CUSPARSE_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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 |
|
操作 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵 |
|
使用 |
|
支持的政策有 |
|
由用户分配的缓冲区;大小由 |
输出
|
在分析阶段收集的信息填充的结构(应原封不动地传递给解决阶段)。 |
有关返回状态的描述,请参见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)
该函数执行稀疏三角线性系统解的求解阶段:
A 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义;B 和 X 分别是右侧矩阵和解矩阵;\(\alpha\) 是一个标量,且

和

仅支持 op(A)=A。
op(B) 和 op(X) 必须以相同的方式执行。换句话说,如果 op(B)=B,则 op(X)=X。
BSR格式的块大小为blockDim*blockDim,根据参数dirA决定以列优先或行优先方式存储,该参数可以是CUSPARSE_DIRECTION_ROW或CUSPARSE_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。
支持原地操作,要求B和X指向相同的内存块,且ldb=ldx。
如果pBuffer != NULL,该函数支持以下属性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
操作 |
|
操作 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
用于乘法的标量。 |
|
矩阵 |
|
|
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵 |
|
使用 |
|
|
|
|
|
|
|
支持的策略是 |
|
由用户分配的缓冲区;大小由 |
输出
|
|
有关返回状态的描述,请参见cusparseStatus_t。
5.5.5. cusparseXbsrsm2_zeroPivot() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseXbsrsm2_zeroPivot(cusparseHandle_t handle,
bsrsm2Info_t info,
int* position)
如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOT,position=j表示A(j,j)是结构零或数值零(奇异块)。否则position=-1。
position 可以是基于0或基于1的索引,与矩阵的索引方式相同。
函数 cusparseXbsrsm2_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。
position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。
该例程不需要额外的存储空间。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
|
输出
|
如果没有结构或数值上的零值, |
有关返回状态的描述,请参见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)
该函数执行以下矩阵-矩阵运算
其中A、B和C是\(m \times n\)稀疏矩阵(分别由三个数组csrValA|csrValB|csrValC、csrRowPtrA|csrRowPtrB|csrRowPtrC和csrColIndA|csrColIndB|csrcolIndC以CSR存储格式定义),\(\alpha\text{~和~}\beta\)为标量。由于A和B具有不同的稀疏模式,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。如果A或B是对称或厄米特矩阵,用户必须将矩阵扩展为完整矩阵,并将描述符的MatrixType字段重新配置为CUSPARSE_MATRIX_TYPE_GENERAL。如果已知矩阵
C的稀疏模式,用户可以跳过对函数cusparseXcsrgeam2Nnz()的调用。例如,假设用户有一个迭代算法会不断更新A和B但保持稀疏模式不变。用户可以仅调用一次cusparseXcsrgeam2Nnz()来设置C的稀疏模式,然后在每次迭代时仅调用函数cusparse[S|D|C|Z]geam()。指针
alpha和beta必须有效。当
alpha或beta为零时,cuSPARSE不会将其视为特殊情况。C的稀疏模式与alpha和beta的值无关。如果用户需要\(C = 0 \times A + 1 \times B^{T}\),那么使用csr2csc()会比csrgeam2()更合适。csrgeam2()与csrgeam()功能相同,区别在于csrgeam2()需要显式缓冲区,而csrgeam()会在内部自动分配缓冲区。此函数需要临时额外存储空间,该空间在内部分配。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
用于乘法的标量。 |
|
矩阵 |
|
稀疏矩阵 |
|
|
|
一个包含 |
|
|
|
<type> 用于乘法的标量。如果 |
|
矩阵 |
|
稀疏矩阵 |
|
|
|
一个包含 |
|
|
|
矩阵 |
输出
|
|
|
一个包含 |
|
长度为 |
|
设备或主机内存中非零元素的总数。它等于 |
有关返回状态的描述,请参见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 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValA、csrRowPtrA 和 csrColIndA 以 CSR 存储格式定义。
缓冲区大小取决于矩阵的维度m和非零元素数量nnz。如果用户更改了矩阵,必须再次调用csric02_bufferSize()以获取正确的缓冲区大小,否则可能会出现段错误。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
|
|
一个包含 |
|
长度为 |
输出
|
根据不同算法记录内部状态 |
|
在 |
有关返回状态的描述,请参见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 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValA、csrRowPtrA 和 csrColIndA 以 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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
|
|
一个包含 |
|
长度为 |
|
使用 |
|
支持的策略是 |
|
由用户分配的缓冲区;大小由 |
输出
|
在 |
有关返回状态的描述,请参见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\)填充且无主元选择:
此函数需要由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与其转置矩阵的乘积。
// 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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
|
|
一个包含 |
|
长度为 |
|
包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。 |
|
支持的策略是 |
|
由用户分配的缓冲区;大小由 |
输出
|
有关返回状态的描述,请参见cusparseStatus_t。
5.7.1.4. cusparseXcsric02_zeroPivot() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseXcsric02_zeroPivot(cusparseHandle_t handle,
csric02Info_t info,
int* position)
如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOT,position=j表示A(j,j)存在结构零或数值零;否则,position=-1。
position 可以是基于0或基于1的索引,与矩阵的索引方式相同。
函数 cusparseXcsric02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 以确保之前的所有内核操作都已完成。
position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。
该例程不需要额外的存储空间。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
|
输出
|
如果没有结构或数值上的零值, |
有关返回状态的描述,请参见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 是一个 (mb*blockDim)*(mb*blockDim) 稀疏矩阵,由三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义。
缓冲区大小取决于mb、blockDim的维度以及矩阵nnzb的非零块数量。如果用户更改了矩阵,必须再次调用bsric02_bufferSize()以获取正确的缓冲区大小;否则可能会出现段错误。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度,大于零。 |
输出
|
根据不同算法记录内部状态。 |
|
在 |
有关返回状态的描述,请参见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 是一个 (mb*blockDim)x(mb*blockDim) 的稀疏矩阵,由三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式为列优先或行优先,由参数 dirA 决定,该参数可以是 CUSPARSE_DIRECTION_COLUMN 或 CUSPARSE_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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度;必须大于零。 |
|
使用 |
|
支持的策略是 |
|
由用户分配的缓冲区;大小由 |
输出
|
填充了分析阶段收集的信息的结构(应原封不动地传递给求解阶段)。 |
有关返回状态的描述,请参见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 是一个 (mb*blockDim)x(mb*blockDim) 的稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式为列优先或行优先,由参数 dirA 决定,该参数可以是 CUSPARSE_DIRECTION_COLUMN 或 CUSPARSE_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 与其转置的乘积。
// 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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度,大于零。 |
|
包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。 |
|
支持的策略是 |
|
由用户分配的缓冲区,其大小由 |
输出
|
有关返回状态的描述,请参见cusparseStatus_t。
5.7.1.8. cusparseXbsric02_zeroPivot() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseXbsric02_zeroPivot(cusparseHandle_t handle,
bsric02Info_t info,
int* position)
如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOT,position=j表示A(j,j)存在结构零或数值零(该块不是正定的)。否则position=-1。
position 可以是基于0或基于1的索引,与矩阵的索引方式相同。
函数 cusparseXbsric02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。
position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。
该例程不需要额外的存储空间。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
|
输出
|
如果没有结构或数值上的零值, |
有关返回状态的描述,请参见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,则忽略 tol 和 boost_val。
tol 和 boost_val 可以存放在主机内存或设备内存中。用户可以通过 cusparseSetPointerMode() 设置合适的模式。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄 |
|
使用 |
|
通过 |
|
用于确定数值零的容差 |
|
用于替换数值零的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 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValA、csrRowPtrA 和 csrColIndA 以 CSR 存储格式定义。
缓冲区大小取决于矩阵的维度m和非零元素数量nnz。如果用户更改了矩阵,必须再次调用csrilu02_bufferSize()以获取正确的缓冲区大小;否则可能会出现段错误。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
一个包含 |
|
长度为 |
输出
|
根据不同算法记录内部状态 |
|
在 |
有关返回状态的描述,请参见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 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValA、csrRowPtrA 和 csrColIndA 以 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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
一个包含 |
|
长度为 |
|
使用 |
|
支持的策略是 |
|
由用户分配的缓冲区,其大小由 |
输出
|
填充了分析阶段收集的信息的结构(应原封不动地传递给求解阶段)。 |
有关返回状态的描述,请参见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 是一个 \(m \times m\) 的稀疏矩阵,通过三个数组 csrValA_valM、csrRowPtrA 和 csrColIndA 以 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 因子 L 和 U 的乘积。
// 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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
一个包含 |
|
长度为 |
|
包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。 |
|
支持的策略是 |
|
由用户分配的缓冲区;大小由 |
输出
|
有关返回状态的描述,请参见cusparseStatus_t。
5.7.2.5. cusparseXcsrilu02_zeroPivot() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseXcsrilu02_zeroPivot(cusparseHandle_t handle,
csrilu02Info_t info,
int* position)
如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOT,position=j表示A(j,j)存在结构零或数值零;否则,position=-1。
position 可以是基于0或基于1的索引,与矩阵的索引方式相同。
函数 cusparseXcsrilu02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。
position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。
该例程不需要额外的存储空间
如果流序内存分配器可用,该例程支持异步执行
如果流序内存分配器可用,该例程支持CUDA图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
|
输出
|
如果没有结构或数值上的零值, |
有关返回状态的描述,请参见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,则忽略 tol 和 boost_val。
tol 和 boost_val 可以存储在主机内存或设备内存中。用户可以通过 cusparseSetPointerMode() 设置适当的模式。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
使用 |
|
通过设置 |
|
用于确定数值零的容差。 |
|
用于替换数值零的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 是一个 (mb*blockDim)x(mb*blockDim) 稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义。
缓冲区大小取决于mb、blockDim的维度以及矩阵nnzb的非零块数量。如果用户更改了矩阵,必须再次调用bsrilu02_bufferSize()以获取正确的缓冲区大小;否则可能会出现段错误。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度,大于零。 |
输出
|
根据不同算法记录内部状态。 |
|
在 |
返回状态
|
操作已成功完成。 |
|
库未初始化。 |
|
资源无法分配。 |
|
传递了无效参数( |
|
该设备仅支持计算能力2.0及以上版本。 |
|
内部操作失败。 |
|
不支持该矩阵类型。 |
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) 的稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式可以是列优先或行优先,由参数 dirA 决定,其值为 CUSPARSE_DIRECTION_COLUMN 或 CUSPARSE_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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度,大于零。 |
|
使用 |
|
支持的策略是 |
|
由用户分配的缓冲区,其大小由 |
输出
|
在分析阶段收集的信息填充的结构(应原封不动地传递给求解阶段) |
有关返回状态的描述,请参见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 是一个 (mb*blockDim)×(mb*blockDim) 的稀疏矩阵,通过三个数组 bsrValA、bsrRowPtrA 和 bsrColIndA 以BSR存储格式定义。BSR格式中的块大小为 blockDim*blockDim,存储方式为列优先或行优先,由参数 dirA 决定,该参数可以是 CUSPARSE_DIRECTION_COLUMN 或 CUSPARSE_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 因子 L 和 U 的乘积。
// 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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式:可以是 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每个块行起始位置及最后一个块行结束位置加1的 |
|
|
|
稀疏矩阵A的块维度;必须大于零。 |
|
包含分析阶段收集的信息的结构(这些信息应原封不动地传递给求解阶段)。 |
|
支持的策略是 |
|
由用户分配的缓冲区;大小由 |
输出
|
有关返回状态的描述,请参见cusparseStatus_t。
5.7.2.10. cusparseXbsrilu02_zeroPivot() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseXbsrilu02_zeroPivot(cusparseHandle_t handle,
bsrilu02Info_t info,
int* position)
如果返回的错误代码是CUSPARSE_STATUS_ZERO_PIVOT,position=j表示A(j,j)存在结构零或数值零(该块不可逆)。否则position=-1。
position 可以是基于0或基于1的索引,与矩阵的索引方式相同。
函数 cusparseXbsrilu02_zeroPivot() 是一个阻塞调用。它会调用 cudaDeviceSynchronize() 来确保之前的所有内核操作都已完成。
position可以位于主机内存或设备内存中。用户可以通过cusparseSetPointerMode()设置合适的模式。
该例程不需要额外的存储空间。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
|
输出
|
如果没有结构或数值上的零值, |
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
线性系统的规模(必须 ≥ 3)。 |
|
右侧的数量,矩阵 |
|
|
|
|
|
|
|
|
|
|
输出
|
在 |
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B。
假设 A 的大小为 m 且基于1,dl、d 和 du 由以下公式定义:
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。
该例程确实执行了主元选择,虽然会牺牲一些执行时间,但通常能比cusparse或cusparse获得更准确和更稳定的结果。
此函数需要由gtsv2_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
线性系统的规模(必须 ≥ 3)。 |
|
右侧的数量,矩阵 |
|
|
|
包含三对角线性系统主对角线的密集数组。 |
|
|
|
|
|
|
|
由用户分配的缓冲区,其大小由 |
输出
|
|
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
线性系统的规模(必须 ≥ 3)。 |
|
右侧的数量,矩阵 |
|
|
|
包含三对角线性系统主对角线的密集数组。 |
|
包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。 |
|
|
|
|
输出
|
在 |
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B。
该例程不执行任何主元选择,而是结合使用循环约简(CR)和平行循环约简(PCR)算法来求解。当m是2的幂时,它能获得更好的性能。
此函数需要一个由gtsv2_nopivot_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
线性系统的规模(必须 ≥ 3)。 |
|
右侧的数量,矩阵 |
|
包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。 |
|
包含三对角线性系统主对角线的密集数组。 |
|
包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。 |
|
<type> 右侧密集数组,维度为 |
|
|
|
用户分配的缓冲区,其大小由 |
输出
|
|
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵X中。注意解Y会在退出时覆盖右侧项矩阵X。假设不同矩阵具有相同大小,并在内存中以固定的batchStride存储。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
线性系统的规模(必须 ≥ 3)。 |
|
|
|
|
|
|
|
|
|
需要求解的系统数量。 |
|
步幅(元素数量),用于分隔每个系统的向量(必须至少为 |
输出
|
在 |
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵X中。请注意,解Y会在退出时覆盖右侧矩阵X。假设不同矩阵具有相同大小,并在内存中以固定的batchStride存储。
该例程不执行任何主元选择,而是结合使用循环约简(CR)和平行循环约简(PCR)算法来求解。当m是2的幂时,它能获得更好的性能。
此函数需要由gtsv2StridedBatch_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
线性系统的规模(必须 ≥ 3)。 |
|
|
|
|
|
|
|
|
|
需要求解的系统数量。 |
|
步幅(元素数量)用于分隔每个系统的向量(必须至少为 |
|
用户分配的缓冲区,其大小由 |
输出
|
|
有关返回状态的描述,请参见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由三个向量定义,分别对应其下对角线(dl)、主对角线(d)和上对角线(du);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B。
假设 A 的大小为 m 且基于1,dl、d 和 du 由以下公式定义:
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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
algo = 0: cuThomas(不稳定算法); algo = 1: 带主元的LU分解(稳定算法); algo = 2: QR分解(稳定算法) |
|
线性系统的规模。 |
|
包含三对角线性系统下对角线的密集数组。每个下对角线的第一个元素必须为零。 |
|
包含三对角线性系统主对角线的密集数组。 |
|
包含三对角线性系统上对角线的密集数组。每个上对角线的最后一个元素必须为零。 |
|
|
|
由用户分配的缓冲区,其大小由 |
输出
|
|
有关返回状态的描述,请参见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由五个向量定义,分别对应其下对角线(ds, dl)、主对角线(d)和上对角线(du, dw);右侧项存储在稠密矩阵B中。请注意,解X会在退出时覆盖右侧矩阵B。
假设A的大小为m且基于1,ds、dl、d、du和dw由以下公式定义:
ds(i) := A(i, i-2) 当 i=1,2,...,m
ds的前两个元素超出边界(ds(1) := A(1,-1), ds(2) := A(2,0)),因此ds(1) = 0且ds(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) = 0 且 dw(m) = 0。
数据布局与gtsvStridedBatch相同。
该例程在数值上是稳定的,因为它使用QR分解来求解线性系统。
此函数需要由gpsvInterleavedBatch_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。如果不是,将返回CUSPARSE_STATUS_INVALID_VALUE。
如果pBuffer != NULL,该函数支持以下属性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
仅支持 algo = 0 (QR) |
|
线性系统的规模。 |
|
|
|
|
|
|
|
|
|
|
|
<type> 密集右侧数组,维度为 |
|
由用户分配的缓冲区,其大小由 |
输出
|
<type> 维度为 |
有关返回状态的描述,请参见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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
<type> 矩阵 |
|
包含每行起始位置及最后一行末尾加1的 |
|
长度为 |
|
需要着色的节点比例,应在区间[0.0,1.0]内,例如0.8表示80%的节点将被着色。 |
|
包含要传递给着色处理的信息的结构。 |
输出
|
使用的不同颜色数量(最多为矩阵的大小,但很可能小得多)。 |
|
生成的着色排列 |
|
结果的重排序置换(如果为NULL则保持不变) |
有关返回状态的描述,请参见cusparseStatus_t。
5.9. cuSPARSE格式转换参考
本章介绍不同稀疏与密集存储格式之间的转换例程。
coosort、csrsort、cscsort和csru2csr是不含内部malloc的排序例程,下表估算了所需的缓冲区大小。
|
|
|
|
|
125M |
|
|
100M |
|
|
'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)
该函数将由三个数组bsrValA、bsrRowPtrA和bsrColIndA定义的BSR格式稀疏矩阵转换为由数组csrValC、csrRowPtrC和csrColIndC定义的CSR格式稀疏矩阵。
设m(=mb*blockDim)为矩阵A的行数,n(=nb*blockDim)为矩阵A的列数,则A和C都是m*n的稀疏矩阵。A的BSR格式包含nnzb(=bsrRowPtrA[mb] - bsrRowPtrA[0])个非零块,而稀疏矩阵A包含nnz(=nnzb*blockDim*blockDim)个元素。用户必须为数组csrRowPtrC、csrColIndC和csrValC分配足够的空间。具体要求如下:
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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
矩阵 |
|
|
|
包含矩阵 |
|
矩阵 |
|
稀疏矩阵 |
|
矩阵 |
输出
|
|
|
包含矩阵 |
|
矩阵 |
有关返回状态的描述,请参见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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
矩阵 |
|
|
|
包含每个块行起始位置及最后一个块行结束位置加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)
该函数将由三个数组bsrValA、bsrRowPtrA和bsrColIndA定义的通用BSR格式稀疏矩阵,转换为由数组bsrValC、bsrRowPtrC和bsrColIndC定义的另一种通用BSR格式稀疏矩阵。
如果 rowBlockDimA=1 且 colBlockDimA=1,那么 cusparse[S|D|C|Z]gebsr2gebsr() 就等同于 cusparse[S|D|C|Z]csr2gebsr()。
如果 rowBlockDimC=1 且 colBlockDimC=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。
该实现采用两步法进行转换。首先,用户分配bsrRowPtrC的mc+1个元素,并使用函数cusparseXgebsr2gebsrNnz()确定矩阵C每块行的非零块列数。其次,用户从(nnzc=*nnzTotalDevHostPtr)或(nnzc=bsrRowPtrC[mc]-bsrRowPtrC[0])中获取nnzc(矩阵C的非零块列数),并分配bsrValC的nnzc*rowBlockDimC*colBlockDimC个元素以及bsrColIndC的nnzc个整数。最后调用函数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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
矩阵 |
|
矩阵 |
|
|
|
包含矩阵 |
|
矩阵 |
|
|
|
|
|
矩阵 |
|
一个 |
|
一个块中的列数 |
|
包含 |
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
包含矩阵 |
|
矩阵 |
|
|
有关返回状态的描述,请参见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)
该函数将由三个数组bsrValA、bsrRowPtrA和bsrColIndA定义的通用BSR格式稀疏矩阵转换为由数组csrValC、csrRowPtrC和csrColIndC定义的CSR格式稀疏矩阵。
设m(=mb*rowBlockDim)为A的行数,n(=nb*colBlockDim)为A的列数,则A和C都是m*n的稀疏矩阵。A的一般BSR格式包含nnzb(=bsrRowPtrA[mb] - bsrRowPtrA[0])个非零块,而稀疏矩阵A包含nnz(=nnzb*rowBlockDim*colBlockDim)个元素。用户必须为数组csrRowPtrC、csrColIndC和csrValC分配足够的空间。具体要求如下:
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图捕获
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
矩阵 |
|
|
|
包含矩阵 |
|
矩阵 |
|
|
|
|
|
矩阵 |
输出
|
|
|
包含矩阵 |
|
矩阵 |
有关返回状态的描述,请参见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(由数组csrValA、csrRowPtrA和csrColIndA定义)转换为通用BSR格式的稀疏矩阵C(由三个数组bsrValC、bsrRowPtrC和bsrColIndC定义)。
矩阵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的倍数,则会填充零。
该实现采用两步法进行转换。首先,用户分配bsrRowPtrC的mb+1个元素,并使用函数cusparseXcsr2gebsrNnz()确定每个块行的非零块列数。其次,用户从(nnzb=*nnzTotalDevHostPtr)或(nnzb=bsrRowPtrC[mb]-bsrRowPtrC[0])中获取nnzb(矩阵C的非零块列数),并分配bsrValC的nnzb*rowBlockDim*colBlockDim个元素和bsrColIndC的nnzb个整数。最后调用函数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图捕获。
例程 cusparse 具有以下属性:
如果
pBuffer != NULL,该例程不需要额外的存储空间。该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
块的存储格式,可以是 |
|
稀疏矩阵 |
|
稀疏矩阵 |
|
矩阵 |
|
|
|
一个包含矩阵 |
|
矩阵 |
|
矩阵 |
|
一个 |
|
一个块中的列数 |
|
由用户分配的缓冲区,其大小由 |
输出
|
|
|
包含矩阵 |
|
矩阵 |
|
矩阵 |
有关返回状态的描述,请参见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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
长度为 |
|
稀疏矩阵的非零元素数量(同时也是数组 |
|
矩阵 |
|
|
输出
|
包含每行起始位置及最后一行末尾加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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
包含每行起始位置及最后一行末尾加1的 |
|
稀疏矩阵的非零元素数量(同时也是数组 |
|
矩阵 |
|
|
输出
|
长度为 |
有关返回状态的描述,请参见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格式的稀疏矩阵(由三个数组csrVal、csrRowPtr和csrColInd定义)转换为CSC格式的稀疏矩阵(由数组cscVal、cscRowInd和cscColPtr定义)。结果矩阵也可以视为原始稀疏矩阵的转置。请注意,此例程也可用于将CSC格式的矩阵转换为CSR格式的矩阵。
该例程需要与非零值数量nnz成比例的额外存储空间。它在输出中始终提供相同的矩阵。
它相对于主机是异步执行的,可能在结果准备就绪之前就将控制权返回给主机上的应用程序。
函数 cusparseCsr2cscEx2_bufferSize() 返回 cusparseCsr2cscEx2() 所需工作空间的大小。用户需要分配一个此大小的缓冲区,并将该缓冲区作为参数传递给 cusparseCsr2cscEx2()。
如果 nnz == 0,那么 csrColInd、csrVal、cscVal 和 cscRowInd 可能为 NULL 值。在这种情况下,cscColPtr 的所有值都将被设置为 idxBase。
如果m == 0或n == 0,则不会检查指针,并且该例程返回CUSPARSE_STATUS_SUCCESS。
输入
|
cuSPARSE库上下文的句柄 |
|
CSR输入矩阵的行数;CSC输出矩阵的列数 |
|
CSR输入矩阵的列数;CSC输出矩阵的行数 |
|
CSR和CSC矩阵的非零元素数量 |
|
CSR矩阵的大小为 |
|
大小为 |
|
大小为 |
|
CSC矩阵的大小为 |
|
大小为 |
|
大小为 |
|
CSR和CSC矩阵的值类型 |
|
|
|
索引基准 |
|
算法实现。有关可能的值,请参见 |
|
|
|
指向工作区缓冲区的指针 |
cusparseCsr2cscEx2() 支持以下数据类型:
|
|---|
|
|
|
|
|
|
|
|
|
cusparseCsr2cscEx2() 支持以下算法 (cusparseCsr2CscAlg_t):
算法 |
备注 |
|---|---|
|
默认算法 |
操作 |
备注 |
|---|---|
|
计算CSC输出矩阵的"结构"(偏移量、行索引) |
|
计算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图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
指定按 |
|
矩阵 |
|
矩阵 |
|
矩阵 |
|
维度数组 |
|
稠密数组 |
输出
|
大小为 |
|
设备或主机内存中的非零元素总数 |
有关返回状态的描述,请参见cusparseStatus_t。
5.9.10. cusparseCreateIdentityPermutation() [已弃用]
> 该例程将在下一个主要版本中移除
cusparseStatus_t
cusparseCreateIdentityPermutation(cusparseHandle_t handle,
int n,
int* p);
此函数创建一个恒等映射。输出参数 p 通过 p = 0:1:(n-1) 表示这样的映射。
该函数通常与coosort、csrsort、cscsort配合使用。
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
地图的大小。 |
输出
|
|
|
|
|
维度为 |
有关返回状态的描述,请参见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\) 稀疏矩阵,通过三个数组 cooVals、cooRows 和 cooCols 以COO存储格式定义。
矩阵的基索引没有假设。coosort 对有符号整数使用稳定排序,因此 cooRows 或 cooCols 的值可以是负数。
此函数coosort()需要由coosort_bufferSizeExt()返回的缓冲区大小。pBuffer的地址必须是128字节的倍数。否则,将返回CUSPARSE_STATUS_INVALID_VALUE。
参数 P 既是输入也是输出。如果用户想要计算排序后的 cooVal,必须在 coosort() 之前将 P 设为 0:1:(nnz-1),而在 coosort() 之后,新的排序值数组满足 cooVal_sorted = cooVal(P)。
备注:维度m和n未被使用。如果用户不知道m或n的值,只需传入一个正数值。这种情况通常发生在用户先读取COO数组后,需要稍后确定维度m或n时。
如果
pBuffer != NULL,该例程不需要额外存储空间如果流序内存分配器可用,该例程支持异步执行
如果流序内存分配器可用,该例程支持CUDA图捕获
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
|
|
|
|
|
|
长度为 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
|
|
|
|
|
|
由 |
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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图捕获
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
长度为 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
|
|
|
长度为 |
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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图捕获
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
包含每列起始位置及最后一列结束位置加1的 |
|
|
|
|
|
长度为 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
|
|
|
长度为 |
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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格式,反之亦然。此操作是原地进行的。
该函数是csrsort和gthr的封装器。使用场景如下所示。
如果用户有一个未排序的CSR格式矩阵A,并基于这种特殊顺序(例如先对角线,再下三角,最后上三角)实现了自己的代码(可以是CPU或GPU内核),希望在调用CUSPARSE库时将其转换为CSR格式,然后在内核上进行其他操作时再转换回来。例如,假设用户想通过以下迭代方案求解线性系统Ax=b
该代码大量使用了稀疏矩阵向量乘法(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的要求是
原地操作。
置换向量
P被隐藏在一个不透明的结构中。在转换例程内部不使用
cudaMalloc。相反,用户必须显式提供缓冲区。在未排序的CSR和已排序的CSR之间进行转换可能需要多次操作,但该函数仅生成一次置换向量
P。该函数基于
csrsort、gather和scatter操作。
该操作名为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 用于恢复未排序形式。
例程 cusparse 具有以下属性:
如果
pBuffer != NULL,该例程不需要额外的存储空间如果流序内存分配器可用,该例程支持异步执行
如果流序内存分配器可用,该例程支持CUDA图捕获
如果pBuffer != NULL,则例程cusparse具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
该例程支持CUDA图捕获
以下表格描述了csr2csru_bufferSizeExt和csr2csru的参数。
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
|
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
使用 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
|
|
|
|
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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,其定义为
该实现采用两步法进行转换。首先,用户分配csrRowPtrC的m+1个元素,并使用函数pruneDense2csrNnz()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)或(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中获取nnzC(矩阵C的非零元素数量),并分配csrValC的nnzC个元素和csrColIndC的nnzC个整数。最后调用函数pruneDense2csr()完成转换。
用户必须通过调用pruneDense2csr_bufferSizeExt()获取pruneDense2csr()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneDense2csr()。
例程 cusparse 具有以下属性:
此函数需要临时额外存储空间,该空间在内部分配。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
例程 cusparse 具有以下特性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
维度为(lda, n)的数组。 |
|
|
|
|
|
一个用于删除A条目的值。 |
|
|
矩阵 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
矩阵 |
|
|
|
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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,其定义为
该实现采用两步法进行转换。首先,用户分配csrRowPtrC的m+1个元素,并使用函数pruneCsr2csrNnz()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)或(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中获取nnzC(矩阵C的非零元素数量),然后分配csrValC的nnzC个元素和csrColIndC的nnzC个整数。最后调用函数pruneCsr2csr()完成转换。
用户必须通过调用pruneCsr2csr_bufferSizeExt()获取pruneCsr2csr()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneCsr2csr()。
例程 cusparse 具有以下特性:
此函数需要临时额外存储空间,该空间在内部分配。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
例程 cusparse 具有以下特性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
|
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
一个用于删除A条目的值。 |
|
|
矩阵 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
矩阵 |
|
|
|
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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的绝对值进行排序。
步骤2:通过参数percentage选择阈值
步骤3:调用pruneDense2csr()函数并传入参数threshold。
该实现采用两步法进行转换。首先,用户分配csrRowPtrC的m+1个元素,并使用函数pruneDense2csrNnzByPercentage()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)或(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中收集nnzC(矩阵C的非零元素数量),并分配csrValC的nnzC个元素和csrColIndC的nnzC个整数。最后调用函数pruneDense2csrByPercentage()完成转换。
用户必须通过调用pruneDense2csrByPercentage_bufferSizeExt()获取pruneDense2csrByPercentage()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneDense2csrByPercentage()。
备注1: percentage 的值必须不大于100。否则将返回 CUSPARSE_STATUS_INVALID_VALUE。
备注2:A中的零值不会被忽略。所有条目都会被排序,包括零值。这与pruneCsr2csrByPercentage()的处理方式不同
该例程 cusparse 具有以下特性:
此函数需要临时额外存储空间,该空间在内部分配。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
例程 cusparse 具有以下属性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
维度为 (lda, n) 的数组。 |
|
|
|
|
|
百分比 <=100 且百分比 >= 0 |
|
|
矩阵 |
|
|
由用户分配的缓冲区;其大小由 |
输出
|
|
|
|
|
矩阵 |
|
|
<type> 矩阵 |
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
缓冲区的字节数。 |
有关返回状态的描述,请参见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的绝对值进行排序:
步骤2:通过参数percentage选择阈值:
步骤3:调用pruneCsr2csr()并传入参数threshold。
该实现采用两步法进行转换。首先,用户分配csrRowPtrC的m+1个元素,并使用函数pruneCsr2csrNnzByPercentage()确定每行的非零列数。其次,用户从(nnzC=*nnzTotalDevHostPtr)或(nnzC=csrRowPtrC[m]-csrRowPtrC[0])中收集nnzC(矩阵C的非零元素数量),并分配csrValC的nnzC个元素和csrColIndC的nnzC个整数。最后调用函数pruneCsr2csrByPercentage()完成转换。
用户必须通过调用pruneCsr2csrByPercentage_bufferSizeExt()获取pruneCsr2csrByPercentage()所需的缓冲区大小,分配缓冲区,并将缓冲区指针传递给pruneCsr2csrByPercentage()。
备注1: percentage的值不得超过100。否则将返回CUSPARSE_STATUS_INVALID_VALUE。
例程 cusparse 具有以下特性:
此函数需要临时额外存储空间,该空间在内部分配。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
例程 cusparse 具有以下属性:
该例程不需要额外的存储空间。
该例程支持异步执行。
该例程支持CUDA图捕获。
输入
|
|
|
|
|
cuSPARSE库上下文的句柄。 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
矩阵 |
|
|
<type> 矩阵 |
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
百分比 <=100 且百分比 >= 0 |
|
|
矩阵 |
|
|
由用户分配的缓冲区;大小由 |
输出
|
|
|
|
|
矩阵 |
|
|
<type> 矩阵 |
|
|
包含每行起始位置及最后一行末尾加1的 |
|
|
|
|
|
缓冲区的字节数 |
有关返回状态的描述,请参见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的定义如下:
对于cuComplex和cuDoubleComplex情况的一个关键假设是,这个容差值以实部形式给出。例如tol = 1e-8 + 0*i,我们提取的是cureal,也就是这个结构体的x分量。
此函数需要临时额外存储空间,该空间在内部分配。
如果流序内存分配器可用,该例程支持异步执行。
如果流序内存分配器可用,该例程支持CUDA图捕获。
输入
|
cuSPARSE库上下文的句柄。 |
|
矩阵 |
|
矩阵 |
|
CSR非压缩值数组 |
|
对应的输入未压缩行指针。 |
|
非负容差,用于判断一个数是否小于或等于该值。 |
输出
|
该数组包含每行中绝对值大于tol的元素数量。 |
|
绝对值大于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存储格式。
值 |
含义 |
|---|---|
|
矩阵以坐标(COO)格式存储,采用数组结构(SoA)布局 |
|
矩阵以压缩稀疏行(CSR)格式存储 |
|
该矩阵以压缩稀疏列(CSC)格式存储 |
|
矩阵以分块Ellpack(Blocked-ELL)格式存储 |
|
矩阵以切片椭圆压缩(Sliced-ELL)格式存储 |
|
矩阵以块稀疏行(BSR)格式存储 |
6.1.2. cusparseOrder_t
该类型表示稠密矩阵的内存布局。
值 |
含义 |
|---|---|
|
矩阵以行优先方式存储 |
|
矩阵以列优先方式存储 |
6.1.3. cusparseIndexType_t
此类型表示用于表示稀疏矩阵索引的索引类型。
值 |
含义 |
|---|---|
|
32位有符号整数 [0, 2^31 - 1] |
|
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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
密集向量描述符 |
|
主机 |
IN |
稠密向量的大小 |
|
设备 |
IN |
稠密向量的值。包含 |
|
主机 |
IN |
指定 |
cusparseCreateDnVec() 有以下限制:
values必须按照valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t。
有关返回状态的描述,请参考cusparseStatus_t。
6.2.2. cusparseDestroyDnVec()
cusparseStatus_t
cusparseDestroyDnVec(cusparseConstDnVecDescr_t dnVecDescr) // non-const descriptor supported
该函数释放为主机内存分配的稠密向量描述符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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
密集向量描述符 |
|
主机 |
输出 |
稠密向量的大小 |
|
设备 |
输出 |
稠密向量的值。包含 |
|
主机 |
输出 |
指定 |
有关返回状态的描述,请参考cusparseStatus_t。
6.2.4. cusparseDnVecGetValues()
cusparseStatus_t
cusparseDnVecGetValues(cusparseDnVecDescr_t dnVecDescr,
void** values)
cusparseStatus_t
cusparseConstDnVecGetValues(cusparseConstDnVecDescr_t dnVecDescr,
const void** values)
该函数返回稠密向量描述符dnVecDescr的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稠密向量描述符 |
|
设备 |
输出 |
稠密向量的值 |
有关返回状态的描述,请参考cusparseStatus_t。
6.2.5. cusparseDnVecSetValues()
cusparseStatus_t
cusparseDnVecSetValues(cusparseDnVecDescr_t dnVecDescr,
void* values)
此函数设置稠密向量描述符dnVecDescr的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
密集向量描述符 |
|
设备 |
IN |
稠密向量的值。包含 |
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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏向量描述符 |
|
主机 |
IN |
稀疏向量的大小 |
|
主机 |
IN |
稀疏向量中非零元素的数量 |
|
设备 |
IN |
稀疏向量的索引。包含 |
|
设备 |
IN |
稀疏向量的值。包含 |
|
主机 |
IN |
指定 |
|
主机 |
IN |
指定 |
|
主机 |
IN |
指定 |
cusparseCreateSpVec() 有以下限制条件:
indices和values必须分别与idxType和valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t。
有关返回状态的描述,请参见cusparseStatus_t。
6.3.2. cusparseDestroySpVec()
cusparseStatus_t
cusparseDestroySpVec(cusparseConstSpVecDescr_t spVecDescr) // non-const descriptor supported
该函数释放为主机内存分配的稀疏向量描述符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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏向量描述符 |
|
主机 |
输出 |
稀疏向量的大小 |
|
主机 |
输出 |
稀疏向量的非零元素数量 |
|
设备 |
输出 |
稀疏向量的索引。包含 |
|
设备 |
输出 |
稀疏向量的值。包含 |
|
主机 |
输出 |
指定 |
|
主机 |
输出 |
指定 |
|
主机 |
输出 |
指定 |
有关返回状态的描述,请参见cusparseStatus_t。
6.3.4. cusparseSpVecGetIndexBase()
cusparseStatus_t
cusparseSpVecGetIndexBase(cusparseConstSpVecDescr_t spVecDescr, // non-const descriptor supported
cusparseIndexBase_t* idxBase)
该函数返回稀疏向量描述符spVecDescr中的idxBase字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏向量描述符 |
|
主机 |
输出 |
指定 |
有关返回状态的描述,请参见cusparseStatus_t。
6.3.5. cusparseSpVecGetValues()
cusparseStatus_t
cusparseSpVecGetValues(cusparseSpVecDescr_t spVecDescr,
void** values)
cusparseStatus_t
cusparseConstSpVecGetValues(cusparseConstSpVecDescr_t spVecDescr,
const void** values)
该函数返回稀疏向量描述符spVecDescr的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏向量描述符 |
|
设备 |
输出 |
稀疏向量的值。包含 |
有关返回状态的描述,请参见cusparseStatus_t。
6.3.6. cusparseSpVecSetValues()
cusparseStatus_t
cusparseSpVecSetValues(cusparseSpVecDescr_t spVecDescr,
void* values)
此函数用于设置稀疏向量描述符spVecDescr中的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏向量描述符 |
|
设备 |
IN |
稀疏向量的值。包含 |
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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稠密矩阵描述符 |
|
主机 |
IN |
稠密矩阵的行数 |
|
主机 |
IN |
稠密矩阵的列数 |
|
主机 |
IN |
稠密矩阵的主维度 |
|
设备 |
IN |
稠密矩阵的值。包含 |
|
主机 |
IN |
指定 |
|
主机 |
IN |
指定稠密矩阵内存布局的枚举器 |
cusparseCreateDnMat() 有以下限制条件:
values必须按照valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅 cudaDataType_t。
有关返回状态的描述,请参考cusparseStatus_t。
6.4.2. cusparseDestroyDnMat()
cusparseStatus_t
cusparseDestroyDnMat(cusparseConstDnMatDescr_t dnMatDescr) // non-const descriptor supported
该函数释放为主机内存分配的稠密矩阵描述符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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稠密矩阵描述符 |
|
主机 |
输出 |
稠密矩阵的行数 |
|
主机 |
输出 |
稠密矩阵的列数 |
|
主机 |
输出 |
稠密矩阵的主维度 |
|
设备 |
输出 |
稠密矩阵的值。包含 |
|
主机 |
输出 |
指定 |
|
主机 |
输出 |
指定稠密矩阵内存布局的枚举器 |
有关返回状态的描述,请参考cusparseStatus_t。
6.4.4. cusparseDnMatGetValues()
cusparseStatus_t
cusparseDnMatGetValues(cusparseDnMatDescr_t dnMatDescr,
void** values)
cusparseStatus_t
cusparseConstDnMatGetValues(cusparseConstDnMatDescr_t dnMatDescr,
const void** values)
该函数返回稠密矩阵描述符dnMatDescr的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稠密矩阵描述符 |
|
设备 |
输出 |
稠密矩阵的值。包含 |
有关返回状态的描述,请参考cusparseStatus_t。
6.4.5. cusparseDnMatSetValues()
cusparseStatus_t
cusparseDnMatSetValues(cusparseDnMatDescr_t dnMatDescr,
void* values)
此函数用于设置稠密矩阵描述符dnMatDescr中的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稠密矩阵描述符 |
|
设备 |
IN |
稠密矩阵的值。包含 |
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的批次数和批次步长。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稠密矩阵描述符 |
|
主机 |
输出 |
稠密矩阵的批次数 |
|
主机 |
输出 |
矩阵与批次中下一个矩阵之间的地址偏移量 |
有关返回状态的描述,请参考cusparseStatus_t。
6.4.7. cusparseDnMatSetStridedBatch()
cusparseStatus_t
cusparseDnMatSetStridedBatch(cusparseDnMatDescr_t dnMatDescr,
int batchCount,
int64_t batchStride)
该函数用于设置稠密矩阵描述符dnMatDescr的批次数和批次步长。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稠密矩阵描述符 |
|
主机 |
IN |
密集矩阵的批次数 |
|
主机 |
IN |
矩阵与批次中下一个矩阵之间的地址偏移量。如果矩阵使用列优先布局,则 |
有关返回状态的描述,请参考cusparseStatus_t。
6.5. 稀疏矩阵API
本节介绍用于稀疏矩阵描述符的cuSPARSE辅助函数。
有关存储格式的详细描述,请参阅COO、CSR、CSC、SELL、BSR和Blocked-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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的行数 |
|
主机 |
IN |
稀疏矩阵的列数 |
|
主机 |
IN |
稀疏矩阵的非零元素数量 |
|
设备 |
IN |
稀疏矩阵的行索引。包含 |
|
设备 |
IN |
稀疏矩阵的列索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
cusparseCreateCoo() 有以下限制条件:
cooRowInd,cooColInd和cooValues必须按照cooIdxType,cooIdxType和valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的行数 |
|
主机 |
输出 |
稀疏矩阵的列数 |
|
主机 |
输出 |
稀疏矩阵的非零元素数量 |
|
设备 |
输出 |
稀疏矩阵的行索引。包含 |
|
设备 |
输出 |
稀疏矩阵的列索引。包含 |
|
设备 |
输出 |
稀疏矩阵的值。包含 |
|
主机 |
输出 |
|
|
主机 |
输出 |
|
|
主机 |
输出 |
|
有关返回状态的描述,请参见cusparseStatus_t。
6.5.1.3. cusparseCooSetPointers()
cusparseStatus_t
cusparseCooSetPointers(cusparseSpMatDescr_t spMatDescr,
void* cooRows,
void* cooColumns,
void* cooValues)
此函数用于设置稀疏矩阵描述符spMatDescr的指针。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
设备 |
IN |
稀疏矩阵的行索引。包含 |
|
设备 |
IN |
稀疏矩阵的列索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
cusparseCooSetPointers() 有以下限制条件:
cooRows,cooColumns和cooValues必须按照spMatDescr中指定的对应数据类型大小进行对齐。有关数据类型的描述,请参阅 cudaDataType_t。
有关返回状态的描述,请参见cusparseStatus_t。
6.5.1.4. cusparseCooSetStridedBatch()
cusparseStatus_t
cusparseCooSetStridedBatch(cusparseSpMatDescr_t spMatDescr,
int batchCount,
int64_t batchStride)
此函数用于设置稀疏矩阵描述符spMatDescr中的batchCount和batchStride字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的批次数 |
|
主机 |
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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的行数 |
|
主机 |
IN |
稀疏矩阵的列数 |
|
主机 |
IN |
稀疏矩阵的非零元素数量 |
|
设备 |
IN |
稀疏矩阵的行偏移量。包含 |
|
设备 |
IN |
稀疏矩阵的列索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
cusparseCreateCsr() 有以下限制条件:
csrRowOffsets、csrColInd和csrValues必须分别按照csrRowOffsetsType、csrColIndType和valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的行数 |
|
主机 |
输出 |
稀疏矩阵的列数 |
|
主机 |
输出 |
稀疏矩阵的非零元素数量 |
|
设备 |
输出 |
稀疏矩阵的行偏移量。包含 |
|
设备 |
输出 |
稀疏矩阵的列索引。包含 |
|
设备 |
输出 |
稀疏矩阵的值。包含 |
|
主机 |
输出 |
|
|
主机 |
输出 |
|
|
主机 |
输出 |
|
|
主机 |
输出 |
|
有关返回状态的描述,请参见cusparseStatus_t。
6.5.2.3. cusparseCsrSetPointers()
cusparseStatus_t
cusparseCsrSetPointers(cusparseSpMatDescr_t spMatDescr,
void* csrRowOffsets,
void* csrColInd,
void* csrValues)
此函数用于设置稀疏矩阵描述符spMatDescr的指针。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
设备 |
IN |
稀疏矩阵的行偏移量。包含 |
|
设备 |
IN |
稀疏矩阵的列索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
cusparseCsrSetPointers() 有以下限制条件:
csrRowOffsets、csrColInd和csrValues必须按照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中的batchCount和batchStride字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的批次数 |
|
主机 |
IN |
行偏移数组中连续批次之间的地址偏移量 |
|
主机 |
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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的行数 |
|
主机 |
IN |
稀疏矩阵的列数 |
|
主机 |
IN |
稀疏矩阵的非零元素数量 |
|
设备 |
IN |
稀疏矩阵的列偏移量。包含 |
|
设备 |
IN |
稀疏矩阵的行索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
cusparseCreateCsc() 有以下限制条件:
cscColOffsets、cscRowInd和cscValues必须分别按照cscColOffsetsType、cscRowIndType和valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的行数 |
|
主机 |
输出 |
稀疏矩阵的列数 |
|
主机 |
输出 |
稀疏矩阵的非零元素数量 |
|
设备 |
输出 |
稀疏矩阵的列偏移量。包含 |
|
设备 |
输出 |
稀疏矩阵的行索引。包含 |
|
设备 |
输出 |
稀疏矩阵的值。包含 |
|
主机 |
输出 |
|
|
主机 |
输出 |
|
|
主机 |
输出 |
|
|
主机 |
输出 |
|
有关返回状态的描述,请参见cusparseStatus_t。
6.5.3.3. cusparseCscSetPointers()
cusparseStatus_t
cusparseCscSetPointers(cusparseSpMatDescr_t spMatDescr,
void* cscColOffsets,
void* cscRowInd,
void* cscValues)
此函数用于设置稀疏矩阵描述符spMatDescr的指针。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
设备 |
IN |
稀疏矩阵的列偏移量。包含 |
|
设备 |
IN |
稀疏矩阵的行索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
cusparseCscSetPointers() 有以下限制条件:
cscColOffsets、cscRowInd和cscValues必须按照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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的行数 |
|
主机 |
IN |
稀疏矩阵的列数 |
|
主机 |
IN |
ELL块的大小 |
|
主机 |
IN |
Blocked-Ellpack格式的实际列数( |
|
设备 |
IN |
Blocked-ELL列索引。包含 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
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的字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的行数 |
|
主机 |
输出 |
稀疏矩阵的列数 |
|
主机 |
输出 |
ELL块的大小 |
|
主机 |
输出 |
Blocked-Ellpack格式的实际列数 |
|
设备 |
输出 |
ELL块的列索引。包含 |
|
设备 |
输出 |
稀疏矩阵的值。包含 |
|
主机 |
输出 |
|
|
主机 |
输出 |
|
|
主机 |
输出 |
|
有关返回状态的描述,请参见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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的行数 |
|
主机 |
IN |
稀疏矩阵的列数 |
|
主机 |
IN |
稀疏矩阵中的非零元素数量 |
|
主机 |
IN |
|
|
主机 |
IN |
每个切片中的行数 |
|
设备 |
IN |
稀疏矩阵的切片偏移量。大小为\(\left \lceil{\frac{rows}{sliceSize}}\right \rceil + 1\)的数组 |
|
设备 |
IN |
稀疏矩阵的列索引。大小为 |
|
设备 |
IN |
稀疏矩阵的值。大小为 |
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
注意
Sliced Ellpack列数组sellColInd包含-1值用于指示填充条目。
cusparseCreateSlicedEll() 有以下限制条件:
sellSliceOffsets、sellColInd和sellValues必须分别与sellSliceOffsetsType、sellColIndType和valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅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。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的块行数 |
|
主机 |
IN |
稀疏矩阵的块列数 |
|
主机 |
IN |
稀疏矩阵的块数 |
|
主机 |
IN |
每个块的行数 |
|
主机 |
IN |
每个块的列数 |
|
设备 |
IN |
稀疏矩阵的行块偏移量。大小为 |
|
设备 |
IN |
稀疏矩阵的块列索引。大小为 |
|
设备 |
IN |
稀疏矩阵的值。大小为 |
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
|
|
主机 |
IN |
指定每个块中值的内存布局的枚举器 |
cusparseCreateBsr() 有以下限制条件:
bsrRowOffsets、bsrColInd和bsrValues必须分别与bsrRowOffsetsType、bsrColIndType和valueType指定的数据类型大小对齐。有关数据类型的描述,请参阅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中的batchCount和batchStride字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
IN |
稀疏矩阵的批次数 |
|
主机 |
IN |
行偏移数组中连续批次之间的地址偏移量 |
|
主机 |
IN |
列数组连续批次之间的地址偏移量 |
|
主机 |
IN |
值数组中连续批次之间的地址偏移量 |
有关返回状态的描述,请参见cusparseStatus_t。
6.5.7. 所有稀疏格式
6.5.7.1. cusparseDestroySpMat()
cusparseStatus_t
cusparseDestroySpMat(cusparseConstSpMatDescr_t spMatDescr) // non-const descriptor supported
该函数释放为稀疏矩阵描述符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的尺寸。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的行数 |
|
主机 |
输出 |
稀疏矩阵的列数 |
|
主机 |
输出 |
稀疏矩阵的非零元素数量 |
有关返回状态的描述,请参见cusparseStatus_t。
6.5.7.3. cusparseSpMatGetFormat()
cusparseStatus_t
cusparseSpMatGetFormat(cusparseConstSpMatDescr_t spMatDescr, // non-const descriptor supported
cusparseFormat_t* format)
该函数返回稀疏矩阵描述符spMatDescr的format字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的存储格式 |
有关返回状态的描述,请参见cusparseStatus_t。
6.5.7.4. cusparseSpMatGetIndexBase()
cusparseStatus_t
cusparseSpMatGetIndexBase(cusparseConstSpMatDescr_t spMatDescr, // non-const descriptor supported
cusparseIndexBase_t* idxBase)
该函数返回稀疏矩阵描述符spMatDescr中的idxBase字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的索引基数 |
有关返回状态的描述,请参见cusparseStatus_t。
6.5.7.5. cusparseSpMatGetValues()
cusparseStatus_t
cusparseSpMatGetValues(cusparseSpMatDescr_t spMatDescr,
void** values)
cusparseStatus_t
cusparseConstSpMatGetValues(cusparseConstSpMatDescr_t spMatDescr,
const void** values)
该函数返回稀疏矩阵描述符spMatDescr的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
设备 |
输出 |
稀疏矩阵的值。包含 |
有关返回状态的描述,请参见cusparseStatus_t。
6.5.7.6. cusparseSpMatSetValues()
cusparseStatus_t
cusparseSpMatSetValues(cusparseSpMatDescr_t spMatDescr,
void* values)
此函数用于设置稀疏矩阵描述符spMatDescr中的values字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
设备 |
IN |
稀疏矩阵的值。包含 |
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字段。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
输出 |
稀疏矩阵的批次数 |
有关返回状态的描述,请参见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的属性。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
稀疏矩阵描述符 |
|
主机 |
IN |
属性枚举器 |
|
主机 |
输出 |
属性值 |
|
主机 |
IN |
属性的安全字节大小 |
属性 |
含义 |
可选值 |
|---|---|---|
|
指示矩阵的下三角或上三角部分是否以稀疏存储方式存储 |
|
|
指示矩阵对角线元素是否为1 |
|
有关返回状态的描述,请参见cusparseStatus_t。
6.5.7.9. cusparseSpMatSetAttribute()
cusparseStatus_t
cusparseSpMatSetAttribute(cusparseSpMatDescr_t spMatDescr,
cusparseSpMatAttribute_t attribute,
const void* data,
size_t dataSize)
该函数用于设置稀疏矩阵描述符spMatDescr的属性
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
输出 |
稀疏矩阵描述符 |
|
主机 |
IN |
属性枚举器 |
|
主机 |
IN |
属性值 |
|
主机 |
IN |
属性的安全字节大小 |
属性 |
含义 |
可选值 |
|---|---|---|
|
指示矩阵的下三角或上三角部分是否以稀疏存储方式存储 |
|
|
指示矩阵对角线元素是否为1 |
|
有关返回状态的描述,请参见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的和。
换句话说,
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]
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机或设备 |
IN |
\(\alpha\) 用于计算类型乘法的标量 |
|
主机 |
IN |
稀疏向量 |
|
主机或设备 |
IN |
\(\beta\) 用于计算类型乘法的标量 |
|
主机 |
输入/输出 |
密集向量 |
cusparseAxpby 支持以下索引类型来表示稀疏向量 vecX:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseAxpby 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
|
|---|---|---|
|
|
|
|
||
|
|
[已弃用] |
|
[已弃用] |
cusparseAxpby() 有以下限制条件:
表示稀疏向量
vecX的数组必须按16字节对齐
cusparseAxpby() 具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
如果稀疏向量
vecX的索引各不相同,则为每次运行提供确定性(逐位)结果该例程允许
indices的vecX无需排序
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]]
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
输出 |
稀疏向量 |
|
主机 |
IN |
密集向量 |
cusparseGather 支持以下索引类型来表示稀疏向量 vecX:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseGather 支持以下数据类型:
|
|---|
|
|
|
|
|
|
|
|
cusparseGather() 有以下限制条件:
表示稀疏向量
vecX的数组必须按16字节对齐
cusparseGather() 具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
如果稀疏向量
vecX的索引各不相同,则为每次运行提供确定性(逐位)结果该例程允许
indices对vecX进行无序排列
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]
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
稀疏向量 |
|
主机 |
输出 |
密集向量 |
cusparseScatter 支持以下索引类型来表示稀疏向量 vecX:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseScatter 支持以下数据类型:
|
|---|
|
|
|
|
|
|
|
|
|
cusparseScatter() 有以下限制条件:
表示稀疏向量
vecX的数组必须16字节对齐
cusparseScatter() 具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
如果稀疏向量
vecX的索引各不相同,则为每次运行提供确定性(逐位)结果该例程允许
indices对vecX进行无序排列
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)
该函数计算吉文斯旋转矩阵
转换为稀疏向量 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]]
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机或设备 |
IN |
旋转矩阵的余弦元素 |
|
主机 |
输入/输出 |
稀疏向量 |
|
主机或设备 |
IN |
旋转矩阵的正弦元素 |
|
主机 |
输入/输出 |
密集向量 |
cusparseRot 支持以下索引类型来表示稀疏向量 vecX:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseRot 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
|
|---|---|---|
|
|
|
|
||
|
|
[已弃用] |
|
[已弃用] |
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 = 0;
for i=0 to nnz-1
result += op(X_values[i]) * Y[X_indices[i]]

函数 cusparseSpVV_bufferSize() 返回 cusparseSpVV() 所需工作空间的大小
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
稀疏向量 |
|
主机 |
IN |
密集向量 |
|
主机或设备 |
输出 |
结果的点积 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
输出 |
|
|
设备 |
IN |
指向至少 |
cusparseSpVV 支持以下索引类型来表示稀疏向量 vecX:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
当前cusparseSpVV支持的数据类型组合如下:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
注意事项 |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
[已弃用] |
|
|
[已弃用] |
cusparseSpVV() 有以下限制条件:
表示稀疏向量
vecX的数组必须16字节对齐
cusparseSpVV() 具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
如果稀疏向量
vecX的索引各不相同,则为每次运行提供确定性(逐位)结果该例程允许
indices对vecX进行无序排列
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的乘法运算
其中
op(A)是一个大小为 \(m \times k\) 的稀疏矩阵X是一个大小为 \(k\) 的密集向量Y是一个大小为 \(m\) 的密集向量\(\alpha\) 和 \(\beta\) 是标量
同样,对于矩阵 A

函数 cusparseSpMV_bufferSize() 返回 cusparseSpMV_preprocess() 和 cusparseSpMV() 所需工作空间的大小
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机或设备 |
IN |
\(\alpha\) 用于与类型 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
IN |
密集向量 |
|
主机或设备 |
IN |
\(\beta\) 用于与类型 |
|
主机 |
输入/输出 |
密集向量 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
IN |
指向至少 |
当前支持的稀疏矩阵格式如下:
CUSPARSE_FORMAT_COOCUSPARSE_FORMAT_CSRCUSPARSE_FORMAT_CSCCUSPARSE_FORMAT_SLICED_ELL
cusparseSpMV 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseSpMV 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
|
注意事项 |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|||
|
|||
|
|
||
|
|
||
|
|
|
|
|
|
[已弃用] |
|
|
|
[已弃用] |
|
|
|---|---|
|
|
混合常规/复杂计算:
|
|
|---|---|
|
|
|
|
注意:CUDA_R_16F、CUDA_R_16BF、CUDA_C_16F和CUDA_C_16BF数据类型始终意味着混合精度计算。
cusparseSpMV() 支持以下算法:
算法 |
备注 |
|---|---|
|
适用于任何稀疏矩阵格式的默认算法。 |
|
COO稀疏矩阵格式的默认算法。使用相同输入参数的不同运行过程中可能会产生略微不同的结果。 |
|
为每次运行提供确定性(逐位)结果。如果 |
|
CSR/CSC稀疏矩阵格式的默认算法。使用相同的输入参数在不同运行时可能会产生略微不同的结果。 |
|
为每次运行提供确定性(逐位)结果。如果 |
|
Sliced Ellpack稀疏矩阵格式的默认算法。每次运行提供确定性(按位)结果。 |
调用cusparseSpMV_preprocess()是可选的。
它可以加速后续对cusparseSpMV()的调用。
当需要多次使用相同的稀疏模式(matA)调用cusparseSpMV()时,这个预处理函数会很有用。
调用cusparseSpMV_preprocess()时使用buffer会使该缓冲区在matA的SpMV调用中处于"激活"状态。
后续使用matA和激活缓冲区调用cusparseSpMV()时,
所有参数值必须与调用cusparseSpMV_preprocess()时保持一致。
例外情况是:alpha、beta、vecX、vecY以及matA的值(但不包括索引)可以不同。
重要的是,自调用cusparseSpMV_preprocess()以来,缓冲区内容必须保持未修改状态。
当使用matA及其激活缓冲区调用cusparseSpMV()时,可能会从缓冲区读取加速数据。
再次调用cusparseSpMV_preprocess()并传入matA和新缓冲区时,将使新缓冲区变为活动状态,同时遗忘先前活动的缓冲区并将其置为非活动状态。对于cusparseSpMV(),每个稀疏矩阵同一时间只能有一个活动缓冲区。若要实现单个稀疏矩阵拥有多个活动缓冲区的效果,可创建多个矩阵句柄(这些句柄都指向相同的索引和值缓冲区),然后为每个句柄使用不同的工作区缓冲区各调用一次cusparseSpMV_preprocess()。
调用cusparseSpMV()时使用非活动缓冲区始终是被允许的。但在这种情况下,预处理可能不会带来加速效果。
出于线程安全的考虑,
cusparseSpMV_preprocess()正在写入matA的内部状态。
性能说明:
CUSPARSE_SPMV_COO_ALG1和CUSPARSE_SPMV_CSR_ALG1相比CUSPARSE_SPMV_COO_ALG2和CUSPARSE_SPMV_CSR_ALG2能提供更高的性能。通常来说,
opA == CUSPARSE_OPERATION_NON_TRANSPOSE比opA != CUSPARSE_OPERATION_NON_TRANSPOSE快3倍。使用
cusparseSpMV_preprocess()有助于提升CSR格式下cusparseSpMV()的性能。当我们需要用同一个矩阵多次运行cusparseSpMV()时特别有益(cusparseSpMV_preprocess()只需执行一次)。
cusparseSpMV() 具有以下特性:
该例程需要为CSR/CSC格式(所有算法)以及使用
CUSPARSE_SPMV_COO_ALG2算法的COO格式提供额外存储空间。仅为
CUSPARSE_SPMV_COO_ALG2和CUSPARSE_SPMV_CSR_ALG2算法,以及opA == CUSPARSE_OPERATION_NON_TRANSPOSE的情况,提供每次运行的确定性(逐位)结果。该例程支持异步执行。
当
beta == 0时,compute-sanitizer可能会对此例程报告虚假的竞态条件。这是出于优化目的,不会影响计算的正确性。该例程允许
matA的索引不排序。
cusparseSpMV() 支持以下 优化:
CUDA图捕获
硬件内存压缩
有关返回状态的描述,请参见cusparseStatus_t。
请访问cuSPARSE库示例 - cusparseSpMV CSR和cusparseSpMV 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(A)是一个大小为 \(m \times m\) 的稀疏方阵X是一个大小为 \(m\) 的密集向量Y是一个大小为 \(m\) 的密集向量\(\alpha\) 是一个标量
同样,对于矩阵 A

函数 cusparseSpSV_bufferSize() 返回 cusparseSpSV_analysis() 和 cusparseSpSV_solve() 所需的工作空间大小。
函数 cusparseSpSV_analysis() 执行分析阶段,而 cusparseSpSV_solve() 则执行稀疏三角线性系统的求解阶段。
不透明数据结构 spsvDescr 用于在所有函数之间共享信息。
函数 cusparseSpSV_updateMatrix() 用新的矩阵值更新 spsvDescr。
该例程支持输入矩阵的任意稀疏性,但在计算中仅考虑上三角或下三角部分。
注意:所有参数在cusparseSpSV API调用之间必须保持一致,且在cusparseSpSV_analysis()和cusparseSpSV_solve()之间不得修改矩阵描述和externalBuffer。函数cusparseSpSV_updateMatrix()可用于更新存储在spsvDescr不透明数据结构中的稀疏矩阵值。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机或设备 |
IN |
\(\alpha\) 用于与类型 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
IN |
密集向量 |
|
主机 |
输入/输出 |
密集向量 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
输入/输出 |
指向至少 |
|
主机 |
输入/输出 |
用于存储三个步骤间使用的内部数据的不透明描述符 |
当前支持的稀疏矩阵格式如下:
CUSPARSE_FORMAT_CSRCUSPARSE_FORMAT_COOCUSPARSE_FORMAT_SLICED_ELL
cusparseSpSV() 支持以下形状和属性:
CUSPARSE_FILL_MODE_LOWER和CUSPARSE_FILL_MODE_UPPER填充模式CUSPARSE_DIAG_TYPE_NON_UNIT和CUSPARSE_DIAG_TYPE_UNIT对角线类型
填充模式和对角线类型可以通过cusparseSpMatSetAttribute()进行设置。
cusparseSpSV() 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseSpSV() 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
cusparseSpSV() 支持以下算法:
算法 |
备注 |
|---|---|
|
默认算法 |
cusparseSpSV() 具有以下特性:
该例程在分析阶段需要额外的存储空间,其大小与稀疏矩阵的非零元素数量成正比
为求解阶段
cusparseSpSV_solve()的每次运行提供确定性(逐位)结果该例程支持原地操作
cusparseSpSV_solve()例程支持异步执行cusparseSpSV_bufferSize()和cusparseSpSV_analysis()例程允许为vecX和vecY传入NULL值该例程允许
matA的索引不排序
cusparseSpSV() 支持以下 优化:
CUDA图捕获
硬件内存压缩
cusparseSpSV_updateMatrix() 在调用分析阶段后更新稀疏矩阵。该函数支持以下更新策略 (updatePart):
策略 |
备注 |
|---|---|
|
使用 |
|
使用存储在 |
有关返回状态的描述,请参见cusparseStatus_t。
请访问cuSPARSE Library Samples - cusparseSpSV CSR和cuSPARSE 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的乘法运算。
其中
op(A)是一个大小为 \(m \times k\) 的稀疏矩阵op(B)是一个大小为 \(k \times n\) 的稠密矩阵C是一个大小为 \(m \times n\) 的密集矩阵\(\alpha\) 和 \(\beta\) 是标量
该例程也可用于执行稠密矩阵与稀疏矩阵的乘法,只需切换稠密矩阵的布局:
其中 \(\mathbf{B}_{C}\) 和 \(\mathbf{C}_{C}\) 表示列优先布局,而 \(\mathbf{B}_{R}\) 和 \(\mathbf{C}_{R}\) 表示行优先布局
同样地,对于矩阵 A 和 B


当使用稀疏矩阵A的(共轭)转置时,该例程在相同输入参数的不同运行中可能会产生略微不同的结果。
函数 cusparseSpMM_bufferSize() 返回 cusparseSpMM() 所需工作空间的大小
调用cusparseSpMM_preprocess()是可选的。
它可以加速后续对cusparseSpMM()的调用。
当使用相同的稀疏模式(matA)多次调用cusparseSpMM()时,这个函数很有用。
它对CUSPARSE_SPMM_CSR_ALG1或CUSPARSE_SPMM_CSR_ALG3能提供性能优势。
对于所有其他格式和算法则没有效果。
调用cusparseSpMM_preprocess()时使用buffer会使该缓冲区在matA的SpMM调用中处于"激活"状态。
后续使用matA和激活缓冲区调用cusparseSpMM()时,
所有参数值必须与调用cusparseSpMM_preprocess()时保持一致。
例外情况包括:alpha、beta、matX、matY以及matA的值(但不包括索引)可以不同。
重要的是,自调用cusparseSpMM_preprocess()后,缓冲区内容必须保持未被修改。
当使用matA及其激活缓冲区调用cusparseSpMM()时,可能会从缓冲区读取加速数据。
再次调用cusparseSpMM_preprocess()并传入matA和新缓冲区时,将使新缓冲区变为活动状态,同时遗忘先前活动的缓冲区并将其置为非活动状态。对于cusparseSpMM(),每个稀疏矩阵同一时间只能有一个活动缓冲区。若要实现单个稀疏矩阵拥有多个活动缓冲区的效果,可创建多个矩阵句柄(这些句柄都指向相同的索引和值缓冲区),然后为每个句柄使用不同的工作区缓冲区各调用一次cusparseSpMM_preprocess()。
调用cusparseSpMM()时使用非活动缓冲区始终是被允许的。但在这种情况下,预处理可能不会带来加速效果。
出于线程安全的考虑,
cusparseSpMM_preprocess()会写入matA的内部状态。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
操作 |
|
主机或设备 |
IN |
\(\alpha\) 用于与类型 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
IN |
稠密矩阵 |
|
主机或设备 |
IN |
\(\beta\) 用于与类型 |
|
主机 |
输入/输出 |
稠密矩阵 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
IN |
指向至少 |
cusparseSpMM 支持以下稀疏矩阵格式:
CUSPARSE_FORMAT_COOCUSPARSE_FORMAT_CSRCUSPARSE_FORMAT_CSCCUSPARSE_FORMAT_BSRCUSPARSE_FORMAT_BLOCKED_ELL
(1) |
COO/CSR/CSC/BSR格式 |
cusparseSpMM 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseSpMM 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
|
|
|---|---|---|---|
|
|
|
|
|
|
|
|
|
|||
|
|||
|
|
||
|
|
||
|
|
|
[已弃用] |
|
|
[已弃用] |
注意:CUDA_R_16F、CUDA_R_16BF、CUDA_C_16F和CUDA_C_16BF数据类型始终意味着混合精度计算。
cusparseSpMM 支持以下算法:
算法 |
备注 |
|---|---|
|
适用于任何稀疏矩阵格式的默认算法 |
|
COO稀疏矩阵格式的算法1
|
|
COO稀疏矩阵格式的算法2
|
|
COO稀疏矩阵格式的算法3
|
|
COO稀疏矩阵格式的算法4
|
|
CSR/CSC稀疏矩阵格式的算法1
|
|
针对CSR/CSC稀疏矩阵格式的算法2
|
|
针对CSR/CSC稀疏矩阵格式的算法3
|
|
BSR稀疏矩阵格式的算法1
|
性能说明:
行优先布局比列优先布局提供更高的性能
CUSPARSE_SPMM_COO_ALG4和CUSPARSE_SPMM_CSR_ALG2应与行优先布局一起使用,而CUSPARSE_SPMM_COO_ALG1、CUSPARSE_SPMM_COO_ALG2、CUSPARSE_SPMM_COO_ALG3和CUSPARSE_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}\)
批次数及其步长可以通过使用cusparseCooSetStridedBatch、cusparseCsrSetStridedBatch和cusparseDnMatSetStridedBatch来设置。cusparseSpMM()的最大批次数为65,535。
cusparseSpMM() 具有以下特性:
该例程对于
CUSPARSE_SPMM_COO_ALG1、CUSPARSE_SPMM_COO_ALG3、CUSPARSE_SPMM_COO_ALG4和CUSPARSE_SPMM_BSR_ALG1不需要额外的存储空间该例程支持异步执行
仅为
CUSPARSE_SPMM_COO_ALG2、CUSPARSE_SPMM_CSR_ALG3和CUSPARSE_SPMM_BSR_ALG1算法提供每次运行的确定性(逐位)结果compute-sanitizer可能会报告此例程的虚假竞争条件。这是出于优化目的,不会影响计算的正确性该例程允许
matA的索引不排序
cusparseSpMM() 支持以下 优化:
CUDA图捕获
硬件内存压缩
请访问cuSPARSE库示例 - cusparseSpMM CSR和cusparseSpMM COO查看代码示例。如需批量计算,请访问cusparseSpMM CSR批量版和cusparseSpMM COO批量版。
(2) |
分块ELLPACK格式 |
cusparseSpMM 支持以下数据类型用于 CUSPARSE_FORMAT_BLOCKED_ELL 格式,以及以下GPU架构以利用NVIDIA Tensor Cores:
|
|
|
|
|
|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
||||
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cusparseSpMM 支持以下使用 CUSPARSE_FORMAT_BLOCKED_ELL 格式的算法:
算法 |
备注 |
|---|---|
|
适用于任何稀疏矩阵格式的默认算法 |
|
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的乘法运算。
其中
op(A)是一个大小为 \(m \times k\) 的稀疏矩阵op(B)是一个大小为 \(k \times n\) 的稠密矩阵C是一个大小为 \(m \times n\) 的密集矩阵\(\oplus\)、\(\otimes\)和\(\text{epilogue}\)分别是自定义的加法、乘法和收尾运算符。
同样地,对于矩阵 A 和 B


目前仅支持 opA == CUSPARSE_OPERATION_NON_TRANSPOSE
函数 cusparseSpMMOp_createPlan() 返回 cusparseSpMMOp() 所需的工作空间大小和编译后的内核
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
IN |
稠密矩阵 |
|
主机 |
输入/输出 |
稠密矩阵 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
IN |
计算算法 |
|
主机 |
IN |
指向包含自定义add运算符的NVVM缓冲区的指针 |
|
主机 |
IN |
|
|
主机 |
IN |
指向包含自定义mul运算符的NVVM缓冲区的指针 |
|
主机 |
IN |
|
|
主机 |
IN |
指向包含自定义尾声运算符的NVVM缓冲区的指针 |
|
主机 |
IN |
|
|
主机 |
输出 |
|
操作符必须具有以下签名和返回类型
__device__ <computetype> add_op(<computetype> value1, <computetype> value2);
__device__ <computetype> mul_op(<computetype> value1, <computetype> value2);
__device__ <computetype> epilogue(<computetype> value1, <computetype> value2);
可以是 float、double、cuComplex、cuDoubleComplex 或 int 类型之一,
cusparseSpMMOp 支持以下稀疏矩阵格式:
CUSPARSE_FORMAT_CSR
cusparseSpMMOp 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseSpMMOp 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
|
|---|---|---|
|
|
|
|
|
|
|
||
|
||
|
|
|
|
|
cusparseSpMMOp 支持以下算法:
算法 |
备注 |
|---|---|
|
适用于任何稀疏矩阵格式的默认算法 |
性能说明:
行优先布局比列优先布局提供更高的性能。
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(A)是一个大小为 \(m \times m\) 的稀疏方阵op(B)是一个大小为 \(m \times n\) 的密集矩阵C是一个大小为 \(m \times n\) 的密集矩阵\(\alpha\) 是一个标量
同样,对于矩阵 A


函数 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
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
操作 |
|
主机或设备 |
IN |
\(\alpha\) 用于与类型 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
IN |
稠密矩阵 |
|
主机 |
输入/输出 |
稠密矩阵 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
输入/输出 |
指向至少 |
|
主机 |
输入/输出 |
用于存储三个步骤间使用的内部数据的不透明描述符 |
当前支持的稀疏矩阵格式如下:
CUSPARSE_FORMAT_CSRCUSPARSE_FORMAT_COO
cusparseSpSM() 支持以下形状和属性:
CUSPARSE_FILL_MODE_LOWER和CUSPARSE_FILL_MODE_UPPER填充模式CUSPARSE_DIAG_TYPE_NON_UNIT和CUSPARSE_DIAG_TYPE_UNIT对角线类型
填充模式和对角线类型可以通过cusparseSpMatSetAttribute()进行设置。
cusparseSpSM() 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseSpSM() 支持以下数据类型:
统一精度计算:
|
|---|
|
|
|
|
cusparseSpSM() 支持以下算法:
算法 |
备注 |
|---|---|
|
默认算法 |
cusparseSpSM() 具有以下特性:
该例程不需要额外的存储空间
为求解阶段
cusparseSpSM_solve()的每次运行提供确定性(逐位)结果cusparseSpSM_solve()例程支持异步执行该例程支持原地操作。必须为稠密矩阵
matB和matC的values参数提供相同的设备指针。所有其他稠密矩阵描述符参数(例如order)可以独立设置cusparseSpSM_bufferSize()和cusparseSpSM_analysis()例程接受matB和matC的NULL值描述符。这两个例程不接受NULL描述符该例程允许
matA的索引不排序
cusparseSpSM() 支持以下 优化:
CUDA图捕获
硬件内存压缩
cusparseSpSM_updateMatrix() 在调用分析阶段后更新稀疏矩阵。该函数支持以下更新策略 (updatePart):
策略 |
备注 |
|---|---|
|
使用 |
|
使用存储在 |
有关返回状态的描述,请参见cusparseStatus_t。
请访问cuSPARSE Library Samples - cusparseSpSM CSR和cuSPARSE 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)
该函数执行matA与matB的乘法运算,然后与matC的稀疏模式进行逐元素相乘。形式上,它执行以下操作:
其中
op(A)是一个大小为 \(m \times k\) 的稠密矩阵op(B)是一个大小为 \(k \times n\) 的稠密矩阵C是一个大小为 \(m \times n\) 的稀疏矩阵\(\alpha\) 和 \(\beta\) 是标量
\(\circ\) 表示哈达玛(逐元素)矩阵乘积,而 \({spy}\left( \mathbf{C} \right) 是
C的结构稀疏模式矩阵,其定义为:

同样地,对于矩阵 A 和 B


函数 cusparseSDDMM_bufferSize() 返回 cusparseSDDMM 或 cusparseSDDMM_preprocess 所需的工作空间大小。
调用cusparseSDDMM_preprocess()是可选的。
它可以加速后续对cusparseSDDMM()的调用。
当cusparseSDDMM()需要多次使用相同的稀疏模式(matC)进行调用时,这个预处理函数会很有帮助。
使用buffer调用cusparseSDDMM_preprocess()会使该缓冲区对matC的SDDMM调用变为"活跃"状态。
后续使用matC和活跃缓冲区调用cusparseSDDMM()时,所有参数值必须与调用cusparseSDDMM_preprocess()时保持一致。
例外情况是:alpha、beta、matA、matB以及matC的值(但不包括索引)可以不同。
重要的是,自调用cusparseSDDMM_preprocess()以来,缓冲区内容必须保持未修改状态。
当使用matC及其活跃缓冲区调用cusparseSDDMM()时,可能会从缓冲区读取加速数据。
再次调用cusparseSDDMM_preprocess()并传入matC和新缓冲区时,将使新缓冲区处于活动状态,
同时遗忘先前活动的缓冲区并将其置为非活动状态。
对于cusparseSDDMM(),每个稀疏矩阵同一时间只能有一个活动缓冲区。
若需实现单个稀疏矩阵拥有多个活动缓冲区的效果,
可创建多个指向相同索引和值缓冲区的矩阵句柄,
然后为每个句柄调用cusparseSDDMM_preprocess()并传入不同的工作区缓冲区。
使用非活跃缓冲区调用cusparseSDDMM()始终是被允许的。但在这种情况下,预处理可能不会带来加速效果。
出于线程安全的考虑,
cusparseSDDMM_preprocess()正在写入matC的内部状态。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
操作 |
|
主机或设备 |
IN |
\(\alpha\) 用于与类型 |
|
主机 |
IN |
密集矩阵 |
|
主机 |
IN |
稠密矩阵 |
|
主机或设备 |
IN |
\(\beta\) 用于与类型 |
|
主机 |
输入/输出 |
稀疏矩阵 |
|
主机 |
IN |
执行计算所用的数据类型 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
IN |
指向至少 |
当前支持的稀疏矩阵格式:
CUSPARSE_FORMAT_CSRCUSPARSE_FORMAT_BSR
cusparseSDDMM() 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
当前cusparseSDDMM支持的数据类型组合如下:
统一精度计算:
|
|---|
|
|
|
|
混合精度计算:
|
|
|
|---|---|---|
|
|
|
|
|
cusparseSDDMM 针对 CUSPARSE_FORMAT_BSR 格式还支持以下混合精度计算:
|
|
|
|---|---|---|
|
|
|
|
|
注意:CUDA_R_16F、CUDA_R_16BF数据类型始终意味着混合精度计算。
cusparseSDDMM() 对于 CUSPASRE_FORMAT_BSR 格式支持2、4、8、16、32、64和128的块大小。
cusparseSDDMM() 支持以下算法:
算法 |
备注 |
|---|---|
|
默认算法。它支持批量计算。 |
性能说明:当matA和matB满足以下条件时,cuspaseSDDMM()针对CUSPARSE_FORMAT_CSR格式能提供最佳性能:
-
matA:matA是行优先顺序且opA为CUSPARSE_OPERATION_NON_TRANSPOSE,或者matA采用列优先存储顺序且opA不是CUSPARSE_OPERATION_NON_TRANSPOSE
-
matB:matB是列优先顺序且opB为CUSPARSE_OPERATION_NON_TRANSPOSE,或者matB是行优先顺序且opB不是CUSPARSE_OPERATION_NON_TRANSPOSE
cuspaseSDDMM() 针对 CUSPARSE_FORMAT_BSR 格式时,当 matA 和 matB 满足以下条件时可提供最佳性能:
-
matA:matA是行优先顺序且opA为CUSPARSE_OPERATION_NON_TRANSPOSE,或者matA采用列优先存储顺序且opA不是CUSPARSE_OPERATION_NON_TRANSPOSE
-
matB:matB是行优先顺序且opB为CUSPARSE_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}\)
批处理的数量及其步长可以通过使用cusparseCsrSetStridedBatch和cusparseDnMatSetStridedBatch来设置。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)
该函数执行两个稀疏矩阵matA和matB的乘法运算。
其中 \(\alpha,\) \(\beta\) 为标量,且 \(\mathbf{C},\) \(\mathbf{C^{\prime}}\) 具有相同的稀疏模式。
函数 cusparseSpGEMM_workEstimation()、cusparseSpGEMM_estimateMemory() 和 cusparseSpGEMM_compute() 用于确定缓冲区大小和执行实际计算。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
操作 |
|
主机 |
IN |
操作 |
|
主机或设备 |
IN |
\(\alpha\) 用于乘法的标量 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
IN |
稀疏矩阵 |
|
主机或设备 |
IN |
\(\beta\) 用于乘法的标量 |
|
主机 |
输入/输出 |
稀疏矩阵 |
|
主机 |
IN |
指定计算执行数据类型的枚举器 |
|
主机 |
IN |
指定计算算法的枚举器 |
|
主机 |
输入/输出 |
用于存储三个步骤间使用的内部数据的不透明描述符 |
|
主机 |
输出 |
指向64位整数的指针,用于存储由 |
|
主机 |
IN |
计算块中中间产物占总产出的比例。仅由 |
|
主机 |
输入/输出 |
|
|
主机 |
输入/输出 |
|
|
主机 |
输入/输出 |
|
|
设备 |
IN |
指向 |
|
设备 |
IN |
指向 |
|
设备 |
IN |
指向 |
当前,该功能存在以下限制:
仅支持32位索引
CUSPARSE_INDEX_32I仅支持CSR格式
CUSPARSE_FORMAT_CSR仅支持
opA和opB等于CUSPARSE_OPERATION_NON_TRANSPOSE的情况
当前cusparseSpGEMM支持的数据类型组合如下:
统一精度计算:
|
|---|
|
|
|
|
|
|
|
|
cusparseSpGEMM 例程适用于以下算法:
算法 |
备注 |
|---|---|
|
默认算法。当前为 |
|
算法 1
|
|
算法 2
|
|
算法3
|
cusparseSpGEMM() 具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
该例程允许
matA和matB的索引不排序该例程保证
matC的索引是有序的
cusparseSpGEMM() 支持以下 优化:
CUDA图捕获
硬件内存压缩
有关返回状态的描述,请参见cusparseStatus_t。
请访问cuSPARSE库示例 - cusparseSpGEMM查看CUSPARSE_SPGEMM_DEFAULT和CUSPARSE_SPGEMM_ALG1的代码示例,以及访问cuSPARSE库示例 - 内存优化的cusparseSpGEMM查看CUSPARSE_SPGEMM_ALG2和CUSPARSE_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)
该函数执行两个稀疏矩阵matA和matB的乘法运算,其中输出矩阵matC的结构可重复用于不同值的多次计算。
其中 \(\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仅支持
opA和opB等于CUSPARSE_OPERATION_NON_TRANSPOSE的情况
当前cusparseSpGEMMreuse支持的数据类型组合如下所示。
统一精度计算:
|
|---|
|
|
|
|
|
|
混合精度计算:[已弃用]
|
|
|
|---|---|---|
|
|
|
|
|
|
cusparseSpGEMMreuse 例程适用于以下算法:
算法 |
备注 |
|---|---|
|
|
默认算法。为每次运行的输出矩阵提供确定性(按位)结构,但数值计算不具有确定性。 |
|
为输出矩阵和每次运行的值计算提供确定性(逐位)结构。 |
cusparseSpGEMMreuse() 具有以下特性:
该例程不需要额外的存储空间
该例程支持异步执行
该例程允许
matA和matB的索引不排序该例程保证
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() 所需工作空间的大小。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
稀疏矩阵 |
|
主机 |
输出 |
稠密矩阵 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
IN |
指向工作区缓冲区的指针 |
cusparseSparseToDense() 支持以下索引类型来表示稀疏矩阵 matA:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseSparseToDense() 支持以下数据类型:
|
|---|
|
|
|
|
|
|
|
|
|
cusparseSparse2Dense() 支持以下算法:
算法 |
备注 |
|---|---|
|
默认算法 |
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()来填充上一步骤中分配的数组。
参数 |
内存 |
输入/输出 |
含义 |
|---|---|---|---|
|
主机 |
IN |
cuSPARSE库上下文的句柄 |
|
主机 |
IN |
稠密矩阵 |
|
主机 |
输出 |
稀疏矩阵 |
|
主机 |
IN |
计算算法 |
|
主机 |
输出 |
|
|
设备 |
IN |
指向工作区缓冲区的指针 |
cusparseDenseToSparse() 支持以下索引类型来表示稀疏向量 matB:
32位索引 (
CUSPARSE_INDEX_32I)64位索引 (
CUSPARSE_INDEX_64I)
cusparseDenseToSparse() 支持以下数据类型:
|
|---|
|
|
|
|
|
|
|
|
|
cusparseDense2Sparse() 支持以下算法:
算法 |
备注 |
|---|---|
|
默认算法 |
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 谨此感谢以下个人和机构所作出的贡献:
cusparse
gtsv 的实现源自伊利诺伊大学李雯(Li-Wen Chang)开发的版本。 cusparse
gtsvInterleavedBatch采用了由巴塞罗那超级计算中心和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公司的商标或注册商标。其他公司及产品名称可能是其各自关联公司的商标。