- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在比较 Matlab 和 C++ 之间普通看涨期权的蒙特卡罗定价算法的速度。这与 Why is MATLAB so fast in matrix multiplication? 不同因为加速不是由于矩阵乘法(只有一个快速完成的点积),而是由于其高效的高斯随机数生成器。
在 Matlab 中,代码已经被矢量化,代码如下所示
function [ value ] = OptionMCValue( yearsToExpiry, spot, strike, riskFreeRate, dividendYield, volatility, numPaths )
sd = volatility*sqrt(yearsToExpiry);
sAdjusted = spot * exp( (riskFreeRate - dividendYield - 0.5*volatility*volatility) * yearsToExpiry);
g = randn(1,numPaths);
sT = sAdjusted * exp( g * sd );
values = max(sT-strike,0);`
value = mean(values);
value = value * exp(-riskFreeRate * yearsToExpiry);
end
如果我按如下方式使用 1000 万条路径运行它
strike = 100.0;
yearsToExpiry = 2.16563;
spot = 100.0;
volatility = 0.20;
dividendYield = 0.03;
riskFreeRate = 0.05;
oneMillion = 1000000;
numPaths = 10*oneMillion;
tic
value = OptionMCValue( yearsToExpiry, spot, strike, riskFreeRate, dividendYield, volatility, numPaths );
toc
我明白了
Elapsed time is 0.359304 seconds.
12.8311
现在我在 VS2013 中用 C++ 做同样的事情
我的代码在 OptionMC 类中,如下所示
double OptionMC::value(double yearsToExpiry,
double spot,
double riskFreeRate,
double dividendYield,
double volatility,
unsigned long numPaths )
{
double sd = volatility*sqrt(yearsToExpiry);
double sAdjusted = spot * exp( (riskFreeRate - dividendYield - 0.5*volatility*volatility) * yearsToExpiry);
double value = 0.0;
double g, sT;
for (unsigned long i = 0; i < numPaths; i++)
{
g = GaussianRVByBoxMuller();
sT = sAdjusted * exp(g * sd);
value += Max(sT - m_strike, 0.0);
}
value = value * exp(-riskFreeRate * yearsToExpiry);
value /= (double) numPaths;
return value;
}
BM代码如下
double GaussianRVByBoxMuller()
{
double result;
double x; double y;;
double w;
do
{
x = 2.0*rand() / static_cast<double>(RAND_MAX)-1;
y = 2.0*rand() / static_cast<double>(RAND_MAX)-1;
w = x*x + y*y;
} while (w >= 1.0);
w = sqrt(-2.0 * log(w) / w);
result = x*w;
return result;
}
我已将优化选项设置为优化 Visual Studio 中的速度。
对于 10m 的路径,它需要 4.124 秒。
这比 Matlab 慢 11 倍。
谁能解释一下区别?
编辑:在进一步测试中,减速似乎是对 GaussianRVByBoxMuller 的调用。 Matlab 似乎有一个非常有效的实现 - Ziggurat 方法。请注意,BM 在这里不是最优的,因为它生成 2 个 RV,而我只使用 1 个。仅修复此问题将得到 2 倍的加速。
最佳答案
就目前而言,您正在生成单线程代码。猜测,Matlab 使用的是多线程代码。这使它的运行速度提高了大约 N 倍,其中 N = CPU 中的内核数。
不过,故事的内容远不止于此。出现的另一个问题是您正在使用 rand()
,它使用隐藏的全局状态。因此,如果您对代码进行简单的重写以使其成为多线程的,rand()
内部状态的冲突很有可能会阻止您获得很大的速度提升(并且可能很容易运行得更慢——也许慢很多)。
要解决这个问题,您可以考虑(例如)使用 C++11 中添加的新随机数生成(和可能的分布)类。有了这些,您可以为每个线程创建一个单独的随机数生成器实例,防止它们的内部状态发生冲突。
我稍微重写了您的代码以使用这些代码,并调用该函数以获取此信息:
double m_strike = 100.0;
class generator {
std::normal_distribution<double> dis;
std::mt19937_64 gen;
public:
generator(double lower = 0.0, double upper = 1.0)
: gen(std::random_device()()), dis(lower, upper) {}
double operator()() {
return dis(gen);
}
};
double value(double yearsToExpiry,
double spot,
double riskFreeRate,
double dividendYield,
double volatility,
unsigned long numPaths)
{
double sd = volatility*sqrt(yearsToExpiry);
double sAdjusted = spot * exp((riskFreeRate - dividendYield - 0.5*volatility*volatility) * yearsToExpiry);
double value = 0.0;
double g, sT;
generator gen;
// run iterations in parallel, with a private random number generator for each thread:
#pragma omp parallel for reduction(+:value) private(gen)
for (long i = 0; i < numPaths; i++)
{
g = gen(); // GaussianRVByBoxMuller();
sT = sAdjusted * exp(g * sd);
value += std::max(sT - m_strike, 0.0);
}
value = value * exp(-riskFreeRate * yearsToExpiry);
value /= (double)numPaths;
return value;
}
int main() {
std::cout << "value: " << value(2.16563, 100.0, 0.05, 0.03, 0.2, 10'000'000) << "\n";
}
我使用 VC++ 2015 编译了这个,使用以下命令行:
cl -openmp -Qpar -arch:AVX -O2b2 -GL test.cpp
在 AMD A8-7600 上,它运行了 ~.31 秒。
在 Intel i7 处理器上,运行时间约为 0.16 秒。
当然,如果您的 CPU 有更多的内核,您很有可能会运行得更快一些。
就目前而言,我的代码需要 VC++ 2015 而不是 2013,但我怀疑它对性能的影响很大。这主要是为了方便,比如使用 10'000'000
而不是 10000000
(但我不会在这台机器上安装 2013 的拷贝只是为了弄清楚我需要更改以适应它)。
另请注意,与最近的 Intel 处理器相比,您可能(或可能不会)通过将 arch:AVX
更改为 arch:AVX2
来获得一些改进。
快速检查单线程代码表明您的 Box-Muller 分发代码可能比标准库的正常分发代码快一点,因此切换到线程友好的版本可能会获得更快的速度(并且优化版本应该也大约是它的两倍)。
关于c++ - 为什么 Matlab 比 C++ 快 11 倍,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36130653/
在 Matlab 中,您可以选择创建新的“示例”脚本文件以及脚本、函数、类等。创建它们时,它们会获得一个脚本图标。 它们与其他标准脚本文件的处理方式有何不同? 是否有关于这些示例脚本类型的预期用途的文
我正在运行一个不是我自己编写的大 m 文件,它依赖于某些子函数。我想知道是否在所有嵌套函数的任何地方都使用了特定函数(在我的例子中是函数 eig.m(计算特征值))。有没有快速的方法来做到这一点? 亲
Matlab中有一个函数叫 copulafit .我怎样才能看到这个函数背后的代码?许多 Python 的 numpy 和 scipy 函数在 Github 上很容易开源,但由于某种原因我在 Gith
我定义了一个抽象基类measurementHandler < handle它定义了所有继承类的接口(interface)。这个类的两个子类是a < measurementHandler和 b < me
假设有一个矩阵 A = 1 3 2 4 4 2 5 8 6 1 4 9 例如,我有一个 Vector 包含该矩阵每一列的“类”
我有一个在后台运行的 Matlab 脚本。随着计算的进行,它会不断弹出进度栏窗口。这很烦人。 问题是我没有自己写 Matlab 脚本,这是一段很长很复杂的代码,我不想搞砸。那么如何在不修改 Matla
有没有办法从一个 matlab 程序中检测计算机上正在运行多少个 matlab 进程? 我想要恰好有 n 个 matlab 进程在运行。如果我的数量太少,我想创建它们,如果数量太多,我想杀死一些。您当
我正在测试我们在 Matlab 中开发的一个独立应用程序,当时我注意到它的内存使用量(根据 Windows 任务管理器)达到了 16gb 以上的数倍峰值。我决定在编译版本后面的脚本上使用 profil
我面临着一个相当棘手的问题。在 Matlab 中,命令 S = char(1044) 将俄语字母 д 放入变量 S。但是 disp(S) 返回空白符号,尽管内容实际上是正确的: >> S = char
我在这行 MATLAB 代码中遇到内存不足错误: result = (A(1:xmax,1:ymax,1:zmax) .* B(2:xmax+1,2:ymax+1,2:zmax+1) +
我正在寻找一种在 MATLAB 中比较有限顺序数据与非确定性顺序的方法。基本上,我想要的是一个数组,但不对包含的元素强加顺序。如果我有对象 a = [x y z]; 和 b = [x z y]; 我希
我有一个由 1 和 0 组成的二维矩阵。 mat = [0 0 0 0 1 1 1 0 0 1 1 1 1 1 0 0 1 0 0 0 1 0 1 1 0 0 1]; 我需
我可以在 Matlab 中用一组 x,y 点绘制回归线。但是,如果我有一组点(如下图),假设我有四组点,我想为它们绘制四条回归线……我该怎么做?所有的点都保存在 x,y 中。没有办法将它们分开并将它们
我正在尝试使用以下代码在 MATLAB 中绘制圆锥体。但是,当 MATLAB 生成绘图时,曲面中有一个间隙,如下图所示。谁能建议关闭它的方法? clearvars; close all; clc; [
我有一个 map称为 res_Map,包含一组不同大小的数组。我想找到用于存储 res_Map 的总内存。 正如您在下面看到的,看起来 res_Map 几乎不占用内存,而 res_Map 中的各个元素
有没有办法在 MATLAB 中组合 2 个向量,这样: mat = zeros(length(C),length(S)); for j=1:length(C) mat(j,:)=C(j)*S;
已结束。此问题不符合 Stack Overflow guidelines 。它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答它。 关闭 5 年前
我正在尝试将MatLab中的t copula适配到我的数据,并且我的功能是: u = ksdensity(range_1, range_1,'function','cdf'); v = ksdens
大家好,我目前正在尝试使用论文“多尺度形态学图像简化”中的 SMMT 运算符 Dorini .由于没有订阅无法访问该页面,因此我将相关详细信息发布在这里: 请注意,我将相关文章的部分内容作为图片发布。
我在MATLAB中编写代码,需要使用一个名为modwt的函数,该函数同时存在于两个我同时使用的工具箱(Wavelet和WMTSA)中。问题在于,一个版本仅返回一个输出,而另一个版本则返回三个输出。我应
我是一名优秀的程序员,十分优秀!