2011-02-16 15 views
7

CUDAで行列乗算を打ちました。得られた積行列は常にゼロである。私はmatrix multiplication in cudaのようないくつかのサンプルコードを読んで、私の問題を解決しましたが、すべて無駄です。CUDAを使用した行列乗算

エラーが「0」であることを除いて、最大サイズ「幅」(下のコード)は512ではありません。問題のある場所でデバッグできませんでした。 StackOverflowで議論することができるかもしれません。私は言及しています

が機能あなたのMatrixMulKernelで

#include<cuda.h> 
#include<stdio.h> 

int main(void) { 
    void MatrixMultiplication(float *, float *, float *, int); 
    const int Width = 5; 
    float M[Width*Width], N[Width*Width], P[Width*Width]; 
    for(int i = 0; i < (Width*Width) ; i++) { 
     M[i] = 5; 
     N[i] = 5; 
     P[i] = 0; 
    } 
    MatrixMultiplication(M, N, P, Width); 
    for(int i = 0; i < (Width*Width) ; i++) { 
     printf("%d \n", P[i]); 
    } 
    int quit; 
    scanf("%d",&quit); 
    return 0; 
} 

//Matrix multiplication kernel - thread specification 
__global__ void MatrixMulKernel(float *Md, float *Nd, float *Pd, int Width) { 
    //2D Thread ID 
    int tx = threadIdx.x; 
    int ty = threadIdx.y; 

    //Pvalue stores the Pd element that is computed by the thread 
    float Pvalue = 0; 

    for(int k = 0; k < Width ; ++k) { 
     float Mdelement = Md[ty*Width + k]; 
     float Ndelement = Nd[k*Width + tx]; 
     Pvalue += (Mdelement*Ndelement); 
    } 

    Pd[ty*Width + tx] = Pvalue; 
} 

void MatrixMultiplication(float *M, float *N, float *P, int Width) { 
    int size = Width*Width*sizeof(float); 
    float *Md, *Nd, *Pd; 

    //Transfer M and N to device memory 
    cudaMalloc((void**)&Md, size); 
    cudaMemcpy(Md,M,size,cudaMemcpyHostToDevice); 
    cudaMalloc((void**)&Nd, size); 
    cudaMemcpy(Nd,N,size,cudaMemcpyHostToDevice); 

    //Allocate P on the device 
    cudaMalloc((void**)&Pd,size); 

    //Setup the execution configuration 
    dim3 dimBlock(Width,Width); 
    dim3 dimGrid(1,1); 

    //Launch the device computation threads! 
    MatrixMulKernel<<<dimGrid,dimBlock>>>(Md,Nd,Pd,Width); 

    //Transfer P from device to host 
    cudaMemcpy(P,Pd,size,cudaMemcpyDeviceToHost); 

    //Free device matrices 
    cudaFree(Md); 
    cudaFree(Nd); 
    cudaFree(Pd); 
} 
+2

適切なコードフォーマットを得るには、4つのスペースですべてのコードをインデントする必要があります。これを簡単に行うには、コードを強調表示してCtrl + Kキーを押します。 –

+0

ありがとうございましたJeff!ただそれを行うつもりだった –

+0

CUDA Cプログラミングガイドには、独自のコードに固執する必要がない場合は、2の累乗以外の次元を持つ行列を処理でき、共有メモリを使用して最適化された素晴らしい行列-mul実装があります。実世界での使用と学習に強くお勧めします。 –

答えて

1

を私が何であったかを考え出しました違う。のは、それを分析してみましょう:

ポイント1:プログラムはの値で失敗する理由:これまでの単調な「ゼロ値」を除去するためのクエスト

指摘し、あなたがprintf("%d \n", P[i]);

printf("%f \n", P[i]);として

ポイント2を交換しなければならないと幅512?

実際には、23などの小さな値でも失敗します。なぜですか? 23 * 23は512より大きい(本日現在GPUがブロックあたりに持つ最大スレッド数!)

0

「超並列プロセッサのプログラミング」あなたのループのためのあなたの配列のサイズであるよう

for(int k = 0; k < Width ; ++k) 
{ 
    //rest of code  
} 

代わりのWidthは、あなたがWidth*Widthを使用しなければならないようなものですWidth*Width。あなたはこの時点まで細かいやっていた

+1

CUDA並列処理を使用することの全ポイントは、計算上のオーバーヘッドを排除することです。この場合、各スレッドは、製品マトリックスの1つの結果にしか関与しない。製品行列の1つの結果(要素)は、「幅」反復を使用して見つけることができます。 Width * Widthはどんな場合でも動作しません。 –

+0

@Gauravのように、幅*幅だけメモリを吹くだろう.. – ardiyu07

4

for(int i = 0; i < (Width*Width) ; i++) { 
    printf("%d \n", P[i]); 
} 

私はきれいに印刷(それはフロートだから)%fにそれを変更し、それらはすべて:)

$ ./test.exe 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
125.000000 
+0

確かに!私はあなたの答えを読まずにそれを理解しましたが、それを投稿するつもりでした。 –