MATLAB代码需要太多的编译时间

MATLAB代码需要太多的编译时间,matlab,optimization,Matlab,Optimization,我正在计算这个 但是代码需要大约8小时来编译。尤其是e,Ft=[h(t);q(t)]和Omega是2x1矩阵(e'是1x2),Gamma是2x2矩阵,n=30。有人能帮我优化这个代码吗 我试着这样做: 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);

我正在计算这个

但是代码需要大约8小时来编译。尤其是
e
Ft=[h(t);q(t)]
Omega
是2x1矩阵(
e'
是1x2),
Gamma
是2x2矩阵,
n=30
。有人能帮我优化这个代码吗

我试着这样做:

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);
编辑

现在我换成这个,速度更快,但我不确定我是否正确应用了图片中的公式

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);

(我不需要Vix(1))

以下是我可以想到的一些原因:

重复复制(无预分配)长时间运行的主要原因是行
aux=[aux Gamma^j*Omega]
行,在该行中,
数组
在每次循环迭代中串联。MATLAB的调试器应该在其编辑器中为您标记这一点,并且应该使用
零实现“memorypreallocation

本质上,当一个人以这种方式连接数组时,MATLAB在每次循环迭代时都会在内部复制数组,因此,除了数学运算外,还会进行复制。随着阵列的增长,复制操作变得越来越昂贵。这可以通过预分配来避免,预分配包括预定义存储阵列的大小(在本例中为变量
aux
),这样MATLAB就不必在运行中不断分配空间。尝试:

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);
现在,MATLAB只是覆盖
aux
的各个元素,而不是复制
aux
,并将其与
Gamma^j*Omega
连接,然后覆盖
aux
。从本质上讲,上述情况使MATLAB将空间分配给
aux
一次,而不是406次。通过运行以下代码,我发现
aux
最终是
n=30
情况下的一个2×406数组:

p = 0;
for k = 0:29
    for j = 1:k-1
        p = p + 1;
    end
end
要知道其他
n
值的
aux
的最终大小,您应该查看是否有可用的公式(或推导您自己的公式)

常数的循环换位? 接下来,
e'
。您可能知道,
是转置操作。从示例代码中,变量
e
未在
for
循环中编辑,但在
for
循环的外部
中有
'
运算符。如果在外部
for
循环之外执行一次转置操作,可以节省每次循环迭代转置的费用

运行总数 最后,我建议将
sum(aux,2)
替换为一个保持运行总数的变量。这是因为目前,这使得MATLAB在每次循环迭代时对整个
aux
求和


希望这对mate有所帮助。

以下是我能想到的一些原因:

重复复制(无预分配)长时间运行的主要原因是行
aux=[aux Gamma^j*Omega]
行,在该行中,
数组
在每次循环迭代中串联。MATLAB的调试器应该在其编辑器中为您标记这一点,并且应该使用
零实现“memorypreallocation

本质上,当一个人以这种方式连接数组时,MATLAB在每次循环迭代时都会在内部复制数组,因此,除了数学运算外,还会进行复制。随着阵列的增长,复制操作变得越来越昂贵。这可以通过预分配来避免,预分配包括预定义存储阵列的大小(在本例中为变量
aux
),这样MATLAB就不必在运行中不断分配空间。尝试:

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);
现在,MATLAB只是覆盖
aux
的各个元素,而不是复制
aux
,并将其与
Gamma^j*Omega
连接,然后覆盖
aux
。从本质上讲,上述情况使MATLAB将空间分配给
aux
一次,而不是406次。通过运行以下代码,我发现
aux
最终是
n=30
情况下的一个2×406数组:

p = 0;
for k = 0:29
    for j = 1:k-1
        p = p + 1;
    end
end
要知道其他
n
值的
aux
的最终大小,您应该查看是否有可用的公式(或推导您自己的公式)

常数的循环换位? 接下来,
e'
。您可能知道,
是转置操作。从示例代码中,变量
e
未在
for
循环中编辑,但在
for
循环的外部
中有
'
运算符。如果在外部
for
循环之外执行一次转置操作,可以节省每次循环迭代转置的费用

运行总数 最后,我建议将
sum(aux,2)
替换为一个保持运行总数的变量。这是因为目前,这使得MATLAB在每次循环迭代时对整个
aux
求和


希望这对mate有所帮助。

“编译”是指将代码翻译成机器指令。这需要几分之一秒的时间。运行代码需要8个小时。如果需要帮助,您必须包含完整的代码(请参阅)。您确定要将
k
的每次迭代添加到
aux
?在我看来,这并不正确,因为您在该循环中使用了
sum(aux)
。我也不明白,如果你要做的只是取它的和,为什么要构建数组
aux
。为什么不直接添加这些值呢
aux=aux+Gamma^j*ω
?另外,您确定Gamma ^j是您当前计算的矩阵幂吗?我认为这是不可能的,符号的意思是不同的。并且在代码中也跳过了j=0