1

私は宿題のために生産者/消費者の問題を実装しています。逐次アルゴリズムと並列アルゴリズムを比較する必要があります。私の並列アルゴリズムは、順次アルゴリズムと同じ速度または遅い速度でしか実行できないようです。キューの使用は制限要因であり、アルゴリズムの速度は向上しないという結論に達しました。

これは事実ですか、それともコーディングが間違っているだけですか?

int main() {
    long sum = 0;
    unsigned long serial = ::GetTickCount();
    for(int i = 0; i < test; i++){
        enqueue(rand()%54354);
        sum+= dequeue(); 
    }
    printf("%d \n",sum);

    serial = (::GetTickCount() - serial);
    printf("Serial Program took: %f seconds\n", serial * .001);
    sum = 0;
    unsigned long omp = ::GetTickCount();

    #pragma omp parallel for num_threads(128) default(shared) 
    for(int i = 0; i < test; i++){
        enqueue(rand()%54354);
        sum+= dequeue(); 

    }

    #pragma omp barrier //joins all threads
    omp = (::GetTickCount() - omp);
    printf("%d \n",sum);
    printf("OpenMP Program took: %f seconds\n", omp * .001);
    getchar();
}
4

1 に答える 1

2

問題#1:

rand()並列領域内にあります。

rand()スレッドセーフではありません。グローバル/静的変数を使用します。そのため、複数のスレッドから同時に呼び出すと、予期しない (おそらく未定義の) 動作が発生します。

それはさておき、 への同時呼び出しから生じるデータ競合はrand()、多くのキャッシュ コヒーレンス ストールにつながります。これが速度低下の原因と考えられます。


問題#2:

enqueue()とはdequeue()スレッドセーフですか?

そうでない場合は、まずそれを修正する必要があります。もしそうなら、どのように同期していますか?

一度に 1 つのスレッドのみがキューにアクセスできる重要な領域である場合、そのようなものは並列処理の目的全体を無効にします。


問題 3:

この行は、sum反復ごとに変数を変更します。

sum += dequeue(); 

すべてのスレッドが同時にこれを行うことに注意してください。sumしたがって、リダクション変数として宣言する必要があります。

于 2012-05-07T06:36:24.790 に答える