cuDSS 概述#
本节介绍使用 cuDSS API 的一般方面。
错误状态#
所有 cuDSS 调用都返回错误状态 cudssStatus_t。
库句柄#
为了使用 cuDSS,调用应用程序必须始终首先通过调用 cudssCreate() 函数来创建 cuDSS 库句柄。一旦应用程序完成使用库,它必须调用函数 cudssDestroy() 以释放与 cuDSS 库句柄关联的资源。
内存所有权和生命周期#
cuDSS 不拥有用户提供的数据缓冲区的所有权。这包括创建 cudssMatrix_t
对象或用户置换时使用的缓冲区,或通过 cudssDataSet() 函数传递的任何其他缓冲区。这意味着如果缓冲区是在 cuDSS 外部分配的,则它不会被 cuDSS 释放,用户有责任这样做。此外,用户也有责任确保用户提供的缓冲区在 cuDSS 停止对其进行操作之前不会被销毁。由于某些 cuDSS API(例如,因式分解和求解阶段)是异步的,因此可能需要通过 cudaStreamSynchronize()
进行流同步,以确保在销毁缓冲区之前不再使用它们。
cuDSS 分配主机和设备缓冲区供内部使用。这些缓冲区保存在相应的 API 对象内部,例如 cudssHandle_t 或 cudssData_t。当包含对象(cudssHandle_t
或 cudssData_t
)在调用 cudssDestroy() 或 cudssDataDestroy() 期间被销毁时,这些内部缓冲区将被释放。
当通过 Create()
函数创建不透明对象时,cuDSS 会分配主机缓冲区。为了释放这些缓冲区,必须调用相应的 Destroy()
函数。Create()
和 Destroy()
调用必须始终成对出现,否则可能会发生内存问题。
cudssMatrix_t 应该被视为用户提供的缓冲区的一个非常薄的包装器。
可以通过 cudssDeviceMemHandlers 和相关的 API 来控制 cuDSS 内部分配的设备缓冲区。
内存对齐#
对于用户提供的缓冲区,cuDSS 没有任何额外的内存对齐要求,即只需要存在默认的依赖于数据类型的对齐方式。
线程安全#
从多个主机线程调用 cuDSS 不能保证线程安全。例如,库句柄 对库分配的设备缓冲区进行内部簿记,并且当设备缓冲区正在分配时,不能由多个主机线程对其进行操作。此外,在分析和因式分解阶段期间发生的对 cudssData_t
对象的更新不是线程安全的。
cudssExecute()
的唯一阶段是不分配设备内存并且可以与多个主机线程并发执行的阶段是求解阶段。但是,在这种情况下,主机线程必须对不同的 cudssMatrix_t
对象进行操作以进行求解。
结果可重复性#
目前,cuDSS 正在使用原子操作,因此即使在固定环境内的重复运行中,也不能保证按位可重复性。通常,这种运行到运行的差异只会导致传统残差范数的小幅变化。
使用流的并行性#
通常,为了求解线性系统,cuDSS 同时使用主机和设备计算资源。具体来说,当禁用 混合主机/设备执行模式 时,重排序(分析阶段的主要部分)在主机上执行,而符号因式分解(分析阶段的另一部分)、数值因式分解和求解在 GPU 上执行。因此,很自然地,分析阶段目前始终是同步的。如果既未启用 :ref:` 混合内存 <hybrid-mode-label>` 也未启用 混合执行 模式,则因式分解和求解阶段是异步的。
由此可见,为了使用多个流来调用 cuDSS,应用程序应首先在所有流上调用分析阶段(这将不会并发执行),然后再在每个流中调用(重新)因式分解和求解阶段。
环境变量#
以下环境变量是 cuDSS 特定的
与 cuSolver 库的 cuSolverSp 和 cuSolverRf 组件的关系#
cuDSS 提供的稀疏直接求解器功能也部分可在 cuSolver 库的 (已弃用的) cuSolverSp 和 cuSolverRf 组件的例程中使用。强烈建议 cuSolverSp 和 cuSolverRf 的用户切换到 cuDSS。有关技术细节,请参阅 cuSolverSp 和 cuSolverRf 的文档,以及 转换示例。