cublas库 中文简介

更新时间:2024-06-29 23:13:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

Cublas Library 第一章 简介

Cublas Library 就是在NVIDIA CUDA中实现Blas(基本线性代数子程序)。它允许用户访问NVIDIA中GPU(图形处理单元)的计算资源,但不能同时对多个GPU进行自动并行访问.在使用Cublas library时,应用程序必须在GPU内存空间中分配所需的矩阵向量空间,并将其填充数据,再顺序调用所需的Cublas函数,最后将计算结果从GPU内存空间上传到主机中。Cublas library 同时还提供了从GPU中书写和检索数据的功能。

1.1 数据布局 对于现有的具有最大兼容性的Fortran环境,Cublas library使用column-major storage(列主序存储)和1-based indexing(以1开始索引)。由于C和C++使用row-major storage, 使得用这些语言编写的应用程序对于二维数组不能使用本地数组语义。相反,宏或内联函数应该被定义为实现以为数组矩阵。将Fortran代码机械的移植到C中,你可以选择保留1-based indexing 以避免转换循环。在这种情况下,矩阵中位于i行j列的数组元素可通过下面的宏计算:#define IDX2F(i,j,ld) ((((j)-1)*(ld))+((i)-1))。这里,ld代表矩阵的主要维度,而在列主序存储矩阵中代表行数。在本地写C或C++代码,我们喜欢用0-based indexing, 那么上述矩阵中元素可通过下面宏计算: #define IDX2C(i,j,ld) (((j)*(ld))+(i))

1.2 新的和遗留的Cublas AP1(应用程序接口) 从第四版开始,

Cublas Library提供了一个升级的API,另外还有已有的 legacy API. 这节讨论为什么要提供新的API,它有哪些优势,以及与原先的API 的区别。 新的CUBLAS library API可以通过引用头文件“cublas_v2.h”而被使用。它包含以下legacy CUBLAS library API 所没有的特征。

1.已经利用函数初始化了对Cublas Library 内容的处理并明确的传递给每个后续的库函数调用,这使得用户在使用多主机线程和多个GPU时能对库的设置有更多的控制。这也使得CUBLAS API成为可重入的。

2.标量α和β可通过引用传递给主机或设备,替代原先只能通过主机数值进行传递。这种改变使得库函数在使用流时可以异步地并行执行,即使当α和β由前一个内核所产生。

3.当库例程序返回一个标量结果时,它可通过主机或设备上的应用返回,代替只能通过主机上的数值返回。这种改变允许库例程序被称为异步的,当标量结果通过设备参数产生和返回导致最大的并行性。 4.错误状态cublasStatus_t可通过所有Cublas Library 函数调用返回,这种变化促进了调试并简化了软化开发。cublasStatus重命名为cublasStatus_t使它更符合Cublas Library库中其他类型。 5.? cublasAlloc()和cublasFree()函数已被弃用,此更改分别移除cudaMalloc() 和 cudaFree()中不必要的包装。

6.?函数cublasSetKernelStream()被重命名为cublasSetStream()以便更符合CUDA libraries中其他内容。

第二章

使用Cublas AP1

2.1. Error status(错误状态)

所有的CUBLAS library都通过cublasStatus_t返回错误状态。 2.2. CUBLAS context

所有应用程序必须通过调用cublasCreate()函数对Cublas Library 内容进行初始化处理,然后明确地传递给后面库函数调用,一旦应用程序结束了对库的使用,必须调用函数cublasDestory()以释放与Cublas库内容相关的资源。

这种方式允许用户在使用多主机线程和多GPU 时可明确地掌握库的启动。

例如,应用程序可使用cudaSetDevice()连接不同设备和不同的主机线程,其中的每一个主机线程初始化一个独特的处理,这可使一个独特的设备连接那个主机线程,然后cublas库函数调用不同处理去自动调度不同的计算到设备中。只有在假设相应的cublasCreate() 和cublasDestory()之间内容保持不变的情况下才能使设备与某个特定的CUBLAS内容相连。为了使CUBLAS库在同一主机线程中使用不同设备,应用程序必须通过cudaSetDevice()设置所需要使用的新设备然后创建另一个CUBLAS内容,通过调用cublasCreate()连接一个新设备。

2.3. Thread Safety(线程安全性)

该库是线程安全,可以从多个主机线程调用此功能,即使是相同的操作。

2.4. Scalar Parameters(标量参数)

在CUBLAS中,标量参数α和β可以通过主机或设备中的参数传递。 一些函数例如amax(), amin, asum(),rotg(), rotmg(), dot() 和nrm2()可以返回标量结果,通过主机或设备的参数返回标量数值。尽管这些函数可以像矩阵和向量一样立即返回值,标量结果只有当常规的GPU执行完成后才能准备好,这些都需要适当的同步以从主机上读取结果。这些变化允许库函数使用流执行完全异步,即使标量α和β由前一个内核产生。例如当出现迭代法解线性系统和如何使用Cublas库完成特征值问题。

2.5. Parallelism with Streams(流的并行性)

如果应用程序使用多个独立任务来得到计算结果,CUDA流可用于在重叠计算中执行这些任务。应用程序可以在概念上将每个流与任务相联系,为了实现任务的重叠计算,用户应当使用cudaStreamCreate()函数创建CUDA 流,在调用实际的cublas 例程以前,调用cublasSetStream()让这些流被cublas库中每个单独的例程所引用,然后再每个单独流中的计算结果将会在GPU上自动重叠计算。当一个任务的计算规模相对较小时,不足以填满GPU工作。

我们建议在标量参数中使用新的CUBLAS API,在结果传递中使用设备内存的参数,以实现最大程度的重叠计算。

2.6. Batching Kernels(批处理内核)

本节将讨论如何使用流批处理小内核,例如我们有个应用程序需要使用密集矩阵实现多个独立小矩阵的相乘运算。 很明显即使有数以百万的独立小矩阵也不能实现像一个大矩阵实现GFLOPS(每秒千兆次浮点运算)。例如对于一个n×n规模的大矩阵乘法对于的输入需要执行n三次方的操作。然而对于1024个(n/32)*(n/32)小矩阵对于相同的输入需要执行n三次方/32次操作。由此可见我们可以通过使用很多独立的小矩阵实现更好的计算效率相比于一整个大矩阵。 GPU体系结构允许我们同时执行多个内核。因此,为了批处理这些独立内核,我们可以将其放在每个单独的流中执行。尤其,在上述事例中我们通过cudaStreamCreate()创建了1024个CUDA流。这将确保不同的计算能够同步执行,虽然用户可以创建许多流,但实际上不可能有超过16个流同时运算。

2.7. Cache configuration(缓存配置)

在一些设备中,一级缓存和共享内存使用相同的硬件资源。缓存可以通过CUDA的事例程序cudaDeviceSetCacheConfig()直接配置,当然对于某些专门函数也可以通过cudaFuncSetCacheConfig()来专门配置。 因为从一个配置切换到另一个会影响到核并发,CUBLAS Library并没有设置任何缓存配置偏向和依赖于当前配置。然而对于某些Cublas例程,尤其是 Level-3例程,严重依赖于共享内存,因此缓存首选设置可能对其表现不利。

第三章 CUBLAS 数据类型参量

3.1 cublasHandle_t cublasHandle_t类型是一个不透明指针类型结构支持CUBLAS库内容。CUBLAS库内容必须通过cublasCreate()初始化,返回的处理结果必须经过所有后续库函数调用,最后必须使用cublasDestroy()摧毁其中内容。

3.2. cublasStatus_t 该函数用于函数状态的返回。所有的CUBLAS library

都返回他们的状态。通常有以下值。

CUBLAS_STATUS_SUCCESS

CUBLAS_STATUS_NOT_INITIALIZED(CUBLAS library未初始化,通常由于缺少前面的cublasCreate()函数调用引起,是CUDA运行时调用CUBLAS例程的错误,或者是一个硬件启动的错误。 纠正方法:在调用函数前先调用cublasCreate(),检查硬件,适合的驱动版本,CUBLAS库正确安装) CUBLAS_STATUS_ALLOC_FAILED(CUBLAS库中资源分配失败,通常由cudaMalloc()失败所引起。 纠正:在调用此函数之前,尽可能多的解除之前分配的内存) CUBLAS_STATUS_INVALID_VALUE(一个无效值或参数传递给了函

)。

纠正:确保所有传递的参数有有效值) CUBLAS_STATUS_ARCH_MISMATCH(函数需要一个设备结构中缺少的功能,通常由于缺少支持双精度所造成。 纠正:在具备相应计算

CUBLAS_STATUS_MAPPING_ERROR (访问GPU内存空间失败,

通常由绑定纹理失败所造成。

纠正:在调用函数前,解开以前的绑定纹理) CUBLAS_STATUS_EXECUTION_FAILED(GPU项目执行失败。由于GPU发送失败的内核引起,多种原因引起。 纠正:检查硬件,一个合适的驱动程序版本,CUBLAS库的正确安装)

3.3. cublasOperation_t 该类型表明哪些操作需要被执行密集矩阵。其值对应于FORTRAN的字符‘N’或‘n’(非转置), ‘T’或 ‘t’(转置), ‘C’或’c’(共轭转置)。往往作为参数,以传统BLAS实现。其值有 CUBLAS_OP_N(非转置操作被选择) CUBLAS_OP_T(转置操作被选择) CUBLAS_OP_C(共轭转置操作被选)

3.4. cublasFillMode_t 该类型表明哪一部分密集矩阵已被填充,因此需要被函数使用。其值对应FORTRAN的字符数据类型参数‘L’ 或 ‘l’(更低)和‘U’ 或 ‘u’(更高)通常被用作参数遗留给CUBLAS实现。有以下值 CUBLAS_FILL_MODE_LOWER(矩阵的低位被填充) CUBLAS_FILL_MODE_UPPER(矩阵的高位被填充)

3.5. cublasDiagType_t 该类型表明是否稠密矩阵的主对角线归一,以此不应被函数触及和修改。其值对应FORTRAN字符‘N’ or ‘n’ (不归一) and ‘U’ or ‘u’ (归一)。通常被用作参数遗留给CUBLAS实现。有以下值 CUBLAS_DIAG_NON_UNIT(矩阵对角线有非归一元素) CUBLAS_DIAG_UNIT(矩阵对角线都为归一元素)

3.6. cublasSideMode_t 该类型表明密集矩阵是位于等式的左边还是右边。 CUBLAS_SIDE_LEFT(矩阵位于等式左边)

CUBLAS_SIDE_RIGHT(矩阵位于等式右边)

3.7. cublasPointerMode_t 该类型表明标量值是否通过主机或设备上的参数来传递。需要指出的是,如果有几个标量值在函数中被调用,它们必须符合同一指针模式。指针模式分别通过cublasSetPointerMode() 和cublasGetPointerMode()例程来进行设置和检索。 CUBLAS_POINTER_MODE_HOST(标量通过主机参数传递) CUBLAS_POINTER_MODE_DEVICE(标量通过设备参数传递) 3.8. cublasAtomicsMode_t 该类型表明CUBLAS例程通过原子实现替代功能是否可实现。原子模式可通过例程进行设置和查询。 CUBLAS_ATOMICS_NOT_ALLOWED(不能使用原子模式) CUBLAS_ATOMICS_ALLOWED(可以使用原子模式) 第四章 CUBLAS辅助函数参数

4.1. cublasCreate() cublasStatus_t cublasCreate(cublasHandle_t *handle) 该函数初始化CUBLAS库,并创造了一个支持CUBLAS库的解决方案,它在主机和设备上分配硬件资源,在调用其它CUBLAS库时必须先被调用。返回值如下: CUBLAS_STATUS_SUCCESS CUBLAS_STATUS_NOT_INITIALIZED CUBLAS_STATUS_ALLOC_FAILED

4.2. cublasDestroy() cublasStatus_t cublasDestroy(cublasHandle_t handle) 该函数释放CUBLAS库所使用的硬件资源。GPU资源的释放可能会被延迟到应用程序退出。该函数通常是对应于CUBLAS库特定处理的最后一个调用。返回值如下:

CUBLAS_STATUS_SUCCESS

CUBLAS_STATUS_NOT_INITIALIZED 4.3.cublasGetVersion()

cublasStatus_t cublasGetVersion(cublasHandle_t handle, int *version) 该函数返回CUBLAS库的版本号。返回值如下: CUBLAS_STATUS_SUCCESS CUBLAS_STATUS_NOT_INITIALIZED

4.4. cublasSetStream() cublasStatus_t cublasSetStream(cublasHandle_t handle, cudaStream_t streamId) 该函数设置CUBLAS库流,将用于执行对CUBLAS库函数所有的后续调用。如果CUBLAS库流未设置,所有内核使用默认的空流。特别地,可以使用该例程改变流之间的内核启动,然后重置CUBLAS库流归零。返回值如下: CUBLAS_STATUS_SUCCESS

CUBLAS_STATUS_NOT_INITIALIZED

4.5. cublasGetStream() cublasStatus_t cublasGetStream(cublasHandle_t handle, cudaStream_t *streamId) 这个函数获取CUBLAS库流,被用来执行CUBLAS库函数的所有调用。如果CUBLAS库流未被设置,所有内核使用默认空流。返回值如下: CUBLAS_STATUS_SUCCESS CUBLAS_STATUS_NOT_INITIALIZED 4.6.cublasGetPointerMode() cublasStatus_t

cublasGetPointerMode(cublasHandle_t

handle,

cublasPointerMode_t *mode) 该函数通过CUBLAS库获得指针模式。

返回值如下: CUBLAS_STATUS_SUCCESS

CUBLAS_STATUS_NOT_INITIALIZED 4.7.

cublasSetPointerMode()

handle,

cublasStatus_t cublasPointerMode_t

cublasSetPointerMode(cublasHandle_t

mode) 该函数通过CUBLAS库设置指针模式,默认值是通过主机上的参数来传递。返回值如下: CUBLAS_STATUS_SUCCESS CUBLAS_STATUS_NOT_INITIALIZED

4.8. cublasSetVector() cublasStatus_t cublasSetVector(int n, int elemSize, const void *x, int incx, void *y, int incy) 该函数从主机内存空间中复制向量x中n个元素到GPU的内存空间向量y中。两向量中元素都被假定有elemSize字节大小。连续元素的存储空间是源向量x到目标向量y的距离。 一般来说,y 指向一个对象或物体的一部分并通过cublasAlloc()分配。由于假定了列主格式为二维的。如果向量是矩阵的一部分,向量增量等于是访问列矩阵的一部分。类似地,使用一个增量等于是访问矩阵行中的主要维度。返

CUBLAS_STATUS_SUCCESS

CUBLAS_STATUS_NOT_INITIALIZED

CUBLAS_STATUS_INVALID_VALUE 参数incx, incy, elemSize<=0 CUBLAS_STATUS_MAPPING_ERROR 访问GPU内存失败 4.9. cublasGetVector() cublasStatus_t cublasGetVector(int n, int elemSize, const void *x, int incx, void *y, int incy) 这个函数从GPU内存空间复制向量x中n个元素到主机内存中y向

量。两向量中元素都被假定有elemSize字节大小。连续元素的存储空间是源向量x到目标向量y的距离。 一般来说,x指向一个对象或对象的一部分,通过cublasAlloc()分配。因为先假设了列主为二维矩阵格式。如果向量是矩阵的一部分,那么向量增量等同于访问矩阵的一个列。类似,使用一个增量等同于引出矩阵维度,导致对矩阵行的访问。返回值如下: CUBLAS_STATUS_SUCCESS CUBLAS_STATUS_NOT_INITIALIZED

CUBLAS_STATUS_INVALID_VALUE 参数incx, incy, elemSize<=0 CUBLAS_STATUS_MAPPING_ERROR 访问GPU内存失败 4.10. cublasSetMatrix() cublasStatus_t cublasSetMatrix(int rows, int cols, int elemSize, const void *A, int lda, void *B, int ldb) 该函数从主机内存空间复制矩阵A中一系列行*列元素到GPU内存空间中的矩阵B。它假定每个元素需要elemSize字节存储,这两个矩阵都被存储为列主形式。源矩阵A和目标矩阵B中主导的维度都分别被存放于lda 和 ldb,主导维度代表分配矩阵的行数,即使只有一个子矩阵被使用。通常,B是设备指针-指向对象或其一部分,通过cublasAlloc()被分配在GPU内存空间。返回值如下: CUBLAS_STATUS_SUCCESS

CUBLAS_STATUS_NOT_INITIALIZED

CUBLAS_STATUS_INVALID_VALUE the parameters rows, cols<0 or elemSize, lda, ldb<=0 CUBLAS_STATUS_MAPPING_ERROR 4.11. cublasGetMatrix() cublasStatus_t cublasGetMatrix(int rows, int

cols, int elemSize, const void *A, int lda, void *B, int ldb)

本文来源:https://www.bwwdw.com/article/i933.html

Top