2012-03-30 24 views
2

非常に重いが、非常に並列なアルゴリズムを実行しています。OpenMPとベクトル操作の最適化

私はそれをスピードアップする方法を見てきました。私が持っている最も遅い操作は私のVecAdd機能です(6000程度の幅のベクトルで何千回も呼び出されます)。非常に単純なループ

bool VecAdd(float* pOut, const float* pIn1, const float* pIn2, unsigned int num) 
{ 
    for(int idx = 0; idx < num; idx++) 
    { 
     pOut[idx] = pIn1[idx] + pIn2[idx]; 
    } 
    return true; 
} 

そのするが、すべての追加が並行して行うことができる。

それは次のように実現されます。私の最初の最適化オプションは、SIMDを使って4倍近くのスピードアップを簡単に行うことができるようにすることです。

OpenMPを使用して自動的にforループをスレッド化することにも興味があります(可能であれば、さらに4倍のスピードアップをSIMDで合計16倍にすることができます)。

しかし、実際はゆっくりと実行されます。ループをまっすぐにすると、サンプルデータを処理するのに約3.2秒かかります。私は、forループの前に

#pragma omp parallel for 

を挿入した場合、私はそれが他のスレッドへの追加のいくつかのブロックを外注だろうと仮定しました。

残念なことに、私のサンプルデータの処理には約7秒かかります。

ここで私の多くの問題はスレッドの設定などのオーバーヘッドが原因で発生すると私は理解していますが、遅くても実行するのは驚きです。

スレッドプールを事前に設定することでこれをスピードアップすることは可能ですか、これらのオーバーヘッドと戦うことはできませんか?

これをOpenMPでうまくスレッド化できるかどうかについては、何かアドバイスをいただければ幸いです。

+0

一般的なOpenMP実装では、事前にスレッドプールを設定します。 –

+1

あなたの質問にはどこにも言及されていないので、あなたは各スレッドのために1つのコアを持っていますか? –

+0

各配列はちょうど6000浮動小数点なので、キャッシュの問題のようには見えません。どのOpenMP実装を使用していますか? – devil

答えて

4

あなたのループは、#pragma omp parallel forとうまく並列化する必要があります。 しかし、問題は、あなたがそのレベルで並列化すべきではないということです。関数は何千回も呼び出されますが、6000の浮動小数点でしか動作しません。より高いレベルで並列化すると、各スレッドはVecAddへの呼び出し/ 4を処理します。今、あなたは、このアルゴリズムを持っている:

  1. リスト項目
  2. シリアル実行
  3. (再)スレッドに開始
  4. 行う
  5. は(forループの終わりに)スレッドを同期短い計算
  6. シリアルコードに戻る

最高のpoで平行になるように変更しますレベル。

もちろんメモリの帯域幅は重要ですが、シリアル実行よりも遅くなることはありません。

+0

それは私が疑っていたほどです。乾杯! :) – Goz

関連する問題