Vectorize this loop

删除回忆录丶 提交于 2019-12-10 23:10:00

问题


I have the following loop in 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

I tried vectorizing it by doing:

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

It didn't work. I understand that the problem is that this bit: z(1,2:end) = rho * z(1,1:end-1) is not recursive.

How can I solve this?


回答1:


In a post apocalyptic world filled with crazy fast parallel processors and almost-free memory latency machines, where vectorizing tools like bsxfun and matrix multiplication could easily spawn across 20,000 cores, one lost soul desperately trying to vectorize such a problem could venture into something like this -

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

In all seriousness, it's not supposed to be memory-efficient and thus, isn't likely to be fast .. now, but is meant to demonstrate a way to trace the recursion and apply it for a vectorized solution.




回答2:


Partially vectorizing the code lowered the execution time for your example form 0.015s to 0.0005s on my system. I simply pre-calculated sigma* epsilon(:,i) using a single matrix multiplication:

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



回答3:


Unless you re-write this particular program in a way that does not use recursion you cannot vectorize it.

It is very hard to have vectorized calculations involving recursion because most of the time you cannot have a closed form expression for the function you try to solve (effectively at any given time-point you do not a finite number of operations; and even if you do have a finite number that will grow exponentially).

I think you might want to consider re-writing your function using filter. It is specifically designed for such relations.

EDIT:

As mentioned, what you describe is an elementary filter. Assuming the same setting as @Daniel you simply have:

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

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

I believe that you will consistently find this to be the faster of the three solutions proposed. To me it also appears to be the most natural as your problem statement describes a filtering algorithm.



来源:https://stackoverflow.com/questions/33442840/vectorize-this-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!