【问题标题】:Is armadillo solve() thread safe?犰狳solve()线程安全吗?
【发布时间】:2015-07-15 19:02:12
【问题描述】:

在我的代码中,我有一个循环,我在其中构建和确定线性系统并尝试解决它:

#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

从堆栈跟踪中可以看出,我的犰狳版本使用了 atlas。根据这个文档,图集似乎是线程安全的: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,但不能重现挂起。

在这两种情况下,用#pragma 围绕solve() omp critical 我完全没有问题

【问题讨论】:

  • /usr/lib64/libblas.so.3 是地图集的一部分吗?为什么它不在 /usr/lib64/atlas 中?
  • 不,在 opensuse 中它是 liblas3 包的一部分,在 redhat 中它是 blas 包的一部分。
  • 那么当你使用默认的BLAS时,你不能使用任何ATLAS的保证。
  • 你解决了吗?如果没有,安装了哪些软件包,您能否发布您用于编译程序的命令?
  • 你也可以尝试用OpenBLAS代替Atlas。

标签: c++ multithreading openmp blas armadillo


【解决方案1】:

您确定您的系统过度确定了吗? solve_ud 在您的堆栈跟踪中另有说明。尽管您也有solve_od,但这可能与问题无关。但是,如果您认为系统应该是异常的,找出发生这种情况的原因并修复它并没有什么坏处。

犰狳solve() 线程安全吗?

我认为这取决于您的 lapack 版本,另请参阅 this。查看solve_odcode,所有访问的变量似乎都是本地的。注意代码中的警告:

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

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

【讨论】:

    【解决方案2】:

    Armadillo 的 solve() 函数的线程安全性(仅)取决于您使用的 BLAS 库。当 BLAS 是时,LAPACK 实现是线程安全的。链接到 the reference BLAS library 时,Armadillo solve() 函数不是线程安全的。但是,使用OpenBLAS 时它是线程安全的。此外,ATLAS 还提供了一个 BLAS 实现,也有 mentions it is thread safe 和英特尔 MKL is thread safe as well,但我没有使用链接到这些库的犰狳的经验。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-11-16
      • 1970-01-01
      相关资源
      最近更新 更多