2013-08-25 7 views
3

우분투에서 부스트 스레드와 잘 실행하는 데 사용되는 코드가 있습니다. 기본 읽기 전용 데이터 공유 멀티 스레딩입니다. boost 대신 C++ 11을 사용하려고합니다. 아주 기본적인 전환입니다. 코드는 컴파일되지만 미묘한 버그가 있습니다. 무작위로 C++ 11 std thread로 충돌합니다. valgrind drd를 사용하려고했지만 디버그 정보를 읽기가 어려웠습니다. 이견있는 사람?부스트와 C++ 11 스레드 호환성

==19608== Conflicting load by thread 3 at 0x00643be8 size 8 
==19608== at 0x41CEBA: std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>::operator()() (random.tcc:601) 
==19608== by 0x41CD6C: double std::generate_canonical<double, 53ul, std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul> >(std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>&) (random.tcc:3475) 
==19608== by 0x41CB06: std::__detail::_Adaptor<std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>, double>::operator()() (random.h:190) 
==19608== by 0x41C877: double std::normal_distribution<double>::operator()<std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul> >(std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>&, std::normal_distribution<double>::param_type const&) (random.tcc:1950) 
==19608== by 0x41C688: double std::normal_distribution<double>::operator()<std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul> >(std::subtract_with_carry_engine<unsigned int, 24ul, 10ul, 24ul>&) (random.h:2196) 
==19608== by 0x41C379: nrand(double, double) (NRand.cpp:8) 
==19608== by 0x416F78: ClassDef::set_x() (LoanDef.h:407) 
==19608== by 0x4168CA: Sim(std::vector<ClassDef, std::allocator<ClassDef> >&, Assumption&, std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > >&, unsigned int, NextStepCalcML&, std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >&, unsigned int, unsigned int) (NewSim.cpp:105) 
==19608== by 0x411A09: _ZNSt12_Bind_simpleIFPFvRSt6vectorI7LoanDefSaIS1_EER10AssumptionRSt13unordered_mapISsS0_IdSaIdEESt4hashISsESt8equal_toISsESaISt4pairIKSsS9_EEEjR14NextStepCalcMLRS0_IS0_IS9_SaIS9_EESaISN_EEjjESt17reference_wrapperIS3_EST_IS5_EST_ISI_EjST_ISK_EST_ISP_EjjEE9_M_invokeIILm0ELm1ELm2ELm3ELm4ELm5ELm6ELm7EEEEvSt12_Index_tupleIIXspT_EEE (functional:1732) 
==19608== by 0x4116AE: std::_Bind_simple<void (*()(std::reference_wrapper<std::vector<LoanDef, std::allocator<LoanDef> > >, std::reference_wrapper<Assumption>, std::reference_wrapper<std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > > >, unsigned int, std::reference_wrapper<NextStepCalcML>, std::reference_wrapper<std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > > >, unsigned int, unsigned int))(std::vector<LoanDef, std::allocator<ClassDef> >&, Assumption&, std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > >&, unsigned int, NextStep&, std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >&, unsigned int, unsigned int)>::operator()() (functional:1720) 
==19608== by 0x411647: std::thread::_Impl<std::_Bind_simple<void (*()(std::reference_wrapper<std::vector<ClassDef, std::allocator<ClassDef> > >, std::reference_wrapper<Assumption>, std::reference_wrapper<std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > > >, unsigned int, std::reference_wrapper<NextStep>, std::reference_wrapper<std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > > >, unsigned int, unsigned int))(std::vector<LoanDef, std::allocator<LoanDef> >&, Assumption&, std::unordered_map<std::string, std::vector<double, std::allocator<double> >, std::hash<std::string>, std::equal_to<std::string>, std::allocator<std::pair<std::string const, std::vector<double, std::allocator<double> > > > >&, unsigned int, NextStep&, std::vector<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > >, std::allocator<std::vector<std::vector<double, std::allocator<double> >, std::allocator<std::vector<double, std::allocator<double> > > > > >&, unsigned int, unsigned int)> >::_M_run() (thread:115) 

감사합니다. btw, 내가 쓴이 임의의 헤드 파일을 사용하려고했는데 다중 스레드 환경에서 안전한지 확실하지 않습니다. 그것은 부스트와 잘 작동하는 데 사용됩니다.

myrand.hpp

#ifndef NRAND_H 
#define NRAND_H 
#include <random> 

double nrand(double mean = 0., double sd = 1.); 
double urand(double a=0., double b=0.); 

#endif 

및 myrand.cpp

#include "NRand.h" 
using namespace std; 

double nrand(double mean, double sd) { 
    static random_device rd; 
    static subtract_with_carry_engine<unsigned,24,10,24> e(rd()); 
    normal_distribution<> dist(mean, sd); 
    return dist(e); 
} 

double urand(double a, double b) { 
    static random_device rd; 
    static subtract_with_carry_engine<unsigned,24,10,24> e(rd()); 
    uniform_real_distribution<> dist(a, b); 
    return dist(e); 
} 

많은 감사.

+0

@Rapptz이 질문은 의심의 여지가 없지만 대답이 없습니다. – Walter

+2

당신의'nrand'와'urand'는 절대로 thread safe하지 않으며, 정의되지 않은 동작을 호출합니다. – Casey

+0

랜덤 장치와 엔진을 비 정적으로 만들어야합니까? 그런 다음 오버 헤드를 제거하는 방법? 감사. – bbc

답변

2

IMHO, 당신의 코드는 스레드 안전하지 않으며, 따라서 C++ 11에서 제대로 작동하지 않을 수 있습니다. 문제는 static 변수 rde이 전역 변수이지만 (뮤텍스에 의해) 보호되지 않으므로 동시 호출이 경쟁 할 것이라고 생각합니다.

아마도 당신은 그 변수를 thread_local하여이 코드 스레드를 만들 수 있습니다,하지만 난 경험이 없다.

+0

고맙습니다. thread_local과 작동합니다. – bbc