从多线程使用 QuantLib 的正确方法是什么?
What is the right way to use QuantLib from multiple threads?
我无法找到任何明确描述 QuantLib 的线程安全属性(或缺少它们!)的文档。 QuantLib configuration documentation 列出了一些与线程安全相关的编译时选项,据此我推断,默认情况下,QuantLib 并不完全是线程安全的。
具体有:
QL_ENABLE_SESSIONS - "If defined, singletons will return different instances for different sessions. You will have to provide and link with the library a sessionId() function in namespace QuantLib, returning a different session id for each session. Undefined by default."
QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN - "If defined, a thread-safe (but less performant) version of the observer pattern will be used. You should define it if you want to use QuantLib via the SWIG layer within the JVM or .NET eco system or any environment with an async garbage collector. Undefined by default."
QL_ENABLE_SINGLETON_THREAD_SAFE_INIT - "Define this to make Singleton initialization thread-safe. Undefined by default. Not compatible with multiple sessions."
如果我想使用 QuantLib,我应该使用哪些选项,我应该采取哪些其他步骤:
来自多个线程,但绝不会同时发生(例如,仅在持有全局锁时)?
同时来自多个线程,但它们之间不共享任何对象?
同时来自多个线程,它们之间共享对象?
我的应用程序的自然结构是一个有向无环图,市场数据源源不断地从一端进入,用于计算和更新各种对象,并生成估计价格流,从另一端离开.我非常希望能够有多个内核并行工作,因为有些计算需要很长时间。
该应用程序将主要使用 Java 编写,只有极少部分使用 C++ 来与 QuantLib 交互。我不打算使用 SWIG 包装器。我很高兴在没有 Java 垃圾收集器帮助的情况下对 QuantLib 对象进行内存管理。
编辑!如果你决定设置这些选项中的任何一个,那么在 unix 上,使用相应的标志来设置 ./configure:
--enable-sessions
--enable-thread-safe-observer-pattern
--enable-thread-safe-singleton-init
不幸的是,QuantLib 不是线程安全的。 None 的选项将对您有所帮助。 QuantLib 是一个免费项目,它的重点是实际的数学建模,而不是线程安全等计算优化。
您绝对应该将 QuantLib 包装在 进程 中。多线程 不 鼓励 QuantLib 除非您完全知道自己在做什么并检查了相关的源代码。
SmallChess 的回答与事实相去不远。 QuantLib 中几乎没有锁或安全网,因此如果大多数人需要在处理器上分配计算,他们会使用多处理——这是有充分理由的。
对于那些想要更深入了解的人,不是在 QuantLib 中使用多线程的认可:
无论你做什么,如果可能的话,启用给你一些安全的配置开关,例如用于单例线程安全初始化的开关(注意事项,见下文);
您可能同时拥有多个线程 运行 如果它们不共享任何对象,和 如果它们不尝试修改全局变量,例如评估日期(查找 类 从 Singleton 继承的全局变量列表)。
如果您需要不同线程的不同评估日期,您可以使用另一个编译开关来构建 QuantLib,以便单例实际上不是单例,但每个线程都有一个实例。警告:此开关与单例的线程安全初始化不兼容。你仍然不应该在线程之间共享对象。
如果你想共享对象,你可能会遇到更多的麻烦。问题是:(1) 对基础数据(例如曲线)的任何更改都会触发重新计算; (2) 重新计算(例如曲线的bootstrap)不会立即执行,而是仅在需要时执行,即调用某些曲线方法时执行。这意味着您必须将各个步骤分开:首先,设置任何引号的值并确保没有任何进一步的更改;然后,绕过曲线并触发重新计算,例如通过在某个日期询问折扣系数;最后,将曲线传递给工具并对其定价。在计算过程中更改值将导致 bootstrap 在计算中间完成;并且在计算之前不触发完整构建可能会导致两个工具同时触发两个 bootstraps,这对任何相关方来说都不会有好结果。
正如我所说,这可能比它的价值更麻烦。理想情况下,不要在线程之间共享对象,也不要接触全局变量。否则,更喜欢多处理。
我无法找到任何明确描述 QuantLib 的线程安全属性(或缺少它们!)的文档。 QuantLib configuration documentation 列出了一些与线程安全相关的编译时选项,据此我推断,默认情况下,QuantLib 并不完全是线程安全的。
具体有:
QL_ENABLE_SESSIONS - "If defined, singletons will return different instances for different sessions. You will have to provide and link with the library a sessionId() function in namespace QuantLib, returning a different session id for each session. Undefined by default."
QL_ENABLE_THREAD_SAFE_OBSERVER_PATTERN - "If defined, a thread-safe (but less performant) version of the observer pattern will be used. You should define it if you want to use QuantLib via the SWIG layer within the JVM or .NET eco system or any environment with an async garbage collector. Undefined by default."
QL_ENABLE_SINGLETON_THREAD_SAFE_INIT - "Define this to make Singleton initialization thread-safe. Undefined by default. Not compatible with multiple sessions."
如果我想使用 QuantLib,我应该使用哪些选项,我应该采取哪些其他步骤:
来自多个线程,但绝不会同时发生(例如,仅在持有全局锁时)?
同时来自多个线程,但它们之间不共享任何对象?
同时来自多个线程,它们之间共享对象?
我的应用程序的自然结构是一个有向无环图,市场数据源源不断地从一端进入,用于计算和更新各种对象,并生成估计价格流,从另一端离开.我非常希望能够有多个内核并行工作,因为有些计算需要很长时间。
该应用程序将主要使用 Java 编写,只有极少部分使用 C++ 来与 QuantLib 交互。我不打算使用 SWIG 包装器。我很高兴在没有 Java 垃圾收集器帮助的情况下对 QuantLib 对象进行内存管理。
编辑!如果你决定设置这些选项中的任何一个,那么在 unix 上,使用相应的标志来设置 ./configure:
--enable-sessions
--enable-thread-safe-observer-pattern
--enable-thread-safe-singleton-init
不幸的是,QuantLib 不是线程安全的。 None 的选项将对您有所帮助。 QuantLib 是一个免费项目,它的重点是实际的数学建模,而不是线程安全等计算优化。
您绝对应该将 QuantLib 包装在 进程 中。多线程 不 鼓励 QuantLib 除非您完全知道自己在做什么并检查了相关的源代码。
SmallChess 的回答与事实相去不远。 QuantLib 中几乎没有锁或安全网,因此如果大多数人需要在处理器上分配计算,他们会使用多处理——这是有充分理由的。
对于那些想要更深入了解的人,不是在 QuantLib 中使用多线程的认可:
无论你做什么,如果可能的话,启用给你一些安全的配置开关,例如用于单例线程安全初始化的开关(注意事项,见下文);
您可能同时拥有多个线程 运行 如果它们不共享任何对象,和 如果它们不尝试修改全局变量,例如评估日期(查找 类 从 Singleton 继承的全局变量列表)。
如果您需要不同线程的不同评估日期,您可以使用另一个编译开关来构建 QuantLib,以便单例实际上不是单例,但每个线程都有一个实例。警告:此开关与单例的线程安全初始化不兼容。你仍然不应该在线程之间共享对象。
如果你想共享对象,你可能会遇到更多的麻烦。问题是:(1) 对基础数据(例如曲线)的任何更改都会触发重新计算; (2) 重新计算(例如曲线的bootstrap)不会立即执行,而是仅在需要时执行,即调用某些曲线方法时执行。这意味着您必须将各个步骤分开:首先,设置任何引号的值并确保没有任何进一步的更改;然后,绕过曲线并触发重新计算,例如通过在某个日期询问折扣系数;最后,将曲线传递给工具并对其定价。在计算过程中更改值将导致 bootstrap 在计算中间完成;并且在计算之前不触发完整构建可能会导致两个工具同时触发两个 bootstraps,这对任何相关方来说都不会有好结果。
正如我所说,这可能比它的价值更麻烦。理想情况下,不要在线程之间共享对象,也不要接触全局变量。否则,更喜欢多处理。