2

2つのマトリックスを追加し、1つのスレッドと2つ以上のスレッドにかかる時間を書き留める基本的なコードを書いています。このアプローチでは、最初に、指定された2つのマトリックス(ランダムに初期化された)をTHREADSのセグメント数で分割し、次にこれらの各セグメントを追加モジュールに送信します。追加モジュールは、pthread_create呼び出しによって開始されます。並列加算関数の引数は次のとおりです。

struct thread_segment
{
  matrix_t *matrix1, *matrix2, *matrix3;
  int start_row, offset;
};

2つのソースマトリックスと1つの宛先マトリックスへのポインター。(ソースと宛先が同じマトリックスを指している場合があります)。これstart_rowは、特定のスレッドが追加を開始する行であり、offsetこのスレッドがから開始して追加する必要がある量を示しますstart_row

matrix_t、次のように定義された単純な構造です。

typedef struct _matrix_t
{
  TYPE **mat;
  int r, c;
} matrix_t;

2つのスレッドでコンパイルしましたが、10000 x 10000のマトリックスで実行した場合、(ほとんど)スピードアップはありません。プログラムで実行時間を記録していtime -pます。

マトリックスのランダムな初期化も、上記のように並行して行われます。

これは、すべてのスレッドが同じマトリックスアドレス領域で機能するためだと思います。これは、ボトルネックが高速化を行っていないことが原因である可能性があります。すべてのスレッドはマトリックスの異なるセグメントで機能しますが、オーバーラップしません。

以前は、同様の特性を示す並列マージソートとクイックソートを実装していましたが、特定のスレッドが機能するデータセグメントを新しく割り当てられたメモリにコピーすると、高速化できました。

私の質問は、これは次の理由によるものです。

  1. メモリのボトルネック?
  2. 時間ベンチマークは適切な方法で行われていませんか?
  3. データセットが小さすぎますか?
  4. コーディングエラー?
  5. 他の

この場合、それがメモリのボトルネックである場合、共有メモリ上のスレッドへの複数のアクセスがミューテックスなしで実行できる場合でも、すべての並列プログラムは排他メモリ領域を使用しますか?

編集

マトリックスセグメントを次のように作成すると、スピードアップが見られます

  curr = 0;
  jump = matrix1->r / THREADS;

  for (i=0; i<THREADS; i++)
  {
    th_seg[i].matrix1 = malloc (sizeof (matrix_t));
    th_seg[i].matrix1->mat = &(matrix1->mat[curr]);
    th_seg[i].matrix1->c = matrix1->c;
    th_seg[i].matrix1->r = jump;

    curr += jump;
  }

つまり、渡す前に、このスレッドによって処理されるマトリックスのベースアドレスを構造体に割り当て、行数を格納します。したがって、各マトリックスのベースアドレスはスレッドごとに異なります。しかし、100 x 100の小さな次元行列を何度も追加した場合にのみ、各反復で並列加算を呼び出す前に、ランダムな値を再割り当てしています。ここで気づいたスピードアップは本当ですか?または、他のいくつかの現象が影響を追いかけているためですか?

4

1 に答える 1

2

メモリ使用量を最適化するには、loop tilingを参照してください。これは、キャッシュ メモリの更新に役立ちます。このアプローチでは、マトリックスを小さなチャンクに分割して、キャッシュが値を長期間保持できるようにし、頻繁に更新する必要がないようにします。
また、多くのスレッドを作成すると、スレッド間の切り替えのオーバーヘッドが増加することに注意してください。

適切な実装が並行プログラムの実行時間にどの程度影響を与えるかを理解するために、これらは naive、cocnurrent、および tiling-concurrent で 2 つの行列を乗算するプログラムの結果です。

seconds  name    
10.72   simpleMul
5.16   mulThread
3.19   tilingMulThread
于 2012-09-02T05:51:53.180 に答える