5

私は OpenMP にかなり慣れていないので、これは簡単な答えかもしれませんが、見つけることができませんでした。

次の C コードがあり、OpenMP を使用して並列化したいとします。A は、1 未満の double 値を持つオブジェクトの配列であり、バケットはリンクされたリストの配列であり、append はオブジェクトへのポインターをリンクされたリストの末尾に追加します。

#pragma omp for 
for (i = 0; i < n; ++i) {
    x = (int) (A[i].val * NUM_BUCKETS);
    append(&A[i], buckets[x]);
} 

問題は、複数のスレッドが一度に特定のバケットにアイテムを追加しようとする可能性があることです。その追加ステートメントをクリティカルにすることができます。ただし、私のアプリケーションでは、おそらく 1000 個程度のバケットを使用することになるため、ほとんどの場合、スレッドは異なるバケットで動作します。

バケットの個々の要素にロックを適用する方法はありますか? または、これを処理する他の方法はありますか?

4

2 に答える 2

12

OpenMP は自動的にそれを行うことはできませんが、配列要素へのアクセスを制限するために使用できる独自のロック変数を作成できます。たとえば、配列要素ごとに 1 つのロックを設定できます。

#include <stdio.h>
#include <omp.h>


int main(int argc, char **argv)
{
    const int NITEMS=20;
    int array[NITEMS];
    omp_lock_t lock[NITEMS];

    for (int i=0; i<NITEMS; i++)
        omp_init_lock(&(lock[i]));

#pragma omp parallel for shared(array, lock) default(none)
     for (int i=0; i<NITEMS; i++) {
        int tid = omp_get_thread_num();
        int item = (i * 7) % NITEMS;

        omp_set_lock(&(lock[item]));
        array[item] = tid;    // only one thread in here at a time; others block at set_lock()
        omp_unset_lock(&(lock[item]));
    }

    for (int i=0; i<NITEMS; i++)
        printf("%3d ", array[i]);
    printf("\n");

    for (int i=0; i<NITEMS; i++)
        omp_destroy_lock(&(lock[i]));


    return 0;
}

または、そのレベルの粒度が必要以上である場合は、配列の領域をブロックすることができます。

于 2012-06-14T00:26:07.013 に答える
2

OpenMP は、きめの細かいロックを提供しません。新しいリスト要素を準備できます。たとえば、そのnextポインタをに設定し、リスト末尾ポインタの更新を保護するためNULLに使用します。atomicこれは、現在の OpenMP 実装で得られるものと同じくらい問題ありません。

もちろん、OpenMP は基盤となる OS スレッド化プリミティブを使用するため、後者が提供するロックを使用できます。たとえば、pthreads各バケットにミューテックスの配列を使用できます。欠点は、移植性のないアプリケーションが作成されることですが、効率がより重要な場合は、移植性を犠牲にしてもかまいません。

于 2012-06-13T17:52:16.417 に答える