В моем коде есть цикл, в котором я строю определенную линейную систему и пытаюсь ее решить:
#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
Обновление 11.09.2015
Наконец-то у меня появилось время провести дополнительные тесты, основанные на предложениях Владимира Ф.
Когда я компилирую броненосца с помощью ATLAS BLAS, я все еще могу воспроизвести, а затем зависания и NaN. Когда он зависает, единственное, что изменяется в stacktrace, - это вызов 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 критическим У меня нет никаких проблем вообще
Ответы:
Вы уверены, что ваши системы чрезмерно настроены?
solve_ud
в вашей трассировке стека говорится об обратном. Хотя у васsolve_od
тоже есть , и, вероятно, это не имеет отношения к проблеме. Но не помешает выяснить, почему это происходит, и исправить это, если вы считаете, что системы должны быть нестандартными.Это, я думаю, зависит от вашей версии Lapack, также см. Это . Глядя на код из
solve_od
всех переменных , доступных кажутся локальными. Обратите внимание на предупреждение в коде:Таким образом, кажется, только
lapack::gels
может доставить вам неприятности. Если починка Lapack невозможна, обходной путь состоит в том, чтобы сложить ваши системы и решить одну большую систему. Это, вероятно, было бы еще более эффективным, если бы ваши индивидуальные системы были небольшими.источник
Потоковая безопасность функции Armadillo
solve()
зависит (только) от библиотеки BLAS, которую вы используете. Реализации LAPACK являются потокобезопасными, когда BLAS. Функция Armadillo неsolve()
является потокобезопасной при связывании с эталонной библиотекой BLAS . Однако при использовании OpenBLAS это потокобезопасный . Кроме того, ATLAS предоставляет реализацию BLAS, в которой также упоминается, что он является потокобезопасным , и Intel MKL также является потокобезопасным , но у меня нет опыта работы с Armadillo, связанным с этими библиотеками.Конечно, это применимо только при запуске
solve()
из нескольких потоков с разными данными.источник