2012-01-11 8 views
10

OpenMPを使用していくつかのループを並列化しようとすると、より大きな問題を解決してバグに遭遇しました。私は自分のコードを模倣した以下の簡単なコードで問題を再現しました。OpenMPとEigenを使用すると無限ループ/デッドロックが発生する

問題は、私がプログラムを実行すると、無作為にループ/デッドロック(CPUは100%ですが、何もしません)にランダムに入ります。私のテストからわかるように、スレッドの1つは行列 - 行列積を計算しようとしますが、何らかの理由で終了することはありません。

OpenMPを有効にすると、EigenはOpenMPを使用してマトリックスマトリックス製品を並列化します。また、これ以外の並列ループも追加しています。しかし、EIGEN_DONT_PARALLELIZEを定義してEigenの並列化を無効にすると、このバグがまだ発生します。

MacOS 10.6.8でgig version 4.6.0 20101127をEigen 3.0.4で使用しています。私は間違って行くことができるかを把握することはできません

...

#include <iostream> 
#include <Eigen/Core> 

using namespace std; 
using namespace Eigen; 

MatrixXd Test(MatrixXd const& F, MatrixXd const& G) 
{ 
    MatrixXd H(F.rows(), G.cols()); 
    H.noalias() = F*G; 

    return H; 
} 

int main() 
{ 
    MatrixXd F = MatrixXd::Random(2,2); 
    MatrixXd G = MatrixXd::Random(2,2); 

    #pragma omp parallel for 
    for (unsigned int i = 0; i < 10000; ++i) 
    MatrixXd H = Test(F,G); 

    cout << "Done!" << endl; 
} 
+0

'MatrixXd :: Random'はスレッドセーフですか? – Mysticial

+0

私の実際のコードでは、MatrixXd :: Randomを呼び出していません。編集:MatrixXd :: Randomへの呼び出しを削除するようにコードを変更しましたが、バグはまだそこにあります。 – user1144371

+0

[this](http://eigen.tuxfamily.org/dox/TopicWrongStackAlignment.html)のような愚かではありませんか?現在、これはopenmpエラーのようには見えないためです。 gccのバージョン4.5.0 20100604で問題なく、あなたのプログラムを並行してダウンロードして実行しました。 – Bort

答えて

10

いくつかのデバッグした後、私は問題が固有に位置していると思います。

static std::ptrdiff_t m_l1CacheSize = 0; 
static std::ptrdiff_t m_l2CacheSize = 0; 
#pragma omp threadprivate(m_l1CacheSize, m_l2CacheSize) 

は私の問題を修正:

static std::ptrdiff_t m_l1CacheSize = 0; 
static std::ptrdiff_t m_l2CacheSize = 0; 

にこれを変更する:ファイルsrc/Core/products/GeneralBlockPanelKernel.hで2つの静的変数を宣言manage_caching_sizesと呼ばれる機能があります。

+2

は、私はちょうどこのバグは、最近の固有のバージョンで修正されたことに気づいた、このstackoverflowの質問への感謝は、バグレポートを参照してくださいEigenライブラリを更新します。 – catchmeifyoutry

2

最新のバージョンのEigen(3.0.5)でも同じ問題がありました。私は上で提案された修正を試しました、新しい初期化子のためバージョン3.0.5では不可能です。そこで、私は次のように変更しました:

static std::ptrdiff_t m_l1CacheSize; 
static std::ptrdiff_t m_l2CacheSize; 
#pragma omp threadprivate(m_l1CacheSize, m_l2CacheSize) 

if (m_l1CacheSize==0) 
{ 
    m_l1CacheSize = manage_caching_sizes_second_if_negative(queryL1CacheSize(),8 * 1024); 
    m_l2CacheSize = manage_caching_sizes_second_if_negative(queryTopLevelCacheSize(),1*1024*1024); 
} 

私の問題が修正されました。

2

Microsoft Visual Studio 2010 SP1 PPL/parallel_forを使用して同じ問題が発生していました。ソリューションは、独自のアプリケーションがマルチスレッド化されている場合には、マルチスレッドアプリケーション

に固有の使い方

http://eigen.tuxfamily.org/dox/TopicMultiThreading.html

に記載されており、複数の のスレッドが固有の呼び出しを行い、その後、あなたはする必要がありますスレッドを作成する前に、次のルーチンを呼び出すことにより、 固有の初期化:

#include <Eigen/Core> 

int main(int argc, char** argv) 
{ 
    Eigen::initParallel(); 

    ... 
} 

であなたのアプリケーションがOpenMPと並列化されている場合は、 は、前の セクションで詳述したように、Eigen自身のパラレル化を無効にしたいかもしれません。

関連する問題