2017-09-04 118 views
0

我想在Alea GPU上使用Gemm进行矩阵乘法,但是,这段代码给出了错误的结果。在alea GPU上使用cuBLAS的矩阵乘法

Gpu gpu = Gpu.Default; 
Blas blas = new Blas(gpu); 

int m=2,n=3; //in dimension and out dimension (output will be mxn matrix) 
int k=4; 

//column major 
float[,] A = new float[4,2] { {100,200},{2,6},{3,7},{4,8} }; //2x4 matrix 
float[,] B = new float[3,4] { {1,4,7,10}, {2,5,8,11}, {3,6,9,12} }; //4x3 matrix 
float[,] C = new float[3,2] { {-1,-1}, {-1,-1}, {-1,-1} }; //2x3 matrix 

var dA = gpu.AllocateDevice<float>(A); 
var dB = gpu.AllocateDevice<float>(B); 
var dC = gpu.AllocateDevice<float>(C); 

blas.Gemm(Operation.N,Operation.N,m,n,k,1f,dA.Ptr,m,dB.Ptr,k,0f,dC.Ptr,m); 

var result = Gpu.Copy2DToHost(dC); 

这是我得到的结果。它只是从矩阵A复制一些数字。矩阵C中的一些数字不会从初始化中改变。

100 -1 -1 
200 -1 -1 

这有什么错的代码?请帮忙。

我使用alea 3.0.3和cuda toolkit 8.0。

UPDATE1:我发现它给出了正确的结果,当我把A,B,C矩阵变成一维数组时。但是,仍然想知道二维数组有什么问题。

回答

1

我发现gpu.AllocateDevice for 2D-Array不会像在CPU上那样分配GPU上的空间。任何2个连续列(间距)的第一个元素之间的距离惊人地大。

因此,必须更改主要尺寸参数。

blas.Gemm(Operation.N,Operation.N,m,n,k,1f,dA.Ptr,dA.PitchInElements.ToInt32(),dB.Ptr,dB.PitchInElements.ToInt32(),0f,dC.Ptr,dC.PitchInElements.ToInt32()); 

现在,我得到了正确的结果。然而,是否有任何文件显示如何在GPU上分配2D阵列真的在Alea中工作?

我只能看到http://www.aleagpu.com/release/3_0_3/api/html/6f0dc687-7191-91ba-6c30-bb379dded567.htm没有任何解释。

+0

最有可能的是,它使用[cudaMallocPitch](http://docs.nvidia.com/cuda/cuda-runtime-api/group__CUDART__MEMORY.html#group__CUDART__MEMORY_1g32bd7a39135594788a542ae72217775c)。音调的原因是将矩阵行与物理内存通道对齐,以便在某些内核中获得更好的性能。 –