CUDA库和系统库或用户自定义没有什么不同,它们是一组在头文件中说明其原型的函数定义的集合。CUDA库的特殊性在于,其中实现的所有计算均使用了GPU加速,而不是CPU。
  使用CUDA库与创建手写CUDA C程序和使用主机现有的库相比有很多优势。CUDA库为很多应用程序在可用性和性能之间提供了最佳平衡。许多CUDA库中的API与相同作用域中的标准库API基本相同。因此,我们可以以基于主机的方式来使用CUDA库,这样能减少编程工作量,同时还能实现明显的加速。将复杂的算法从CPU移植到GPU中所需的时间可以从几个月或几周减少到几天甚至几个小时。
  CUDA库在性能方面已经超过主机库,而且有时也超过了手写的CUDA实现。CUDA库的开发人员对GPU体系架构的研究都有很深的造诣,CUDA库使我们能够利用他们的专业知识迅速加速应用程序的开发。
  对CUDA库的使用也降低了软件开发人员的维护成本,通过重用现有的比较成熟实现工具,在CUDA中对这些复杂算法的测试和管理也变得简单了。这些库是由NVIDIA及其合作伙伴严格测试和管理的,这就减轻了领域内专家和接触CUDA的程序员的工作量。
  不过,将CUDA库添加到现有的应用程序中一般还需要几个步骤,而且与标准主机库相比,性能提升还有进一步的优化。需要声明的是,NVIDIA开发者社区免费提供优秀的在线参考指南。接下来将重点讲述每个独立函数高级的使用方法以及应用程序的优化。

CUDA 库 支 持 的 作 用 域

  下表列举了一些GPU加速库以及它们的作用域:

cuda 深度学习代码 cuda算法库_cuda

通用的CUDA库工作流
  当在主机端程序中调用CUDA库函数时,很多函数有通用的概念、特性及使用步骤。NVIDIA函数库的通用工作流如下所示:
  1.在库操作中创建一个特定的库句柄来管理上下文信息: 许多CUDA库都有句柄这个概念,它包含了该库的一些上下文信息,如使用的数据结构格式、用于计算的设备端的使用等。对于使用句柄的库,在库调用前要做的就是为句柄分配内存及初始化。一般情况下,可以把句柄视作一个放在主机上、包含每个库函数肯恩那个可能访问的信息且对程序员不透明的对象。例如,你可能希望所有的库操作都在一个特定的CUDA流中运行。尽管不同函数库使用不同的函数名,许多函数库都有一个使所有操作在特定流中运行的函数(例如,cuSPARSE中 的cuparseSetStream,cuBLAS中的cublasSetStream以及cuFFT中的cufftSetStream)。这个流信息就保存在库句柄中,这个句柄提供了一种存储库信息的方法,程序员则负责管理句柄的并发访问。
  2.为库函数的输入输出分配设备内存: 一些函数库是由程序员或函数库自己调用cudaMalloc为其分配设备内存的。只有在使用多GPU编程库时,才需要使用API来分配设备内存。
  3.如果输入格式不是函数库支持的格式则需要进行转换: 例如,如果应用程序按行优先顺序存储二维数组,但CUDA库只接受按列优先顺序存储的数组,那么我们就需要进行格式转换了。为了取得最优性能,应尽可能与CUDA库的数据格式一致从而避免数据转换。
  4.将输入以支持的格式填入预先分配的设备内存中: 有了第2步分配的全局内存和第3步格式化后的数据,第4步的任务就是将数据传送到设备内存中,以供CUDA设备上的库函数使用。这类似于cudaMemcpy的作用,尽管多数情况下使用的是库特有的函数。例如,在使用基于cuBLAS的应用程序中把一个向量从主机传输到设备,用的就是cublasSetVector。当然其内部还是调用cudaMemcpy(或其他等价函数)来将输入数据传输到设备内存中的。
  5.配置要执行的库运算: 通常,被调用的库函数必须明确自己所用的数据格式、维度或其他配置参数。在第5步,需要我们来管理这个配置过程。在某些情况下,这些配置只是一些传递给计算函数库的参数。在其他情况下,就需要手动配置之前所说的库句柄了。还有个别情况,我们需要管理一些分离的数据对象。
  6.执行一个将计算部分交付给GPU的库函数调用: 执行阶段其实是函数库调用中最简单的一步!前面的5个步骤已经配置好了所需的库函数,并且获得了高度优化的CUDA库函数性能。
  7.取回设备内存中的计算结果,他可能是库设定的格式: 在这一步中,将输出数据按预定义的格式从设备内存中传回主机内存(数据格式按第5步配置的或函数库规定的),可以理解为它是第4步的反过程。
  8.如有必要,则将取回的数据转换成应用程序的原始格式: 如果应用程序的原始数据格式和CUDA库支持的格式不同,那么就需要将其转换回应用程序所用的格式,这是第3步的反过程。
  9.释放CUDA资源: 如果被工作流分配的资源不再使用就要释放掉,以便在以后的计算中使用。注意,分配和释放资源会有一些开销,因此最好多次调用CUDA库来重用设备内存、函数库句柄和CUDA流等资源。
  10.继续完成应用程序的其他工作: 在第7步取回输出的数据并(可选地)在第8步转换成应用程序地原始数据格式后,并可以继续其他操作了,就好像在GPU上还没有执行计算操作一样。
  并非每个库都遵循这一工作流,有些库可能会跳过某些步骤。