2012-01-11 21 views
10

Rozwiązuję znacznie większy problem i mam do czynienia z błędem, kiedy próbuję użyć OpenMP, aby zrównoleglić niektóre pętle. Odtworzyłem problem za pomocą prostszego kodu poniżej, który naśladuje mój własny kod.Używanie OpenMP i Eigen powoduje nieskończoną pętlę/zakleszczenie.

Problem polega na tym, że po uruchomieniu programu losowo przejdzie do jakiejś nieskończonej pętli/zakleszczenia (procesor jest w 100%, ale nic nie robi). Z tego, co mogę powiedzieć z moich testów, jeden z wątków próbuje obliczyć produkt macierzowo-macierzowy, ale nigdy się nie kończy z jakiegoś powodu.

Wiem, że jeśli włączysz OpenMP, Eigen będzie porównywać produkty macierzy z wykorzystaniem OpenMP. Dodaję też inną równoległą pętlę poza tym. Jednak ten błąd nadal występuje, jeśli wyłączę równoległość Eigena, definiując EIGEN_DONT_PARALLELIZE.

Używam gcc w wersji 4.6.0 20101127 na MacOS 10.6.8 z Eigen 3.0.4.

nie mogę dowiedzieć się, co może być nie tak ...

#include <iostream> 
#include <Eigen/Core> 

using namespace std; 
using namespace Eigen; 

MatrixXd Test(MatrixXd const& F, MatrixXd const& G) 
{ 
    MatrixXd H(F.rows(), G.cols()); 
    H.noalias() = F*G; 

    return H; 
} 

int main() 
{ 
    MatrixXd F = MatrixXd::Random(2,2); 
    MatrixXd G = MatrixXd::Random(2,2); 

    #pragma omp parallel for 
    for (unsigned int i = 0; i < 10000; ++i) 
    MatrixXd H = Test(F,G); 

    cout << "Done!" << endl; 
} 
+0

Czy "MatrixXd :: Random' thread-safe? – Mysticial

+0

W moim prawdziwym kodzie nie wzywam MatrixXd :: Random. Edytuj: Zmieniłem kod, aby usunąć połączenia do MatrixXd :: Random, a błąd nadal tam jest. – user1144371

+0

to nie jest głupie jak [to] (http://eigen.tuxfamily.org/dox/TopicWrongStackAlignment.html)? Ponieważ obecnie nie wygląda to jak błąd openmp. Pobrałem i uruchomiłem program równolegle bez żadnych problemów z gcc w wersji 4.5.0 20100604. – Bort

Odpowiedz

10

Po pewnym debugowania, myślę, że problem znajduje się w Eigen. W pliku src/Core/products/GeneralBlockPanelKernel.h istnieje funkcja o nazwie manage_caching_sizes który deklaruje dwie zmienne statyczne:

static std::ptrdiff_t m_l1CacheSize = 0; 
static std::ptrdiff_t m_l2CacheSize = 0; 

Zmiana tego celu:

static std::ptrdiff_t m_l1CacheSize = 0; 
static std::ptrdiff_t m_l2CacheSize = 0; 
#pragma omp threadprivate(m_l1CacheSize, m_l2CacheSize) 

ustalone mój problem.

+2

Właśnie zauważyłem, że ten błąd został naprawiony w ostatnich wersjach Eigen, dzięki temu pytaniu stackoverflow, zobacz raport błędu: http://eigen.tuxfamily.org/bz/show_bug.cgi?id=406 Więc teraz rozwiązanie byłoby zaktualizować bibliotekę własnych. – catchmeifyoutry

2

Miałem ten sam problem, nawet z najnowszą wersją Eigen (3.0.5). Próbowałem poprawki zaproponowanej powyżej i nie jest to możliwe w wersji 3.0.5, z powodu nowych inicjalizatorów. Wprowadziłem następującą zmianę:

static std::ptrdiff_t m_l1CacheSize; 
static std::ptrdiff_t m_l2CacheSize; 
#pragma omp threadprivate(m_l1CacheSize, m_l2CacheSize) 

if (m_l1CacheSize==0) 
{ 
    m_l1CacheSize = manage_caching_sizes_second_if_negative(queryL1CacheSize(),8 * 1024); 
    m_l2CacheSize = manage_caching_sizes_second_if_negative(queryTopLevelCacheSize(),1*1024*1024); 
} 

Naprawiono problem.

2

Wystąpił ten sam problem przy użyciu oprogramowania Microsoft Visual Studio 2010 SP1 PPL/parallel_for. Rozwiązaniem jest opisana w

http://eigen.tuxfamily.org/dox/TopicMultiThreading.html

Korzystanie Eigen w wielowątkowych aplikacji

W przypadku własnych aplikacji wielowątkowych i wielu wątki wykonywanie połączeń do Eigen, potem trzeba zainicjować Eigen przez wywołując następującą procedurę przed utworzeniem wątki:

#include <Eigen/Core> 

int main(int argc, char** argv) 
{ 
    Eigen::initParallel(); 

    ... 
} 

W W przypadku, gdy twoja aplikacja jest zsynchronizowana z OpenMP, możesz wyłączyć automatyczną paralelizację Eigen, tak jak to opisano w poprzednim rozdziale .