犰狳solve()线程安全吗?


86

在我的代码中,我有一个循环,在该循环中构造并确定了线性系统并尝试解决该问题:

#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

其他线程卡在Armadillo内:

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

更新9/11/2015

我终于有时间根据弗拉基米尔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()#pragmaomp严重的情况下我都没有问题


1
/usr/lib64/libblas.so.3是地图集的一部分吗?为什么它不在/ usr / lib64 / atlas中?
弗拉基米尔F

1
不,在openuse中,它是liblas3软件包的一部分,在redhat中,它是blas软件包的一部分。
maxdebayser

2
这样,当您使用默认的BLAS时,您将无法使用ATLAS的任何保证。
弗拉基米尔F

2
你解决了吗?如果没有,将安装哪些软件包,您能否发布用于编译程序的命令?
vindvaki 2015年

3
您也可以尝试使用OpenBLAS代替Atlas。
2015年

Answers:


2

您确定您的系统已经确定了吗?solve_ud在您的堆栈跟踪中则相反。尽管您也有solve_od,但可能与该问题无关。但是找到问题的原因并修复它(如果您认为系统应该被修复)并没有什么害处。

犰狳solve()线程安全吗?

我认为取决于您的lapack版本,也请参阅。纵观代码solve_od所有访问的变量似乎是本地的。注意代码中的警告:

注意:ATLAS 3.6提供的lapack库中的dgels()函数似乎有问题

因此,这似乎只会lapack::gels给您带来麻烦。如果无法修复lapack,一种解决方法是将系统堆叠在一起并解决一个大型系统。如果您的单个系统很小,那可能会更有效率。


1

Armadillosolve()函数的线程安全性(仅)取决于您使用的BLAS库。当BLAS处于运行状态时,LAPACK实现是线程安全的。链接到参考BLAS库时,犰狳solve()函数不是线程安全的。但是,使用OpenBLAS时它是线程安全的。此外,ATLAS提供了BLAS实现,该实现还提到它是线程安全的,而Intel MKL也是线程安全的,但是我对将Armadillo链接到这些库没有任何经验。

当然,这仅适用于solve()从具有不同数据的多个线程运行。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.