Ist Gürteltier lösen () Thread sicher?

86

In meinem Code habe ich eine Schleife, in der ich ein überbestimmtes lineares System konstruiere und versuche, es zu lösen:

#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);
        }
    }
}

Manchmal hängt das Programm ganz zufällig oder die Ergebnisse im Lösungsvektor sind NaN. Und wenn ich das sage:

arma::vec solution;
#pragma omp critical 
{
    solution = solve(weights*A,weights*y);
}

dann scheinen diese Probleme nicht mehr aufzutreten.

Wenn es hängt, geschieht dies, weil einige Threads an der OpenMP-Barriere warten:

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

Und die anderen Fäden stecken in 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

Wie Sie dem Stacktrace entnehmen können, verwendet meine Version von Armadillo den Atlas. Und laut dieser Dokumentation scheint der Atlas threadsicher zu sein: ftp://lsec.cc.ac.cn/netlib/atlas/faq.html#tsafe

Update 9/11/2015

Ich hatte endlich Zeit, weitere Tests durchzuführen, basierend auf den Vorschlägen von Vladimir F.

Wenn ich Gürteltier mit ATLASs BLAS kompiliere, kann ich immer noch reproduzieren, hängt dann und die NaNs. Wenn es hängt, ändert sich im Stacktrace nur der Aufruf von 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

Ohne ATLAS kompiliert, nur mit Netlib BLAS und LAPACK, konnte ich die NaNs reproduzieren, aber nicht die Hänge.

In beiden Fällen habe ich überhaupt keine Probleme , wenn ich solve()mit #pragmaomp kritisch umgehe

maxdebayser
quelle
1
Ist /usr/lib64/libblas.so.3 Teil des Atlas? Warum befindet es sich nicht in / usr / lib64 / atlas?
Vladimir F
1
Nein, in opensuse ist es Teil des Pakets liblas3 und in redhat ist es Teil des Pakets blas.
Maxdebayser
2
Dann können Sie keine Garantien von ATLAS verwenden, wenn Sie das Standard-BLAS verwenden.
Vladimir F
2
Hast du das gelöst? Wenn nicht, welche Pakete sind installiert, und können Sie bitte den Befehl veröffentlichen, mit dem Sie das Programm kompiliert haben?
Vindvaki
3
Sie können auch versuchen, OpenBLAS anstelle von Atlas zu verwenden.
Montag,

Antworten:

2

Sind Sie sicher, dass Ihre Systeme überbestimmt sind? solve_udIn Ihrem Stack-Trace steht etwas anderes. Obwohl Sie auch haben solve_od, und wahrscheinlich hat das nichts mit dem Problem zu tun. Aber es tut nicht weh, herauszufinden, warum das passiert, und es zu beheben, wenn Sie der Meinung sind, dass die Systeme nicht funktionieren sollten.

Ist Gürteltier lösen () Thread sicher?

Dass ich denke, hängt von Ihrer Lapack-Version ab, sehen Sie auch dies . Mit Blick auf den Code von solve_odallen Variablen zugegriffen scheinen lokal zu sein. Beachten Sie die Warnung im Code:

HINWEIS: Die Funktion dgels () in der von ATLAS 3.6 bereitgestellten Lapack-Bibliothek scheint Probleme zu haben

Somit kann es nur lapack::gelsÄrger für Sie verursachen. Wenn das Reparieren von Lapack nicht möglich ist, besteht eine Problemumgehung darin, Ihre Systeme zu stapeln und ein einzelnes großes System zu lösen. Das wäre wahrscheinlich noch effizienter, wenn Ihre einzelnen Systeme klein sind.

Feuerameise
quelle
1

Die Thread-Sicherheit der Armadillo- solve()Funktion hängt (nur) von der von Ihnen verwendeten BLAS-Bibliothek ab. Die LAPACK-Implementierungen sind threadsicher, wenn BLAS aktiviert ist. Die Armadillo- solve()Funktion ist beim Verknüpfen mit der Referenz-BLAS-Bibliothek nicht threadsicher . Bei Verwendung von OpenBLAS ist es jedoch threadsicher . Darüber hinaus bietet ATLAS eine BLAS-Implementierung, in der auch erwähnt wird , dass sie threadsicher ist , und Intel MKL ist auch threadsicher , aber ich habe keine Erfahrung mit Armadillo, das mit diesen Bibliotheken verknüpft ist.

Dies gilt natürlich nur, wenn Sie solve()von mehreren Threads mit unterschiedlichen Daten ausgeführt werden.

André Offringa
quelle