我想知道NVIDIA的cuBLAS库。有人有经验吗?例如,如果我使用BLAS编写C程序,我是否可以通过调用cuBLAS替换对BLAS的调用?或者甚至更好地实现一个让用户在运行时选择的机制?
如果我使用Boost with C ++提供的BLAS库呢?
答案 0 :(得分:5)
janneb的答案是不正确的,cuBLAS 不是CPU BLAS的直接替代品。它假定数据已经在设备上,并且函数签名有一个额外的参数来跟踪cuBLAS上下文。
然而,进入CUDA 6.0是一个名为NVBLAS的新库,它提供了这种“插入式”功能。它拦截Level3 BLAS调用(GEMM,TRSV等)并自动将它们发送到GPU,通过GPU计算有效地平铺PCIE传输。
此处有一些信息:https://developer.nvidia.com/cublasxt,今天CUDA注册开发人员可以使用CUDA 6.0。
一旦CUDA 6.0向公众发布,完整的文档将在线。
答案 1 :(得分:2)
CUBLAS不包围BLAS。 CUBLAS还以列主要顺序访问矩阵,例如一些Fortran代码和BLAS。
我更习惯用C语言编写代码,即使对于CUDA也是如此。 用CBLAS(BLAS的C包装)编写的代码可以很容易地变成CUDA代码。 请注意,使用BLAS的Fortran代码与使用CBLAS的C / C ++代码完全不同。 Fortran和BLAS通常以列主要顺序存储矩阵或双数组, 但是C / C ++通常会处理Row-major排序。 我通常会处理这个问题,将矩阵保存在一维数组中, 并使用#define编写宏来访问矩阵的元素i,j:
/* define macro to access Aij in the row-wise array A[M*N] */
#define indrow(ii,jj,N) (ii-1)*N+jj-1 /* does not depend on rows M */
/* define macro to access Aij in the col-wise array A[M*N] */
#define indcol(ii,jj,M) (jj-1)*M+ii-1
CBLAS库有很好的组织参数和约定(const枚举变量) 给每个函数赋予矩阵的排序。 请注意,矩阵的存储也会有所不同,行方式带状矩阵的存储方式与列式带矩阵的存储方式不同。
我认为没有机制让用户在使用BLAS或CUBLAS之间做出选择, 无需编写代码两次。 CUBLAS在大多数函数调用中也有一个“句柄”变量,它不会出现在BLAS上。 我想#define在每个函数调用时更改名称,但这可能不起作用。
答案 2 :(得分:0)
我一直在将BLAS代码移植到CUBLAS。我使用的BLAS库是ATLAS,所以我说的可能只有BLAS库的选择才正确。
ATLAS BLAS要求您指定是否使用列主要排序或行主要排序,并且我选择了列主要排序,因为我使用的是使用列主要排序的CLAPACK。另一方面,LAPACKE将使用行主要排序。 CUBLAS是列主要订购。您可能需要相应调整。
即使订购不是移植到CUBLAS的问题也绝不是替代品。最大的问题是您必须将数据移入和移出GPU的内存空间。该内存是使用cudaMalloc()设置的,并与cudaFree()一起发布,这可能是人们所期望的。您可以使用cudaMemcpy()将数据移动到GPU内存中。如果从CPU转向GPU是值得的,那么这样做的时间将是一个很大的决定因素。
然而,一旦完成,呼叫就非常相似。 CblasNoTrans变为CUBLAS_OP_N,CblasTrans变为CUBLAS_OP_T。如果您的BLAS库(如ATLAS那样)允许您按值传递标量,则必须将其转换为通过引用传递(对于FORTRAN来说是正常的)。
鉴于此,任何允许选择CPU / GPU的开关最容易处于比使用BLAS的功能更高的级别。在我的情况下,我有算法的CPU和GPU变体,并根据问题的大小选择更高级别。