1

これが私の状況です。いくつかのデータの配列を指すポインターの配列があります...たとえば、次のように言います。

    Data** array = malloc ( 100 * sizeof(Data*));
    for(i = 0; i < 100; i++) array[i] = malloc (20 * sizeof(Data);

並列領域内で、そのデータを使用するいくつかの操作を行います。例えば:

    #pragma omp parallel num_threads(4) firstprivate(array)
    {
         function(array[0], array[omp_get_thread_num()];
    }

最初のパラメータは読み取り専用ですが、すべてのスレッドで同じです...

問題は、最初のパラメーターとして異なるデータブロック、つまりarray [omp_get_thread_num()+ 1]を使用すると、各関数が1セグ持続することです。しかし、同じデータブロックarray [0]を使用すると、関数呼び出しは4セグメント続きます。

私の理論では、配列[0]が関数によって変更されるかどうかを知る方法がないため、各スレッドはコピーを要求し、他のスレッドが持っているコピーを無効にします。これにより、遅延が説明されます...

次のようにarray[0]のローカルコピーを作成しようとしました。

    #pragma omp parallel num_threads(4) firstprivate(array)
    {
        Data* tempData = malloc(20 * sizeof(Data));
        memcpy(tempData,array[0], 20*sizeof(Data));

        function(tempData, array[omp_get_thread_num()];
    }

しかし、同じ結果が得られます...スレッドがDataブロックを「解放」しないため、他のスレッドがそれを使用できるようになります...

最初のパラメーターは常にarray[0]であるとは限らないため、プラグマ行でfirstprivate(array [0])を使用できないことに注意する必要があります...

質問は次のとおりです。

  • 私は何か間違ったことをしていますか?
  • 他のスレッドがそれを使用できるように、メモリの共有ブロックを「解放」する方法はありますか?

理解させるのは大変でしたので、さらに詳しい情報が必要な場合はお知らせください!

よろしくお願いします...ハビエル

編集:ライブラリ内にあるため、関数宣言を変更できません!(ACML)

4

2 に答える 2

2

あなたの分析では、コンパイラーには、指定された配列が背後で変更されていないことを知る方法がないというのは正しいと思います。スレッドは変更可能な引数としても0同じものを受け取るので、実際には彼はそれらが変更される可能性があることを知っています。array[0]

したがって、彼は値を頻繁にリロードする必要があります。まず、関数を次のように宣言する必要があります

void function(Data const*restrict A, Data*restrict B);

Aこれは、最初に、の値を変更できないこと、次に、他の(または他のポインター)によってどのポインターもエイリアスできないこと、および配列内の値が変更されることをコンパイラーに通知します。関数自体によってのみ変更されます。

スレッド番号0の場合、上記のアサーションは真ではなく、配列AB実際には同じです。したがって、に入る前にarray[0]コモンにコピーし、それをすべてのスレッドの最初の引数と同じように渡すのが最善です。temparray #pragma omp paralleltemparray

Data const* tempData = memcpy(malloc(20 * sizeof(Data)), array[0], 20*sizeof(Data));

#pragma omp parallel num_threads(4)
function(tempData, array[omp_get_thread_num()];
于 2013-03-23T22:56:39.250 に答える