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
ます。
マトリックスのランダムな初期化も、上記のように並行して行われます。
これは、すべてのスレッドが同じマトリックスアドレス領域で機能するためだと思います。これは、ボトルネックが高速化を行っていないことが原因である可能性があります。すべてのスレッドはマトリックスの異なるセグメントで機能しますが、オーバーラップしません。
以前は、同様の特性を示す並列マージソートとクイックソートを実装していましたが、特定のスレッドが機能するデータセグメントを新しく割り当てられたメモリにコピーすると、高速化できました。
私の質問は、これは次の理由によるものです。
- メモリのボトルネック?
- 時間ベンチマークは適切な方法で行われていませんか?
- データセットが小さすぎますか?
- コーディングエラー?
- 他の
この場合、それがメモリのボトルネックである場合、共有メモリ上のスレッドへの複数のアクセスがミューテックスなしで実行できる場合でも、すべての並列プログラムは排他メモリ領域を使用しますか?
編集
マトリックスセグメントを次のように作成すると、スピードアップが見られます
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の小さな次元行列を何度も追加した場合にのみ、各反復で並列加算を呼び出す前に、ランダムな値を再割り当てしています。ここで気づいたスピードアップは本当ですか?または、他のいくつかの現象が影響を追いかけているためですか?