2017-09-04 28 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 

コードに問題はありますか?助けてください。

私はcuda toolkit 8.0でalea 3.0.3を使用しています。

UPDATE1:A、B、Cマトリックスを1Dアレイにフラット化すると、正しい結果が得られることがわかりました。しかし、2D配列の何が問題であるかを知りたい。

答えて

1

私は、2D-Arrayのgpu.AllocateDeviceがGPU上の領域をCPU上に割り当てていないことを発見しました。 2つの連続する列(ピッチ)の第1の要素間の距離は驚くほど大きくなります。

したがって、先行次元のパラメータを変更する必要があります。

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()); 

今、私は正しい結果を得ました。しかし、AleaでGPU上の2D配列の割り当てが実際にどのように機能するかの詳細を示す文書はありますか?

私には説明がない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)を使用しています。ピッチの理由は、いくつかのカーネルでパフォーマンスを向上させるために、行列の行を物理メモリチャネルに揃えることです。 –

関連する問題