2014년 4월 24일 목요일

C++ 에서 QuantLib-SWIG 와 Thread-Safe 한 Observer Pattern

원문출처

http://hpcquantlib.wordpress.com/2012/02/27/quantlib-swig-and-a-thread-safe-observer-pattern-in-c/

QuantLib은 사실 Thread-Safe 하지 않습니다. 멀티코어나 병렬환경에서의 성공적인 사용은 여러 프로세스간의  message passing에 의해서 보다는 shared memory 와 multi threading 에 의해서 이루어 집니다. 만약 서로다른 thread 가 서로 다른 object에서 작동을 한다면 QuantLib 또한 Multi threading 환경에서 사용될수 있습니다.(QL_ENABLE_SESSIONS 를 정의 하는 것은 singleton을 thread에 종속적이게 만듭니다.)

만약 당신이 QuantLib을 SWIG를 통하여 Java나 Scala에서 사용한다면 설령 메인 루틴이 싱글스레드 일지라도 QuantLib 루틴은 자동적으로 multi threading 환경에서 실행되어집니다.
JVM의 가비지 컬렉터는 보통 다른 thread에서 돌고 있습니다. 이것은 QuantLib에 구현되어 있는 Observer Pattern 과 결합하여 심각한 문제를 초래 할수 있습니다. 즉, 아래의 간단한 single thread Scala 코드는 멀티코어 컴퓨터에서 짧은 시간에 충돌이 일어날수 있습니다.

import org.quantlib.{Array => QArray, _}
object ObserverTest {
    def main(args: Array[String]) : Unit = {
        System.loadLibrary("QuantLibJNI");
        val aSimpleQuote = new SimpleQuote(0)

        while (true) {
            (0 until 10).foreach(_ => {
                new QuoteHandle(aSimpleQuote)
                aSimpleQuote.setValue(aSimpleQuote.value + 1)
            })
            System.gc
        }
    }
}
같은 객체가 동일한 시점에 aSimpleQuote.setValue 함수에 의해 update 함수가 호출될때 가비지 콜렉터는 observer의 소멸자를 호출합니다.(이 내용에 대한 QuantLib Mailing list는 여기에서 확인 할수 있습니다.). greenfield projects에서 [2]의 저자는 C++에서의 적당한 해답을 제시합니다. 안타깝게도 해당 솔루션은 QuantLib에 적용될 수 없었습니다. 해당 솔루션은 Observer pattern의 interface에 많은 변화를 주어야 하고 obsever pattern의 interface의 변경은 QuantLib library의 아주 많은 변화를 초래하기 때문이었습니다.

가장 중요한 문제는 Observer 가 Destructor가 작용하기 전에 사용불능 상태가 되는것입니다. 이것은 이론적으로 boost::shared_ptr의 새로운 instance 마다 특수한 "삭제자(Deleter)"를 추가하는 것이지만 이것 또한 library의 아주 많은 수정을 초래합니다.

전처리 지시자 BOOST_SP_ENABLE_DEBUG_HOOKS 와 함게 컴파일을 하면 boost library는 boost의 smart pointer의 소멸자가 호출되기전에 callback hook하는 것을 추가하게 된다. 이 hook은 observer의 소멸자가 호출되기전에 observer를 사용할수 없게 하는데 사용한다. 추가적으로 boost::signals2 library [3]은 간단하고 thread-safe한 공지 메커니즘을 제공한다.

원래의 QuantLib의 observer/Observable interface에 맞춰 수정된 thread-safe 한 구현은 여기서 찾을수 있다. 모든 소스파일에  전처리지시자 BOOST_SP_ENABLE_DEBUG_HOOKS를 set 한다. QuantLib project에 observable.hpp 와 observable.cpp 파일을 교체 혹은 추가하고 QuantLib library와 QuantLib-SWIG 모듈을 다시 컴파일 한다.

[1] Simplified Wrapper and Interface Generator, SWIG
[3] Douglas G., Mori Hess F., Boost.Signals2











댓글 없음:

댓글 쓰기