【问题标题】:Speeding up simulation of the Levy motion algorithm加速 Levy 运动算法的仿真
【发布时间】:2015-12-06 01:27:42
【问题描述】:

这是我模拟 Levy 运动的小脚本:

clear all;
clc; close all;
t = 0; T = 1000; I = T-t;
dT = T/I; t = 0:dT:T; tau = T/I;
alpha = 1.5;
sigma = dT^(1/alpha);
mu = 0; beta = 0;
N = 1000;
X = zeros(N, length(I));
for k=1:N
    L = zeros(1,I);
    for i = 1:I-1
       L( (i + 1) * tau ) = L(i*tau) + stable2( alpha, beta, sigma, mu, 1);
    end
    X(k,1:length(L)) = L;
end

q = 0.1:0.1:0.9;
quant = qlines2(X, q, t(1:length(X)), tau);
hold all
for i = 1:length(quant)
    plot( t, quant(i) * t.^(1/alpha), ':k' );
end

stable2 返回一个带有给定参数的stable random variable(在这种情况下,您可以用normrnd(mu, sigma) 替换它,这并不重要); qlines2 返回绘图所需的分位数。

但我不想在这里谈论数学。我的问题是这个实现很慢,我想加快速度。不幸的是,计算机科学不是我的主要领域——我听说过一些关于记忆化、矢量化等方法的知识,还有很多其他技术,但我不知道如何使用它们。
例如,我很确定我应该以某种方式替换这个肮脏的双 for 循环,但我不确定该怎么做。
编辑:也许我应该使用(并学习......)另一种语言(Python、C、任何功能性语言)?我一直认为 Matlab/OCTAVE 是为数值计算而设计的,但如果改变,那是哪一个?

【问题讨论】:

  • 脚本看起来并不太复杂,所以我大胆猜测您将通过优化的 Matlab 实现获得合理的性能。 Matlab 对新手也很宽容——除非最好的性能是绝对必要的,否则我觉得你现在应该坚持下去。特别是因为你现在已经在那里实现了你的模拟:)

标签: performance matlab optimization


【解决方案1】:

正如你所说,关键是for循环,Matlab不喜欢那些,所以 vectorization 确实是关键字。 (连同预分配空间。

我只是稍微改变了你的循环部分,这样你就不必一遍又一遍地重置L,而是将所有Ls 保存在一个更大的矩阵中(我也删除了length(L) 命令)。

L = zeros(N,I);
for k=1:N
    for i = 1:I-1
       L(k,(i + 1) * tau ) = L(k,i*tau) + normrnd(mu, sigma);
    end
    X(k,1:I) = L(k,1:I);
end

现在您已经可以看到循环中的X(k,1:I) = L(k,1:I); 已过时,这也意味着我们可以切换循环的顺序。这一点至关重要,因为i-steps 是递归的(取决于上一步),这意味着我们不能向量化这个循环,我们只能向量化k-loop。

现在你的原始代码在我的机器上需要 9.3 秒,新代码仍然需要大约相同的时间)

L = zeros(N,I);
for i = 1:I-1
    for k=1:N
       L(k,(i + 1) * tau ) = L(k,i*tau) + normrnd(mu, sigma);
    end
end
X = L;

但是现在我们可以应用矢量化,而不是循环遍历所有行(循环k),我们可以消除这个循环,并“一次”执行所有行。

L = zeros(N,I);
for i = 1:I-1
   L(:,(i + 1) * tau ) = L(:,i*tau) + normrnd(mu, sigma); %<- this is not yet what you want, see comment below
end
X = L;

这段代码在我的机器上只需要 0.045 秒。我希望你仍然得到相同的输出,因为我不知道你在计算什么,但我也希望你能看到你是如何进行矢量化代码的。

PS:我刚刚注意到我们现在在上一个示例中对整列使用相同的随机数,这显然不是您想要的。 Instad,您应该生成一个完整的随机数向量,例如:

L = zeros(N,I);
for i = 1:I-1
   L(:,(i + 1) * tau ) = L(:,i*tau) + normrnd(mu, sigma,N,1);
end
X = L;

PPS:好问题!

【讨论】:

  • 干得好。我相信对于模拟,有必要使用normrnd 而不是一个来绘制多个样本。这是通过语法normrnd(mu, sigma, M, N, ...) 实现的,其中MN 等是输出数组的所需维度。并且 usual caveats of using i or j as loop variables 申请。
  • @mikkola 谢谢你让我知道,我也注意到了这一点并添加了一段。
  • 效果很好,谢谢!是的,需要修正(你的 PS),因为我想要模拟路径矩阵。
  • @PhotonLight 还有一件事,这段代码现在只能工作,因为tau 正好是 1。
  • 是的,我明白了,这是另一个问题,但现在我可以假设它是真的 - 实际上它代表时间步长,对于简单的情况它可以是 1。我会和我的教授谈谈。如果可以解决,可能需要另一种实现,但现在我对优化有了更多了解,所以应该更容易!
猜你喜欢
  • 2010-12-27
  • 2019-09-09
  • 1970-01-01
  • 2018-06-26
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多