Armadillo solve () thread safe?


86

Nel mio codice ho un ciclo in cui costruisco e un sistema lineare eccessivamente determinato e cerco di risolverlo:

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

A volte, in modo abbastanza casuale, il programma si blocca oi risultati nel vettore di soluzione sono NaN. E se metto fai questo:

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

allora questi problemi sembrano non verificarsi più.

Quando si blocca, lo fa perché alcuni thread sono in attesa alla barriera di 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

E gli altri fili sono bloccati all'interno di 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

Come puoi vedere dallo stacktrace, la mia versione di Armadillo usa l'atlante. E secondo questa documentazione, l'atlante sembra essere thread-safe: ftp://lsec.cc.ac.cn/netlib/atlas/faq.html#tsafe

Aggiornamento 9/11/2015

Finalmente ho avuto un po 'di tempo per eseguire altri test, sulla base dei suggerimenti di Vladimir F.

Quando compilo l'armadillo con il BLAS di ATLAS, riesco ancora a riprodurre gli hang e i NaN. Quando si blocca, l'unica cosa che cambia nello stacktrace è la chiamata a 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

Compilando senza ATLAS, solo con netlib BLAS e LAPACK, sono stato in grado di riprodurre i NaN ma non gli hang.

In entrambi i casi, che circonda solve()con #pragmaOMP critica non ho problemi a tutti


1
/Usr/lib64/libblas.so.3 fa parte di atlas? Perché non si trova in / usr / lib64 / atlas?
Vladimir F

1
No, in opensuse fa parte del pacchetto liblas3 e in redhat fa parte del pacchetto blas.
maxdebayser

2
Quindi non è possibile utilizzare alcuna garanzia di ATLAS quando si utilizza il BLAS predefinito.
Vladimir F

2
Hai risolto questo problema? In caso contrario, quali pacchetti sono installati e potresti inviare il comando che hai usato per compilare il programma?
vindvaki

3
Puoi anche provare a utilizzare OpenBLAS invece di Atlas.
mtall

Risposte:


2

Sei sicuro che i tuoi sistemi siano troppo determinati? solve_udnella tua traccia dello stack dice il contrario. Anche se lo hai fatto solve_odanche tu , e probabilmente non ha nulla a che fare con il problema. Ma non fa male scoprire perché sta succedendo e risolverlo se pensi che i sistemi dovrebbero essere inefficaci.

Armadillo solve () thread safe?

Questo penso dipenda dalla tua versione del lapack, guarda anche questo . Guardando il codice di solve_odtutte le variabili a cui si accede sembra essere locale. Nota l'avviso nel codice:

NOTA: la funzione dgels () nella libreria lapack fornita da ATLAS 3.6 sembra avere problemi

Quindi sembra che solo lapack::gelspuò causare problemi per te. Se non è possibile riparare lapack, una soluzione alternativa è impilare i sistemi e risolvere un unico sistema di grandi dimensioni. Probabilmente sarebbe ancora più efficiente se i tuoi sistemi individuali fossero piccoli.


1

La sicurezza del thread della solve()funzione di Armadillo dipende (solo) dalla libreria BLAS che utilizzi. Le implementazioni di LAPACK sono thread-safe quando BLAS lo è. La solve()funzione Armadillo non è thread-safe quando si collega alla libreria BLAS di riferimento . Tuttavia, è thread-safe quando si utilizza OpenBLAS . Inoltre, ATLAS fornisce un'implementazione BLAS che menziona anche che è thread-safe e Intel MKL è anche thread-safe , ma non ho esperienza con Armadillo collegato a quelle librerie.

Ovviamente, questo si applica solo quando si esegue solve()da più thread con dati diversi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.