矢量化这个循环

时间:2015-10-30 18:39:50

标签: matlab recursion vectorization

我在MATLAB中有以下循环:

n = 20000
rho=0.9;
sigma=[0.1 0.2 0.3];
epsilon = normrnd(0,1, 3, n);
z =  NaN(1,n);
z(1,1) = 0;
for i=2:n
   z(1,i) = rho * z(1,i-1) + sigma* epsilon(:,i);
end

我尝试通过以下方式对其进行矢量化:

z(1,2:end) = rho * z(1,1:end-1) + sigma * epsilon

它不起作用。我明白问题是这一点:z(1,2:end) = rho * z(1,1:end-1)不是递归的。

我该如何解决这个问题?

3 个答案:

答案 0 :(得分:6)

在充满 crazy fast parallel processors and almost-free memory latency machines 的后世界末日世界中,bsxfunmatrix multiplication等矢量化工具很容易在20,000个核心中产生,其中一个丢失拼命拼命试图对这样的问题进行矢量化可能冒险进入这样的事情 -

parte1 = tril(rho.^(bsxfun(@minus,(0:n-2)',0:n-2)));
parte2 = sigma*epsilon(:,2:end);
z = [0 parte2*parte1.']

严肃地说,它不应该是记忆效率的,因此,不可能很快...... 现在,但是要展示一种方法跟踪递归并将其应用于矢量化解决方案。

答案 1 :(得分:4)

部分矢量化代码会将您的示例表单的执行时间降低0.015秒到0.0005秒。我只是使用单个矩阵乘法预先计算sigma* epsilon(:,i)

n = 20000
rho=0.9;
sigma=[0.1 0.2 0.3];
epsilon = normrnd(0,1, 3, n);
se=sigma*epsilon;
z =  NaN(1,n);
z(1,1) = 0;
for i=2:n
   z(1,i) = rho * z(1,i-1) + se(i);
end

答案 2 :(得分:1)

除非以不使用递归的方式重写此特定程序,否则无法对其进行矢量化。

很难进行涉及递归的矢量化计算,因为大多数时候你不能为你试图解决的函数设置一个闭合的表达式(有效地在任何给定的时间点你没有有限数量的操作;并且即使你确实有一个有限的数字会以指数方式增长。)

我想你可能想考虑使用filter重写你的功能。它专门为这种关系而设计。

编辑:

如上所述,您描述的是基本过滤器。假设设置与@Daniel相同,您只需:

...
epsilon = normrnd(0,1, 3, n);
se=sigma*epsilon;

a = [1 -rho];
b = 1; 
z = filter(b, a, [0  se(2:n)] );

我相信你会一直认为这是三个解决方案中提出的更快的解决方案。对我来说,它似乎也是最自然的,因为你的问题陈述描述了一种过滤算法。