Fabio
Fabio

Reputation: 61

MATLAB code requires too much time for compiling

I am trying to compute this

formula

in MATLAB but the code requires about 8 hours to compile. In particular e, Ft=[h(t);q(t)] and Omega are 2x1 matrices (e' is 1x2), Gamma is a 2x2 matrix and n=30. Can someone help me to optimize this code?

I tried in this way:

aux=[0;0];
for k=0:29 
  for j=1:k-1   
    aux=[aux Gamma^j*Omega];
  end
  E(t,k+1)= e'*(sum(aux,2)+Gamma^k*[h(t);q(t)]);
end
Vix=1/30*sum(E,2);

EDIT

now I changed into this and it is faster, but I am not sure that I am applying correctly the formula in the picture...

for t=2:T
        % 1. compute today's volatility 
        csi(t) = log(SP500(t)/SP500(t-1))-r(t)+0.5*h(t);
        q(t+1) = omega+rho*q(t)+phi*((csi(t)-lambda*sqrt(h(t)))^2-h(t));
        h(t+1) = q(t)+alpha*((csi(t)-lambda*sqrt(h(t)))^2-q(t))+beta*(h(t)-q(t));
         for k=1:30
 aux=zeros(2,k);
              for j=0:k-1
            aux(:,j+1)=Gamma^j*Omega;
              end
        E(t,k)= e'*(sum(aux,2)+Gamma^k*[h(t);q(t)]);
         end
    end
Vix(2:end)=1/30*sum(E(2:end,:),2);

(I don't need Vix(1))

Upvotes: 0

Views: 134

Answers (1)

J.A. Ferrand
J.A. Ferrand

Reputation: 218

Here are some reasons I can think of:

REPEATED COPYING(No preallocation) The main reason for the long run time is the line aux=[aux Gamma^j*Omega] line, in which an array is concatenated at every loop iteration. MATLAB's debugger should have flagged this for you in its editor and should have cited that "memory preallocation" using zeros should be implemented.

Essentially, when one concatenates arrays this way, MATLAB is internally making copies of the array at every loop iteration, thus, in addition to the math operations copying is taking place. As the array grows, the copying operations become ever more expensive. This is avoided by preallocation, which consists of predefining the size of the storage array (in this case the variable aux) so that MATLAB doesn't have to keep on allocating space on the go. Try:

aux = zeros(2, 406); %Creates a 2 by 406 array. I explain how I get 406 below:
p = 0; %A variable that indexes the columns of aux
for k=0:29 
  for j=1:k-1
    p = p+1; %Update column counter
    aux(:,p) = Gamma^j*Omega; % A 2x2 matrix multiplied by a 2x1 matrix yields a 2x1.
  end
  E(t,k+1)= e'*(sum(aux,2)+Gamma^k*[h(t);q(t)]);
end
Vix=1/30*sum(E,2);

Now, MATLAB simply overwrites the individual elements of aux instead of copying aux, and concatenating it with Gamma^j*Omega, and then overwriting aux. Essentially, the above makes MATLAB allocate space for aux ONCE instead of 406 times. I figured out that aux ends up being a 2 by 406 array for the n=30 case in the end by running this code:

p = 0;
for k = 0:29
    for j = 1:k-1
        p = p + 1;
    end
end

To know the final size of aux for other values of n you should see if a formula for it is available (or derive your own).

LOOPING TRANSPOSITION OF A CONSTANT? Next, e'. As you may know, ' is the transpose operation. From your sample code, the variable e is not edited inside the for loops, yet you have the ' operator inside the outer for loop. If you perform the transpose operation once outside the outer for loop you save yourself the expense of transposing it at every loop iteration.

RUNNING TOTAL As a final note, I would suggest replacing sum(aux,2) with a variable that keeps a running total. This is because currently, this makes MATLAB sum over the entirety of aux at every loop iteration.

Hope this helps mate.

Upvotes: 1

Related Questions