0

次のようなプログラムブロックがあります。

    for (iIndex1=0; iIndex1 < iSize; iIndex1++)
    {
        for (iIndex2=iIndex1+1; iIndex2 < iSize; iIndex2++)
        {   
            iCount++;
            fDist =(*this)[iIndex1].distance( (*this)[iIndex2] );
            m_oPDF.addPairDistance( fDist );

            if ((bShowProgress) && (iCount % 1000000 == 0))
                xyz_exception::ui()->progress( iCount, (size()-1)*((size()-1))/2 );

        }
    }
} 
}

内側と外側のループを並列化し、iCount を重要な領域に配置しようとしました。これを並列化するための最良のアプローチは何でしょうか? iCount を omp single または omp atomic でラップすると、コードでエラーが発生し、omp for 内では無効であることがわかりました。これを並列化するために、多くの無関係なものを追加していると思います。アドバイスが必要...

ありがとう、

サヤン

4

3 に答える 3

1

私があなたの意図を正しく解釈した場合、iCount を使用して、いつ (10^6 操作ごとに) UI を更新するかをプログラムに伝えたいですか? iCount はグローバルで、すべてのスレッドが値を共有し、その一貫性を維持したいですか?

このグローバル カウンターを各スレッド専用のカウンターに置き換えて、スレッドにメッセージを送信させて、UI を互いに独立して更新する方法を探します。グローバル カウンターの使用を主張する場合は、何らかの方法でスレッド間で同期する必要があり、パフォーマンスが低下します。はい、そのようにプログラムを書くこともできますが、お勧めしません。

すべてのスレッドが UI にメッセージを送信するという考えが気に入らない場合は、おそらく 1 つのスレッドだけでそれを行うことができます。1 つのスレッドがプログラム全体の 1/4 に到達した場合、他のスレッドも (ほぼ) 終了します。

于 2010-05-25T14:19:45.033 に答える
0

マークに感謝します。iCountを削除し、外側のループを並列にしましたが、シリアルバージョンと比較した場合、まだスピードアップが見られないため、コードを掘り下げています。

この機会を利用して、基本的な事実を明らかにしたいと思います...上記のようなネストされたループ環境で...一般的にはどちらが良いかもしれません:

  1. 内側のループを平行にする

    pragma omp parallel
    for(... i ...)
    pragma omp for
    for(... j ...)

  2. 外側のループを平行にする(外側のループの前の...プラグマを平行にする)

  3. 折りたたみの使用(Omp 3.0の場合)

ありがとう
サヤン

于 2010-05-31T17:31:41.817 に答える
0

ありがとう、マーク。教えていただいた方法を試してみました。reduction(+:iCount) を配置し、iCount++ を pragma critical にラップしようとしましたが、パフォーマンス ヒットです (スピードアップも見られませんでした)。また、1 つのスレッドで iCount を処理できるようにしましたが、私が行ったアプローチでは速度が向上しませんでした。

内側のループの周りにプラグマ for を配置し、リダクション変数として iCount を宣言すると、少なくともいくらかの速度向上に気付くだろうと期待していました。私の目的は、Index1、Index2 のペアに対してこれらのステートメントを並列実行することです。

        fDist =(*this)[iIndex1].distance( (*this)[iIndex2] );
        m_oPDF.addPairDistance( fDist );

これは、プログラムの実行時間に著しく影響を与える可能性があります。

于 2010-05-25T20:43:16.130 に答える