在我的代码中,我有一个循环,我在其中构建并确定了线性系统并尝试解决它:
#pragma omp parallel for
for (int i = 0; i < n[0]+1; i++) {
for (int j = 0; j < n[1]+1; j++) {
for (int k = 0; k < n[2]+1; k++) {
arma::mat A(max_points, 2);
arma::mat y(max_points, 1);
// initialize A and y
arma::vec solution = solve(A,y);
}
}
}
有时,程序会随机挂起,或者解决方案向量中的结果是NaN。如果我这样做:
arma::vec solution;
#pragma omp critical
{
solution = solve(weights*A,weights*y);
}
然后这些问题似乎不再发生了。
当它挂起时,它会这样做,因为有些线程在OpenMP屏障等待:
Thread 2 (Thread 0x7fe4325a5700 (LWP 39839)):
#0 0x00007fe44d3c2084 in gomp_team_barrier_wait_end () from /usr/lib64/gcc-4.9.2/lib64/gcc/x86_64-redhat-linux-gnu/4.9.2/libgomp.so.1
#1 0x00007fe44d3bf8c2 in gomp_thread_start () at ../.././libgomp/team.c:118
#2 0x0000003f64607851 in start_thread () from /lib64/libpthread.so.0
#3 0x0000003f642e890d in clone () from /lib64/libc.so.6
其他线索被困在犰狳里面:
Thread 1 (Thread 0x7fe44afe2e60 (LWP 39800)):
#0 0x0000003ee541f748 in dscal_ () from /usr/lib64/libblas.so.3
#1 0x00007fe44c0d3666 in dlarfp_ () from /usr/lib64/atlas/liblapack.so.3
#2 0x00007fe44c058736 in dgelq2_ () from /usr/lib64/atlas/liblapack.so.3
#3 0x00007fe44c058ad9 in dgelqf_ () from /usr/lib64/atlas/liblapack.so.3
#4 0x00007fe44c059a32 in dgels_ () from /usr/lib64/atlas/liblapack.so.3
#5 0x00007fe44f09fb3d in bool arma::auxlib::solve_ud<double, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times> >(arma::Mat<double>&, arma::Mat<double>&, arma::Base<double, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times> > const&) () at /usr/include/armadillo_bits/lapack_wrapper.hpp:677
#6 0x00007fe44f0a0f87 in arma::Col<double>::Col<arma::Glue<arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times>, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times>, arma::glue_solve> >(arma::Base<double, arma::Glue<arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times>, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times>, arma::glue_solve> > const&) ()
at /usr/include/armadillo_bits/glue_solve_meat.hpp:39
从堆栈跟踪中可以看出,我的Armadillo版本使用了地图集。根据此文档,图集似乎是线程安全的:ftp://lsec.cc.ac.cn/netlib/atlas/faq.html#tsafe
2015年9月11日更新
根据Vladimir F的建议,我终于有时间进行更多测试。
当我用ATLAS的BLAS编译犰狳时,我仍然能够重现然后挂起和NaN。当它挂起时,堆栈跟踪中唯一改变的是调用BLAS:
#0 0x0000003fa8054718 in ATL_dscal_xp1yp0aXbX@plt () from /usr/lib64/atlas/libatlas.so.3
#1 0x0000003fb05e7666 in dlarfp_ () from /usr/lib64/atlas/liblapack.so.3
#2 0x0000003fb0576a61 in dgeqr2_ () from /usr/lib64/atlas/liblapack.so.3
#3 0x0000003fb0576e06 in dgeqrf_ () from /usr/lib64/atlas/liblapack.so.3
#4 0x0000003fb056d7d1 in dgels_ () from /usr/lib64/atlas/liblapack.so.3
#5 0x00007ff8f3de4c34 in void arma::lapack::gels<double>(char*, int*, int*, int*, double*, int*, double*, int*, double*, int*, int*) () at /usr/include/armadillo_bits/lapack_wrapper.hpp:677
#6 0x00007ff8f3de1787 in bool arma::auxlib::solve_od<double, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times> >(arma::Mat<double>&, arma::Mat<double>&, arma::Base<double, arma::Glue<arma::Mat<double>, arma::Mat<double>, arma::glue_times> > const&) () at /usr/include/armadillo_bits/auxlib_meat.hpp:3434
在没有ATLAS的情况下进行编译,仅使用netlib BLAS和LAPACK,我能够重现NaN而不是挂起。
在这两种情况下,围绕solve()
并且#pragma
omp严重我都没有问题
答案 0 :(得分:2)
您确定您的系统已经过度确定吗?堆栈跟踪中的solve_ud
表示不然。虽然你也有solve_od
,但这可能与这个问题无关。但是,如果您认为系统应该是od,那么找到为什么会发生并修复它并没有什么坏处。
犰狳是否解决()线程安全?
我认为这取决于您的lapack版本,另请参阅this。查看solve_od
lapack::gels
# x is a dataframe containing 50,000 ids.
访问的所有变量似乎都是本地的。请注意代码中的警告:
注意:ATLAS 3.6提供的lapack库中的dgels()函数 似乎有问题
因此,似乎只有dbGetQuery(con, "Select * from data where id in x")
可能会给您带来麻烦。如果无法修复lapack,则解决方法是堆叠系统并解决单个大型系统。如果您的个人系统很小,这可能会更有效。
答案 1 :(得分:1)
Armadillo solve()
函数的线程安全性(仅)取决于您使用的BLAS库。当BLAS是LAPACK实现时是线程安全的。链接到the reference BLAS library时,Armadillo solve()
函数不线程安全。但是,使用OpenBLAS时它是线程安全的。此外,ATLAS还提供了mentions it is thread safe和英特尔MKL is thread safe as well的BLAS实现,但我没有与这些库链接的Armadillo经验。
当然,这仅适用于从具有不同数据的多个线程运行solve()
的情况。