罗兰关于MATLAB的艺术

将想法转化为MATLAB

在多gpu上运行蒙特卡罗模拟

今天我要介绍詹姆斯·勒巴克。James是并行计算工具箱中GPU支持的开发者。万博1manbetx

内容

GPU上的基本期权定价

多gpu系统的一个常见用途是执行蒙特卡罗模拟。使用更多的gpu可以增加可以模拟的样本数量,从而实现更精确的模拟。

让我们从基本的期权定价模拟开始并行计算工具箱例子基于Monte-Carlo方法的GPU奇异期权定价.在这个例子中,我们运行了许多股票价格演变的并发模拟。模拟输出的平均值和分布给我们一种股票最终价值的感觉。

这个函数simulateStockPrice描述股票价格的是一个离散的随机微分方程。该方程假设价格的演化符合对数正态分布,与无风险利率、股息收益率(如果有的话)和市场波动性相关。

类型simulateStockPrice
函数finalStockPrice = simulateStockPrice(stockPrice, rate,…股息,波动性,…股票价格的离散模拟t = 0;当t < Tfinal时,t = t + dT;dr = (rate - dividend - volatility*volatility/2)*dT;微扰=波动* sqrt (dT) * randn ();stockPrice = stockPrice*exp(dr +扰动);end finalStockPrice =股票价格;结束

在GPU上实现良好的性能需要并行执行许多操作。GPU有成千上万个独立的计算单元,当你执行数十万或数百万个并行操作时,你就能从中获得最佳的性能。这与我们经常给出的建议相似vectorize函数,以获得更好的性能。这个函数simulateStockPrice产生一个单一的标量输出,因此如果我们按原样运行它,它将无法获得良好的性能。

我们可以在GPU上执行多次仿真使用ARRAYFUN.的arrayfun函数在GPU上有一个函数柄和一个gpuArray输入,并在输入的每个元素上执行函数gpuArray.这是向量化函数的一种替代方法,因为向量化函数需要修改更多代码。它为输入中的每个元素返回一个输出。这正是我们在蒙特卡罗模拟中想要做的:我们想要产生许多独立的输出。

runSimulationOnOneGPU函数使用arrayfun并行执行多个模拟并返回平均价格。

类型runSimulationOnOneGPU.m
function mfp = runSimulationOnOneGPU(Nsamples) %在GPU上运行单个股票模拟,并返回CPU上的%平均文件价格。上涨空间= 100;%股票价格100美元起。股息= 0.01;年股息率% 1%。riskFreeRate = 0.005;% 0.5%。timeToExpiry = 2;%选项的生存期,以年为单位。sampleRate = 1/250; % Assume 250 working days per year. volatility = 0.20; % 20% volatility. % Create the input data. Any scalar inputs are expanded to the size of the % array inputs. In this case, the starting stock prices is a vector whose % length is the number of simulations to perform on the GPU at once, and % all of the other inputs are scalars. startPrices = stockPrice*gpuArray.ones(Nsamples, 1); % Run all Nsamples simulations in parallel with one call to arrayfun. finalPrices = arrayfun( @simulateStockPrice, ... startPrices, riskFreeRate, dividend, volatility, ... timeToExpiry, sampleRate ); mfp = gather(mean(finalPrices)); end

我们使用相对较少的样本执行这个函数,并显示计算出的平均值。

nSamples = 1 e6;meanFinalPrice = runSimulationOnOneGPU (nSamples);disp ([“计算平均最终价格”num2str (meanFinalPrice)]);
最终平均计算价格为98.96

在一台机器上使用多个gpu

假设我们希望在带有两个gpu的台式机上运行这个模拟。这将允许我们在相同的时间内拥有更多的样本,根据大数定律,这将给我们一个更好的最终股票平均价格的近似。

利用并行计算工具箱,MATLAB可以在多个gpu上执行计算。为了做到这一点,我们需要为每个GPU打开一个工作器的MATLAB池。需要一个MATLAB工作人员与每个GPU通信。

池中的工作人员将完成所有的计算,因此客户端不需要使用gpuDevice.取消选择客户端上的设备,以便所有设备上的所有内存对工作人员完全可用。

gpuDevice ([]);

确定我们在这台机器上有多少gpu,并打开这个大小的本地MATLAB池。这就为这台机器上的每个GPU提供了一个worker。

nGPUs = gpuDeviceCount ();matlabpool (“本地”, nGPUs);
使用'local'配置文件启动matlabpool…连接2个工人。

runSimulationOnManyGPUs函数包含一个parfor循环执行硝酸钠次了。函数的每次迭代parfor循环执行nSamples在一个GPU上独立的蒙特卡罗模拟,并返回所有这些模拟的最终平均价格。整体模拟的输出是个体均值的平均值,因为每个parfor迭代执行相同数量的独立模拟。当循环结束时,我们已经执行了硝石* nSamples模拟。

类型runSimulationOnManyGPUs.m
函数[tout, mfp] = runsimulationonmanygpu (nSamples, nIter) %执行总计nSamples*nIter模拟,将%模拟分布在matlabpool中的各个工作人员中。抽搐;parfor ix = 1:nIter meanFinalPrice(ix) = runSimulationOnOneGPU(nSamples);end mfp = mean(meanFinalPrice);兜售= toc;

运行nSamples在每个GPU上的迭代,我们称之为runSimulationOnManyGPUs硝酸钠等于gpu的数量。

[tout, meanFinalPrice] = runsimulationonmanygpu (nSamples, nGPUs);disp ([“在GPU上执行模拟”num2str(宣传),“年代”]);disp ([“计算平均最终价格”num2str (meanFinalPrice)]);
计算出的平均最终价格为98.9855

重要的是,返回的结果作为常规MATLAB数组,而不是作为gpuArrays.如果结果以gpuArray然后客户端将与其中一个工作人员共享GPU,这将不必要地使用设备上的更多内存,并通过PCI总线传输数据。

Multi-GPU执行细节

当使用多个GPU时,推荐的MATLAB设置是,正如我们上面讨论的,为每个GPU打开一个worker。让我们进一步深入了解工作人员如何与gpu交互的细节。

当工作人员使用多个GPU共享一台机器时,MATLAB会自动分配并行池中的每个工作人员使用不同的GPU。可以通过使用spmd命令检查每个worker使用的设备的索引来看到这一点。

spmdgd = gpuDevice;idx = gd.Index;disp ([使用GPU的num2str (idx)]);结束
实验1:使用GPU 1

NVIDIA gpu支持四种计算模式:默认、独占线程、独占进程和禁止。计算模式显示在gpuDevice返回的结构的“ComputeMode”字段中。如果GPU处于禁用模式,则没有worker被分配使用该GPU。如果一个GPU处于独占进程或独占线程模式,只有一个MATLAB worker会尝试访问该GPU。

如果GPU处于“默认”计算模式,多个工作人员可以共享同一个GPU。当这完成时,GPU驱动程序序列化访问设备。您应该注意到,由于序列化,性能会受到影响。GPU上每个worker可用的内存也会更少,因为两个或更多的worker将共享相同的GPU内存空间。一般来说,当多个工作人员共享同一个GPU时,很难实现良好的性能。

通过重写MATLAB函数,您可以自定义MATLAB将工作人员分配到gpu的方式,以满足您自己的需求selectGPU.参见帮助selectGPU为更多的细节。

MATLAB初始化每个worker,默认情况下在GPU上使用不同的随机数字流。这样做可以确保每个worker获得的值是不同的。在这个例子中,为了简单起见,我们选择使用GPU上的默认随机数生成流,即众所周知的MRG32K3A流。虽然MRG32K3A是一种高度重视的算法,对并行性有很好的支持,但您可以选择其他流,它们可能提供更好的性能。万博1manbetx文档页面Using GPUArray描述了在GPU上控制随机数生成的可用选项,并列出了您可以选择的不同流。

在集群中使用多个gpu

有了所有这些细节,是时候考虑如何在需要数亿甚至数十亿次模拟时使用多个gpu了。例如,当我们需要不同的关键参数(如波动性或股息)值时,可能会出现这种情况。

让我们假设我们想要运行8亿个模拟,并且我们有一个具有16个NVIDIA C2050 gpu可用的集群。问题在于单个GPU的内存是有限的。一个NVIDIA C2050计算卡大约有3gb的内存,可以计算$5乘以10^7的点数runSimulationOnOneGPU不会耗尽内存。我们可以称之为runSimulationOnOneGPU16次来完成所有期望的模拟。在一台机器上,这样做大约需要10分钟。

我们测量了运行所有$8\乘以10^8$模拟所需的时间,最多16个gpu。如你所见,我们在这个实验中得到了近乎完美的线性缩放。

您的应用程序中使用了多少gpu,它们是如何交互的?让我知道在评论




发布与MATLAB®R2013a

|
  • 打印
  • 发送电子邮件

评论

要留下评论,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。