激しい計算にOpenMPスレッドを使用する予定です。しかし、私は最初の試行で期待されるパフォーマンスを得ることができませんでした。私はそれにいくつかの問題があると思ったが、私はまだ保証していない。一般的に、私はパフォーマンスのボトルネックがフォークと結合モデルから発生していると考えています。あなたはいくつかの点で私を助けてくれますか? 最初に、コンシューマスレッド上で実行されるルートサイクルでは、2つの独立したループといくつかの追加機能があります。openMpを使用した複数の独立したforループのパフォーマンスの問題
void routineFunction(short* xs, float* xf, float* yf, float* h)
{
// Casting
#pragma omp parallel for
for (int n = 0; n<1024*1024; n++)
{
xf[n] = (float)xs[n];
}
memset(yf,0,1024*1024*sizeof(float));
// Filtering
#pragma omp parallel for
for (int n = 0; n<1024*1024-1024; n++)
{
for(int nn = 0; nn<1024; nn++)
{
yf[n]+=xf[n+nn]*h[nn];
}
}
status = DftiComputeBackward(hand, yf, yf); // Compute backward transform
}
注:機能は既に以下に見られるループ、ルーチンサイクルの終了時との間に配置されるI詳細をクリアするなど、それがより読めるなかったので、このコードは、compiliedすることができません。
OpenMPスレッド番号は動的に8に設定されます。私は、Windowsタスクバーの使用スレッドを観察しました。スレッド数は大幅に増えますが、パフォーマンスの向上は見られませんでした。私はいくつかの推測をしていますが、今後の実装についてあなたと議論したいと思います。
私の質問は次のとおりです。
フォークと結合モデルはスレッドの作成と中止に対応していますか?それはソフトウェアにとって同じコストですか?
routineFunctionがコンシューマによって呼び出されると、OpenMPスレッドは毎回forkとjoinを実行しますか?
rutineFunctionの実行中に、OpenMPスレッドのスレッドフォークを行い、forループごとに結合しますか?または、コンパイラは2番目のループを既存のスレッドを扱うように助けますか?その場合、forループは2回forkとjoinを行い、コードを再度整列させます。パフォーマンスを節約したり、並列領域(
#pragma omp parallel
)と#pragma omp for
(#pragma omp parallel for
ではなく)を使用して共有する方が、ループを1つのループにまとめる方が合理的です。スレッドIDとスレッド番号を使用して静的スケジューリングを強制します。 the document at page 34によれば、静的スケジューリングは負荷の不均衡を引き起こす可能性があります。実際には、私はCUDAプログラミングのため静的スケジューリングに精通していますが、パフォーマンス上の問題があれば、それを避けたいと思います。また、パラレル領域が完成した後、スマートなOpenMPアルゴリズムがマスタースレッドに参加しないことを指摘するstackoverflowの回答をAlexey Kukanov in last paragraphで読みました。最初のループが完了した後、マスタースレッドへの参加を避けるために、OpenMPのビジー待機およびスリープ属性を利用する方法。コードでパフォーマンスの問題が発生する別の理由はありますか?
2つの質問:どのように時間を測定しますか?パラレル化された領域は、連続したウォールクロック時間の何パーセントに相当しますか? – Gilles
私はclock()を使用しましたが、その時間分解能は1ミリ秒でしたが、routineFunctionを100000回テストし、その平均値を取得しました。 – Abdullah
'clock()'を使用することがタイミングの並列効率に関して今までにない最も悪い考えである理由を理解するには、[this](http://stackoverflow.com/q/10673732/5239503)を参照してください。 – Gilles