2015-05-05 18 views
85

Nel mio codice che ho ciclo in cui costruisco e più determinato sistema lineare e cercare di risolverlo:Il thread armadillo solve() è sicuro?

#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, del tutto casualmente il programma si blocca oi risultati nel vettore soluzione sono NaN. E se metto in questo modo:

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

quindi questi problemi non sembrano più accadere.

Quando si blocca, lo fa perché alcuni thread sono in attesa alla barriera 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 thread sono bloccati all'interno 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 si può vedere dalla stacktrace la mia versione di Armadillo usa l'atlante. E secondo questa documentazione 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 armadillo con BLAS di ATLAS, sono ancora in grado di riprodurre quindi hang e NaN. Quando si blocca, l'unica cosa che cambia nel StackTrace è la chiamata alla BLAS:

#0 0x0000003fa8054718 in [email protected]() 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 

compilazione senza ATLAS, solo con netlib BLAS e LAPACK, sono stato in grado di riprodurre le NaNs ma non si blocca.

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

+1

È /usr/lib64/libblas.so.3 parte dell'atlante? Perché non si trova in/usr/lib64/atlas? –

+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. –

risposta

2

Sei sicuro i vostri sistemi sono oltre determinati? solve_ud nella traccia dello stack dice diversamente. Anche se hai anche solve_od, probabilmente non ha nulla a che fare con il problema. Ma non fa male scoprire perché sta accadendo e aggiustarlo se pensi che i sistemi dovrebbero essere od.

È un thread di armadillo solve() sicuro?

Che penso dipenda dalla versione della confezione, vedere anche this. Guardando il code di solve_od tutte le variabili a cui si accede sembrano essere locali. Si noti l'avviso nel codice:

NOTA: i dgels (funzione) nella libreria LAPACK fornito da ATLAS 3,6 sembra avere problemi

Così sembra solo lapack::gels può causare problemi per voi. Se non è possibile risolvere il problema, una soluzione alternativa è quella di impilare i sistemi e risolvere un singolo sistema di grandi dimensioni. Probabilmente sarebbe ancora più efficiente se i tuoi singoli sistemi fossero piccoli.

0

La sicurezza del thread della funzione solve() di Armadillo dipende (solo) dalla libreria BLAS che si utilizza.Le implementazioni di LAPACK sono thread-safe quando BLAS è. La funzione Armadillo solve() è non thread safe quando si collega a the reference BLAS library. Tuttavia, è thread-safe quando si utilizza OpenBLAS. Inoltre, ATLAS fornisce un'implementazione BLAS che è anche mentions it is thread safe e Intel MKL is thread safe as well, ma non ho esperienza con Armadillo collegato a tali librerie.

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