2016-09-01 18 views
-3

私は最後の日にcudaで作業を始めました。サイズN×Nの2つの行列を乗ずるプログラムを書くことは問題ではなかった。カーネル関数では、私はこのコードを使用:非正方行列乗算にCudaを使用する

for(int i = 0; i < width; i++){ 
     sum += a[row * width + i] * b[i * width + col]; 
     c[row * width + col] = sum; 
    } 

私はサイズNのx M

+3

「サイズNのマトリックス」 - あなたはN×Nを意味しますか? – PRP

+0

私はここでの質問を理解していません。関与する行列の他の次元に関係なく、行と列の内積であるコード(ループ内のストアはなぜですか?)は変わりません。 – talonmies

+0

いいえ、1次元行列Nに2次元行列N x Mを掛けたいと思います。結果を格納する行列はMでなければなりません。 @talonmies、私は上記のコードを変更していない。 N x Nの2つの行列を掛けるのは問題ありませんが、非正方行列の場合は、 "a index"の高さパラメータを使用していますが、これは役に立ちません – avaj

答えて

-2

の行列とサイズ1×Nの行列を乗算するカーネル関数を設計しなければならないのはどのように持っていますこの問題の解決策を今すぐ見つけました:

#include <stdio.h> 
#include <iostream> 

using namespace std; 

__global__ 
void kernel(float *a, float *b, float *c, int N, int M) { 
    int tid = threadIdx.x + blockIdx.x * blockDim.x; 
    float sum = 0; 
    if (tid < M) { 
     for (int i = 0; i < N; i++) 
      sum += a[i] * b[(i * M) + tid]; 
     c[tid] = sum; 

    } 
} 

int main(void) { 

    float *dev_a, *dev_b, *dev_c; 

    int N = 16; 
    int M = 12; 

    float a[N]; 
    float b[N][M]; 
    float c[M]; 

    for (int i = 0; i < N; i++) { 
     a[i] = 1.0; 
    } 

    for (int i = 0; i < N; i++) { 
     for (int e = 0; e < M; e++) { 
      b[i][e] = 1.0; 
     } 
    } 

    cudaMalloc((void**) &dev_a, sizeof(float) * N); 
    cudaMalloc((void**) &dev_b, sizeof(float) * N * M); 
    cudaMalloc((void**) &dev_c, sizeof(float) * M); 

    cudaMemcpy(dev_a, a, sizeof(float) * N, cudaMemcpyHostToDevice); 
    cudaMemcpy(dev_b, b, sizeof(float) * N * M, cudaMemcpyHostToDevice); 

    kernel<<<M/256 + 1, 256>>>(dev_a, dev_b, dev_c, N, M); 

    cudaMemcpy(c, dev_c, sizeof(float) * M, cudaMemcpyDeviceToHost); 

    cudaFree(dev_a); 
    cudaFree(dev_b); 
    cudaFree(dev_c); 

    for (int i = 0; i < M; i++) { 
     cout << c[i] << endl; 
    } 

    return 0; 
} 

しかし、私はまだ1つの質問があります。パフォーマンス上の理由からカーネル内のforループ操作をいくつかのカーネルで分割するのは理にかなっていますか?