我有一个365个每日现金流量的排序数组(xDailyCashflowsDistro
),我随机抽样365次以获得每年的现金流量。生成由
1/ picking a random probability in the [0,1] interval
2/ converting this probability to an index in the [0,364] interval
3/ determining what daily cashflow corresponds to this probability by using the index and some linear aproximation.
并总结365生成的每日现金流量。按照前面提到的线程,我的代码预先计算了每日现金流量的差异(xDailyCashflowDiffs
)
xDailyCashflowDiffs[i] = xDailyCashflowsDistro[i+1] - xDailyCashflowsDistro[i]
因此整个代码看起来像
double _dIdxConverter = ((double)(365 - 1)) / (double)(RAND_MAX - 1);
for ( unsigned int xIdx = 0; xIdx < _xCount; xIdx++ )
{
double generatedVal = 0.0;
for ( unsigned int xDayIdx = 0; xDayIdx < 365; xDayIdx ++ )
{
double dIdx = (double)fastRand()* _dIdxConverter;
long iIdx1 = (unsigned long)dIdx;
double dFloor = (double)iIdx1;
generatedVal += xDailyCashflowsDistro[iIdx1] + xDailyCashflowDiffs[iIdx1] *(dIdx - dFloor);
}
results.push_back(generatedVal) ;
}
_xCount
(模拟次数)为1K +,通常为10K。
问题:
此刻模拟正在执行15M次(当写入第一个线程时为100K),在3.4GHz机器上需要大约10分钟。由于问题的性质,这个15M不太可能在未来显着降低,只会增加。使用过VTune Analyzer之后,我被告知最后一行(generatedVal += ...
)会产生80%的运行时间。我的问题是为什么以及如何使用它。
我尝试过的事情:
1 /摆脱(dIdx - dFloor)
部分,看看双重差异和乘法是否是罪魁祸首 - 运行时间下降了几个百分点
2 /将xDailyCashflowsDistro
和xDailyCashflowDiffs
声明为__restict
,以防止编译器认为它们相互依赖 - 无变化
5 /用不同的/ fp编译: - 没有变化
6 /编译为x64 - 对double&lt; - &gt;有影响。 ulong转换,但相关的行不受影响
我愿意牺牲的是解决方案 - 如果速度增益很大,我不关心generatedVal
最后是100010.1还是100020.0。
修改 每日/每年现金流量与整个投资组合相关。我可以按portflio大小划分所有每日现金流量,因此(99.99%置信水平)确保每日现金流/ pflio_size不会超出[-1000,+ 1000]区间。但在这种情况下,我需要精确到百分之一。
答案 0 :(得分:0)
也许您可以将分段线性函数转换为其值的分段线性“直方图”。您采样的数字似乎是该直方图中365个样本的总和。您正在做的是从该直方图中采集365个样本的总和,这是一种非常快速的方法。
您可以尝试计算傅立叶(或小波或类似)变换,仅保留前几个项,将其提升到365次幂,并计算逆变换。最后你不会得到概率分布,但是不应该有“太多”质量低于0或高于1,并且总质量不应该与这种技术的“太大不同”。 (我不知道你的数据是什么样的;出于好的数学原因,这种技术可能不可行。)