2017-03-01 30 views
0

結果はC++の並列行列乗算は、私の乗算の不正確な計算

-842150451 -842150451 -842150451 -842150451 
-842150451 -842150451 -842150451 -842150451 
-842150451 -84215045 -842150451 -842150451 
-842150451 -84215045 -842150451 -842150451 

のようなもので、してください私は、理由を理解していない誰かがこれを助けることができますか?

#include <iostream> 
#include <stdlib.h> 
#include <omp.h> 
#include <random> 
using namespace std; 

#define NUM_THREADS 2 

double**  A; 
double**  B; 
double**  C; 
double   t_Start; 
double   t_Stop; 
int    Am; 
int    An; 
int    Bm; 
int    Bn; 

void   Get_Matrix(); 
void   Mat_Mult_Parallel(); 


int main() 
{ 
    cout << "Matrix A: "; 
    cin >> Am >> An; 
    cout << "Matrix B: "; 
    cin >> Bm >> Bn; 

    Get_Matrix(); 
    Mat_Mult_Parallel(); 


    system("pause"); 
    return 0; 

} 


void Get_Matrix() 
{ 


    A = new double*[Am]; 
    B = new double*[Bm]; 
    C = new double*[Am]; 
    for (int i = 0; i<Am; i++) { A[i] = new double[An]; } 
    for (int i = 0; i<Bm; i++) { B[i] = new double[Bn]; } 
    for (int i = 0; i<Am; i++) { C[i] = new double[Bn]; } 
    omp_set_num_threads(NUM_THREADS); 
#pragma omp parallel for private(i,j) schedule(dynamic) 
    for (int i = 0; i<Am; i++) 
    { 
     for (int j = 0; j<An; j++) 
     { 
      A[i][j] = rand() % 10 +1; 
      cout << A[i][j] << " "; 


     } 
     cout << endl; 
    } 
    printf("\n"); 

#pragma omp parallel for private(i,j) schedule(dynamic) 
    for (int i = 0; i<Bm; i++) 
    { 
     for (int j = 0; j<Bn; j++) 
     { 
      B[i][j] = rand() % 10 + 1; 
      cout << B[i][j] << " "; 


     } 
     cout << endl; 
    } 
    printf("Matrix Created.\n"); 
} 

void Mat_Mult_Parallel() 
{ 
    int i, j, k; 
    t_Start = omp_get_wtime(); 

    omp_set_num_threads(NUM_THREADS); 
#pragma omp parallel for private(i,j) schedule(dynamic) 
    for (i = 0; i<Am; i++) 
    { 
     for (j = 0; j<Bn; j++) 
     { 
      for (k = 0; k<An; k++) 
      { 
       C[i][j] += A[i][k] * B[k][j]; 

      } 
      cout << C[i][j] << " "; 
     } 
     cout << endl; 
    } 

    t_Stop = omp_get_wtime() - t_Start; 
    cout << "Parallel: " << t_Stop << " seconds." << endl; 
} 
+1

解決策ではありませんが、現在の出力の16進数は0xFFFFFFFFCDCDCDCDです。 Visual Studioでは、その0xCDは初期化されていないメモリです。 –

+2

スターターの 'omp parallel for'ディレクティブに' private(k) 'を追加してみてください... – Gilles

+1

HoとBTWの' rand() 'はスレッドセーフではありませんので、とにかく再現性のない結果が得られます – Gilles

答えて

4

あなたの行列Cを初期化できませんでしたが、あなたは「+ =」演算子を使用し、あなたはこの最初のようなものが必要になりますので行列Cのランダムinital値に値を追加:

for (int i = 0; i < Am; i++) 
{ 
    for (int j = 0; j < Bn; j++) 
    { 
     C[ i ][ j ] = 0.0; 
    } 
} 

また、memset/setmem C関数(システムによって異なる)を使用することもできます。 はより高速になります。

ところで、並列化されたループで 'cout'を使用しないと、結果が混乱する可能性があります。

+0

小さなコメント:賢明なコンパイラ(少なくともGCCとIntel)は、このようなループを検出し、それを自動的に 'memset'と置き換えます。楽しい事実:いくつかのシステムでは、いくつかの設定では、 'memset'が代替よりも遅くなる可能性があります。おそらく、それは1バイトだけで動作するからです。 – Zulan

+0

助けてくれてありがとう。 – blazelott

+0

「解決済み」とマークしてください。 – Trantor