0

#pragma omp parallel forOpenMPを使用して、作業を異なるスレッド間で分割するようなものを使用して、このコードを並列化したいと思い ました。

効率的な方法は何でしょうか?ここで、レベルはさまざまなスレッド間で共有されます。

こちらはmakeがセットです。

for(iter=make.at(level).begin();iter!=make.at(level).end();iter++)
{
    Function(*iter);
}
4

3 に答える 3

2

によって返される型に一定のアクセス時間をmake.at(level)持つランダムアクセスイテレータがあり、コンパイラが最新の十分なOpenMPバージョンをサポートしている場合(読み取り:MSVC ++ではありませんparallel for)、 worksharingディレクティブを直接使用できます。

obj = make.at(level);
#pragma omp parallel for
for (iter = obj.begin(); iter != obj.end(); iter++)
{
    Function(*iter);
}

タイプがradom-accessイテレータを提供しないが、コンパイラがOpenMP 3.0以降をサポートしている場合は、OpenMPタスクを使用できます。

#pragma omp parallel
{
    #pragma omp single
    {
        obj = make.at(level);
        for (iter = obj.begin(); iter != obj.end(); iter++)
        {
            #pragma omp task
            Function(*iter);
        }
    }
}

ここでは、単一のスレッドがforループを実行し、多数のOpenMPタスクを作成します。各タスクはFunction()、対応するの値を使用して1回の呼び出しを行います*iter。次に、アイドル状態の各スレッドは、未完了のタスクのリストから選択を開始します。並列領域の終わりには暗黙のバリアがあるため、マスタースレッドはすべてのタスクが終了するのを忠実に待機してから、並列領域を超えて実行を続行します。

残念ながらMSVisualC ++を使用できない場合は、オブジェクトポインターの配列を作成し、単純な整数ループを使用してそれを反復処理する以外に選択肢はありません。

obj = make.at(level);
obj_type* elements = new obj_type*[obj.size()];
for (i = 0, iter = obj.begin(); i < obj.size(); i++)
{
    elements[i] = &(*iter++);
}

#pragma omp parallel for
for (i = 0; i < obj.size(); i++)
{
    Function(*elements[i]);
}

delete [] elements;

これは最も洗練されたソリューションではありませんが、機能するはずです。

編集:あなたの質問のタイトルから私が正しく理解している場合、あなたはセットで作業しています。セットはランダムアクセスイテレータをサポートしていないため、これにより最初のアルゴリズムが除外されます。OpenMPタスクに対するコンパイラーのサポートに応じて、2番目または3番目のアルゴリズムを使用します。

于 2012-07-12T08:10:28.057 に答える
0

forの並列変数はintに署名する必要があるようです。確信はないけど。これについてのトピックがあります。ループ変数を並列に署名する必要があるのはなぜですか?

于 2012-07-12T06:27:13.287 に答える
0

このイテレーターパターンをOpenMPで使用するには、ループの実行方法を再考する必要があり#pragma omp forます。ループは単純な整数ループではないため、使用できません。次のことがうまくいくかどうか疑問に思います:

iter = make.at(level).begin();
end  = make.at(level).end();

#pragma omp parallel private(iter) shared(make,level,end)
{
    #pragma omp single
    func(iter);                      /* only one thread does the first item */

    while (1)
    {
        #pragma omp critical
        iter = make.at(level).next(); /* each thread gets a different item */

        if (iter == end)
            break;

        func(iter);
    }
} /* end parallel block */

iter++それを機能させるには、クリティカルセクションであなたをnext()コールに変更する必要があったことに注意してください。これは、共有make.at(level)オブジェクトがどのアイテムがすでに処理されているかを記憶する必要があるためです。

于 2012-07-12T07:15:57.110 に答える