zoukankan      html  css  js  c++  java
  • QuantLib 金融计算——一个线程安全隐患

    QuantLib 金融计算——一个线程安全隐患

    概述

    C++ 11 后标准库引入了 thread 以实现并行计算。与 OpenMP 不同,thread 对线程的操作属于粗粒度的,适合将若干耗时的计算任务先做独立封装,再并行运行。以蒙特卡洛方法为例,敏感性的计算需要反复进行模拟定价,而这些定价计算则可以借助 thread 并行化。

    一个线程安全隐患

    QuantLib 当前的设计存在着一个不易发觉的线程安全隐患,即 LazyObject 中避免重复计算的机制。LazyObject 用模板方法模式实现了 calculate,而 calculate 会修改 calculate_ 的值(一个 mutable 变量)。并行计算时可能在此处触发数据竞争,这导致 LazyObject 的派生类都是线程不安全的。

    例如,最常用的期限结构类 FlatForward 就是 LazyObject 的派生类,若并行计算任务直接或间接共用了同一个 FlatForward 对象,则可能引发程序崩溃。

    class LazyObject : public virtual Observer,
                       public virtual Observable {
      protected:
        mutable bool calculated_;
        virtual void performCalculations() const = 0;
    
      public:
        void update() { calculated_ = false; }
        virtual void calculate() const {
            if (!calculated_ && !frozen_) {
                calculated_ = true;   // prevent infinite recursion in
                                      // case of bootstrapping
                try {
                    performCalculations();
                } catch (...) {
                    calculated_ = false;
                    throw;
                }
            }
        }
    };
    

    解决办法

    若要修改源代码,参考 Effective Modern C++ 第 16 条,可以为 calculate 方法加锁。

    若不修改源代码,可以在并行计算开始前触发 LazyObject 的派生类对象的计算,使 calculated_ 的值为 true

    还是以 FlatForward 为例,calculatediscountImpl 中被调用,而计算零息利率、远期利率和贴现因子的方法都会调用 discountImpl。随便算一次贴现因子就可以使 calculated_ 的值为 true

    扩展阅读

    ★ 持续学习 ★ 坚持创作 ★
  • 相关阅读:
    8.02_python_lx_day14
    8.02_python_lx_day13<2>
    8.02_python_lx_day13<1>
    7.30_python_lx_day20
    7.29_python_lx_da19
    7.29_python_lx_day12
    Docker镜像
    Docker学习Ⅱ
    Docker学习Ⅰ
    2-3树的插入和删除原理
  • 原文地址:https://www.cnblogs.com/xuruilong100/p/15391319.html
Copyright © 2011-2022 走看看