W swoim kodzie mam pętlę, w której konstruuję i ponad wyznaczony układ liniowy i próbuję go rozwiązać:
#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);
}
}
}
Czasami, całkiem przypadkowo, program zawiesza się lub wyniki w wektorze rozwiązania to NaN. A jeśli wstawię, zrób to:
arma::vec solution;
#pragma omp critical
{
solution = solve(weights*A,weights*y);
}
to wydaje się, że ten problem już się nie pojawia.
Kiedy się zawiesza, robi to, ponieważ niektóre wątki czekają na barierze 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
A inne wątki utknęły w 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
Jak widać ze stosu, moja wersja Armadillo używa atlasu. Zgodnie z tą dokumentacją atlas wydaje się być bezpieczny dla wątków: ftp://lsec.cc.ac.cn/netlib/atlas/faq.html#tsafe
Aktualizacja 11.09.2015
W końcu dostałem trochę czasu, aby przeprowadzić więcej testów, zgodnie z sugestiami Vladimira F.
Kiedy kompiluję pancernik z BLAS-em ATLAS-a, nadal jestem w stanie odtworzyć, a następnie zawiesza się i NaNs. Kiedy się zawiesza, jedyną rzeczą, która zmienia się w stacktrace, jest wywołanie 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
Kompilując bez ATLASA, tylko z netlib BLAS i LAPACK, byłem w stanie odtworzyć NaN, ale nie zawiesiłem się.
W obu przypadkach otaczając solve()
się #pragma
omp krytycznym nie mam żadnych problemów
Odpowiedzi:
Czy na pewno Twoje systemy są zbyt zdeterminowane?
solve_ud
w śladzie stosu mówi inaczej. Chociaż tysolve_od
też masz i prawdopodobnie nie ma to nic wspólnego z problemem. Ale nie zaszkodzi dowiedzieć się, dlaczego tak się dzieje i naprawić to, jeśli uważasz, że systemy powinny być złe.Myślę, że zależy to od twojej wersji lapack, zobacz też to . Patrząc na kod z
solve_od
wszystkich zmiennych dostępnych wydają się być lokalne. Zwróć uwagę na ostrzeżenie w kodzie:Dlatego wydaje się, że tylko
lapack::gels
może powodować kłopoty. Jeśli naprawienie lapack nie jest możliwe, obejściem jest ułożenie systemów w stos i rozwiązanie jednego dużego systemu. Byłoby to prawdopodobnie jeszcze bardziej wydajne, gdyby poszczególne systemy były małe.źródło
Bezpieczeństwo wątków funkcji Armadillo
solve()
zależy (tylko) od biblioteki BLAS, której używasz. Implementacje LAPACK są bezpieczne wątkowo, gdy BLAS jest. Funkcja Armadillo niesolve()
jest bezpieczna wątkowo podczas łączenia z referencyjną biblioteką BLAS . Jednak korzystanie z OpenBLAS jest bezpieczne wątkowo . Ponadto ATLAS zapewnia implementację BLAS, która również wspomina, że jest bezpieczna dla wątków , a Intel MKL również jest bezpieczny dla wątków , ale nie mam doświadczenia z Armadillo połączonym z tymi bibliotekami.Oczywiście dotyczy to tylko sytuacji, gdy uruchamiasz
solve()
z wielu wątków z różnymi danymi.źródło