Использование OpenMP и Eigen вызывает бесконечный цикл / тупик - PullRequest
10 голосов
/ 12 января 2012

Я решаю гораздо большую проблему и столкнулся с ошибкой при попытке использовать OpenMP для распараллеливания некоторых циклов. Я воспроизвел проблему с помощью более простого кода ниже, который имитирует мой собственный код.

Проблема в том, что когда я запускаю программу, она случайно попадает в какой-то бесконечный цикл / тупик (процессор на 100%, но ничего не делает). Из того, что я могу сказать из моего тестирования, один из потоков пытается вычислить матрично-матричный продукт, но по какой-то причине никогда не завершает работу.

Я знаю, что если вы включите OpenMP, Eigen будет распараллеливать матрично-матричные продукты, используя OpenMP. Я также добавляю еще один параллельный цикл вне этого. Однако эта ошибка все еще возникает, если я отключаю распараллеливание Эйгена, определяя EIGEN_DONT_PARALLELIZE.

Я использую gcc версии 4.6.0 20101127 на MacOS 10.6.8 с 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;
}

Ответы [ 3 ]

10 голосов
/ 12 января 2012

После некоторой отладки, я думаю, проблема в Eigen.В файле 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)

исправило мою проблему.

2 голосов
/ 26 августа 2012

У меня была такая же проблема при использовании 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, как подробнопредыдущий раздел.

2 голосов
/ 10 мая 2012

У меня была такая же проблема, даже с самой последней версией 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);
}

исправил мою проблему.

...