cublas是乙個可以與cuda一同使用的函式庫,它提供了多種矩陣運算的api,但是它列主序的儲存方式卻讓人十分疑惑,今天我就以cublas中的矩陣乘法運算簡單說一下我的理解。
cublas中的矩陣乘法運算函式有5個,分別是cublassgemm、cublasdgemm、cublascgemm、cublaszgemm、cublashgemm,分別包括了不同資料型別的計算,比如單精度浮點、雙精度浮點、已經包括了複數等的運算。
我們檢視乙個具體的函式:
cublasstatus_t cublassgemm(
cublashandle_t handle,
cublasoperation_t transa,
cublasoperation_t transb,
int m, int n, int k,
const float *alpha,
const float *a,
int lda,
const float *b,
int ldb,
const float *beta,
float *c, int ldc);
在文件中對該函式的介紹:
該函式實現了矩陣運算c= αop(a)op(b)+βc,op就是指使用原矩陣運算還是使用轉置之後的矩陣運算。其中m、k為第乙個矩陣的行列數,k、n為第二個矩陣行列數。
初一看,並沒有什麼奇怪的地方,但是需要注意上邊的一點:column-major format,列主序。他這個列主序是什麼意思呢,下面我通過乙個例子來解釋一下。
我們待計算的矩陣有
a4*3 = [1,2,3,
4,5,6,
7,8,9,
10,11,12]
b3*2 = [1,2,
3,4,
5,6]
若我們令m=4,k=3,n=2,令transa和transb均為cublas_op_n,那它會不會進行如下圖的矩陣乘法?
圖1答案是不會的,我們需要注意一下前邊提到的列主序。
對於乙個陣列a4*3= [1,2,3,4,5,6,7,8,9,10,11,12],cublas在填充矩陣時,是按照列的順序來填充的,比如對於陣列a,若將其填充到乙個4*3的矩陣中,它是這樣填充的:
圖2所以,若引數按前邊那樣的話,實際進行的運算是這樣的:
圖3那麼,如果我們還是想進行如圖1的運算,該怎麼辦呢?這就用到了transa和transb這2個引數。將這2個引數設定為cublas_op_t,它會做乙個矩陣的轉置,最終的結果就是如圖1所示。需要注意的是,引數m、k、n是轉置後矩陣的行列數。
上邊圖3中的矩陣計算結果如下圖:
那麼,該矩陣是如何儲存的呢?
計算結果矩陣也遵循列主序的方式,所以,若將上圖矩陣從gpu拷貝回主機會發現實際是以下面的陣列的方式存放:
c = [38, 44, 50, 56, 83, 98,113,128]。
CULA矩陣相乘和CUBLAS矩陣相乘
cula的矩陣相乘 culadevicedgemm n n n,m,k,alpha,b device,n,b k x n a device,k,a m x k beta,c device,n 上式表示 c a b的矩陣相乘方法,而且資料型別為double,也可以使用float型別資料的函式 cula...
如何用cublas計算逆矩陣?
cublas的文件中提供了乙個用lu分解求逆矩陣的方法,需要用到兩個函式 第乙個函式用於做lu分解,第二個函式把lu分解的結果變為逆矩陣。但官方文件對這兩個函式的用法語焉不詳,我花了幾個小時才把這個問題搞定。主要遇到兩個問題 函式有乙個引數是 const float 型別,直接把 float 指標傳...
cuda中用cublas庫做矩陣乘法
這裡矩陣c a b,原始文件給的公式是c alpha a b beta c,所以這裡alpha 1,beta 0。主要使用cublassgemm這個函式,這個函式的第二個引數有三種型別,這裡cublas op n求出來矩陣結果是按行排列,所以不需要轉置了。如果用cublas op t引數求得的結果是...