2013-08-16 341 views
3

3D矩陣中的數據是由層(從頂部到底部)生成的,我想將該數據與2D矩陣相乘,但不是採取每個需要拍攝的圖層來自第1層的矢量,來自第2層的矢量等等。乘以3D矩陣和2D矩陣CUDA

目前我在做什麼是對那些矢量從3D矩陣複製到一個二維矩陣TMPA然後用(使用CUBLAS),結果存儲在繁殖tmpB終於逐行復制回到它在3D矩陣中對應的位置C。總體而言,我的整個應用程序運行速度至少比CPU版本快兩倍,但在我看來,從設備到設備製作的這些內存拷貝(甚至是)對於性能來說並不是很好。

什麼是更好的方式來做這種計算?我在考慮在乘數之前重新排列數據,以避免內存拷貝。

的3D矩陣Ç和2D矩陣已經在GPU的存儲器中。

EDIT

設M,N,P是三維矩陣存儲以行優先順序上該設備的存儲器中的線性陣列中的甲的尺寸。我的代碼如下所示:

cudaMalloc((void**)&d_tmpIn, sizeof(float)*M*P); 
cudaMalloc((void**)&d_tmpOut, sizeof(float)*M*P); 
cudaMalloc((void**)&d_C, sizeof(float)*M*N*P); 

for (int iN = 0; iN < N; iN++) 
{ 
    dst = d_tmpIn; 
    for (int iM = 0; iM < M; iM++) 
    { 
    cudaMemcpy(dst, &(d_A[iN*P+0+iM*N*P]), sizeof(float)*P, cudaMemcpyD2D); 
    dst += P; 
    } 

    cublasDgemm(cublasHandle, CUBLAS_OP_N, CUBLAS_OP_N, P, M, M, &alpha, d_tmpIn, P, d_B, M, &beta, d_tmpOut, P); 

    src = d_tmpOut; 
    for (int iM = 0; iM < M; iM++) 
    { 
    cudaMemcpy(&(d_C[iN*P+0+iM*N*P]), src, sizeof(float)*P, cudaMemcpyD2D); 
    src += P; 
    } 
} 

希望這會有所幫助。

+0

您能描述一下數據如何存儲在GPU內存中以及CUBLAS調用您用來執行此計算的內容嗎?這並不是所有這些都清楚你實際上試圖從文本中做什麼(提示:方程式和短代碼片段勝過千言萬語) – talonmies

+0

通常情況下,cudaMemcpyD2D應該很快。你有沒有分析應用程序,以確定時間花在哪裏? –

+0

@RobertCrovella的確他們很快,但我想知道是否有更好的方法來避免這些內存拷貝。我會看看給出的答案,看看是否有幫助。 – BRabbit27

回答

4

你不需要做記憶體拷貝! BLAS和LAPACK API的創建方式可以指定開始點,步幅長度,主要維度的長度等。

這樣,您可以按原樣使用3D數組A和C,但可以使用正確的參數調用cublasDgemm。

在你的情況下(如果我正確理解代碼),它看起來像每個矩陣應該是P X M,你有他們的N。但它看起來像3D陣列排列爲PxNxM。因此,如果不爲d_tmpInd_tmpOut分配內存,則可以這樣做:A的行數爲P。列數是M。但是,主要維度(lda)應該被提及爲N * PC也是如此。

int lda = N * P; 
int ldc = N * P; 
for (int iN = 0; iN < N; iN++) 
{ 
    double *d_tmpIn = d_A + iN * P; 
    double *d_tmpOut = d_C + iN * P; 
    cublasSetStream(streams[iN]); // Optional 
    cublasDgemm(cublasHandle, CUBLAS_OP_N, CUBLAS_OP_N, 
       P, M, M, &alpha, d_tmpIn, lda, d_B, M, &beta, d_tmpOut, ldc); 

} 

您還可以創建iN流並運行每個cublas在單獨的流中運行。請注意,這只是將是,如果M和P足夠小(即GPU還沒有計算飽和)

編輯如果計劃使用流繼續前進,試圖在一次創建它們有用程序開始並重新使用它們。不要在與Dgemm相同的循環中創建和銷燬流。這增加了開銷。

+0

矩陣應該是'MXP'並且有N個(我正在使用行主要順序,並且只是遵循[本指南](http://peterwittek.com/2013/06/cublas-matrix-c-style/))避免轉換到列專業),3D陣列排列爲MxNxP。 – BRabbit27

+0

我認爲我的部分有一個錯誤,而不是乘以** AB **應該是** BA **(否則尺寸不一致)。混亂是因爲使用cublas我不得不顛倒矩陣,以避免從行主變爲列主順序(如上面的指導中所述)。無論如何,我明白了你的觀點,我會馬上嘗試,並帶着結果/懷疑回來。謝謝 ! – BRabbit27

+0

我在想使用流,但我不知道「足夠小」是什麼意思。通常M約爲3到10,P約爲2e6 - 4e6,N可能在30 - 1800之間。我描述了應用程序,顯然我沒有使GPU飽和,你能否給出一些關於使用流的建議。謝謝。 – BRabbit27