11

私はもっ​​と大きな問題を解決していて、OpenMP を使用していくつかのループを並列化しようとするとバグに遭遇しました。私自身のコードを模倣した以下のいくつかの単純なコードで問題を再現しました。

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

OpenMP を有効にすると、Eigen は OpenMP を使用して行列製品を並列化することを知っています。この外側に別の並列ループも追加しています。ただし、EIGEN_DONT_PARALLELIZE を定義して Eigen の並列化を無効にすると、このバグは依然として発生します。

Eigen 3.0.4 を搭載した MacOS 10.6.8 で gcc バージョン 4.6.0 20101127 を使用しています。

何がうまくいかないのかわかりません...

#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;
}
4

3 に答える 3

11

いくつかのデバッグの後、問題は Eigen にあると思います。ファイルには、 2 つの静的変数を宣言するsrc/Core/products/GeneralBlockPanelKernel.h関数が呼び出されています。manage_caching_sizes

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

これを次のように変更します。

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

私の問題を修正しました。

于 2012-01-12T19:07:27.820 に答える
2

Microsoft Visual Studio 2010 SP1 PPL / parallel_for を使用して同じ問題を抱えていました。解決策はに記載されています

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

マルチスレッド アプリケーションで Eigen を使用する

独自のアプリケーションがマルチスレッド化されており、複数のスレッドが Eigen を呼び出す場合、スレッドを作成する前に次のルーチンを呼び出して Eigen を初期化する必要があります。

#include <Eigen/Core>

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

  ...
}

アプリケーションが OpenMP で並列化されている場合、前のセクションで説明したように、Eigen 独自の並列化を無効にすることができます。

于 2012-08-26T12:31:25.670 に答える
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);
}

私の問題を修正しました。

于 2012-05-10T18:23:42.010 に答える