当我尝试使用OpenMP来并行化某些循环时,我解决了一个更大的问题并遇到了一个错误。我在下面用一些模仿自己代码的简单代码重现了这个问题。
问题在于,当我运行程序时,它将随机进入某种无限循环/死锁(CPU为100%,但不做任何事情)。从我的测试中可以看出,其中一个线程试图计算矩阵矩阵产品,但由于某种原因从未完成。
我知道如果启用OpenMP,Eigen将使用OpenMP并行化矩阵 - 矩阵产品。我还在此之外添加了另一个并行循环。但是,如果通过定义EIGEN_DONT_PARALLELIZE禁用Eigen的并行化,仍会出现此错误。
我在MacOS 10.6.8上使用gcc版本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 :(得分:10)
经过一些调试后,我认为问题出在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)
解决了我的问题。
答案 1 :(得分: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 :(得分: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自己的并行化,如前所述 部分。