2017-02-06 38 views
-4

我有下面的代码需要计算3D矩阵的指数。它工作正常,但我不知道是否有反正使它更快。 (目前需要2秒以上,如果可能,我试图让它在半秒内运行)。在Matlab中更快的指数计算

Result = zeros(200,50,300); 
for i=1:30 
    delta = i*randn(200,50,300); 
    X = exp(1i*2*pi*delta); 
    Result = Result + X; 
end 

任何帮助,将不胜感激。 在此先感谢。

+2

你是否介绍了该代码?在那种情况下,'exp'与其他行相比有多少时间?也许问题不在'exp'中。 – mpaskov

+2

我怀疑这将是更快的矢量化。内存消耗本身就会很大。对于涉及大内存的计算,'for'循环更好。 – rayryeng

+1

在你的代码中,'i'与'1i'不一样。我希望你已经知道了! –

回答

1

首先,我不认为这个计算顺序可以做得更快。下面可能是一个很小的有点快,但肯定不是由量你正在寻找:

dim = [200,50,300]; % given 
N  = prod(dim); % total number of samples 
M  = 30;   % number of iterations in for-loop 
phase = bsxfun(@times, randn(N,M), [1:M]); % scaled phases 
Result = reshape(sum(exp(1i*2*pi*phase),2), dim); % sum of exp and reshape 

编辑1开始:

正如@horchler在下面的评论中指出,这种方法实际上比R2016b上的原始方法慢。他还建议使用更快的随机生成方案,我尝试并观察到显着的改进。通过消除一些临时变量也可以获得类似的改进。

s = RandStream('dsfmt19937','Seed',1); 
for i=1:30 
    Result = Result + exp(1i*2*pi*i*randn(s,200,50,300)); 
end 

我对优化的各个阶段,在R2016b的时序结果,如下:

  • 原始代码:4.3小号
  • 我原来的建议:4.5小号
  • 原始代码更简单随机数生成:3.8 s
  • 上面的临时变量删除:3.2 s

也可以尝试其他随机数生成方案,例如shr3cong以努力加速进一步加速。

编辑1:结束

一种不同的方法: 让我提出一个不同的方法,会产生不同的方式所需要的输出,但是这样它会具有相同的统计特性 为你的输出。

Result = sqrt(15) * (randn(200,50,300) + 1i*randn(200,50,300)); 

现在我们试着证明这一点。首先,我们可以认为,由于输出是30个随机过程的和,所以通过中心极限定理(CLT),输出将是高斯分布的。 CLT只适用于这里的松散意义,因为30并不是无限的,并且过程不是完全分布的。但正如我们很快会看到的那样,它仍然是一个非常好的近似值。此外,实数和虚数项也是独立的,由于总和超过30个独立的复数。我不打算在这里证明这一点,但我们会做一些统计检查。

一旦我们确定了独立的高斯分布,分析变得更加简单。高斯分布可以由两个参数定义:均值和方差。让我们估计其个人:

平均:由于相位随机分布并覆盖比2*pi更大的区域,对于实部和虚方面的手段是0。

方差:大随机相位分布的正弦/余弦方差为0.5。所以30个正弦/余弦之和的方差应为15.这就是公式中sqrt(15)项的原因。

统计分析: 要验证所有上述假设和近似值是否合理,我们进行一些统计分析。

首先,让我们检查分布:

figure; 
xGrid = (-15 : 0.1 : 15); 
histogram(real(Result(:)), xGrid, 'Normalization','pdf', 'EdgeColor', 'None'); 
hold on; 
plot(xGrid, normpdf(xGrid, 0, sqrt(15)), 'r', 'LineWidth', 2); 
legend({'Simulated histogram', 'Gaussian pdf'}); 
title('Distribution of the real term'); 

enter image description here

虚数项(这里没有显示)的直方图看起来也相同。该测试验证具有零均值和15个方差的高斯分布的假设。

最后,让我们检查一下真实和虚拟术语之间的独立性。

covar = cov(real(Result(:)), imag(Result(:))); 
disp(covar); 
% 14.9968 0.0036 
% 0.0036 14.9936  

两件事情可以注意到:(1)如前所述,每个的实数和虚数项的方差为约15。(2)相比,该实数和虚数项之间的协方差是小得多个体差异。这支持了他们独立的论点。

+1

+1有趣的答案。在R2016b中,摆脱'for'循环的第一种方法比较慢了20%左右。矢量化并不总是赢。 – horchler

+0

也可考虑使用不同的[基数随机数生成方案](https://www.mathworks.com/help/matlab/ref/randstream.list.html),以获得更快的速度,例如''dsfmt19937''或' 'shr3cong'':'s = RandStream('dsfmt19937','Seed',1);''randn(s,200,50,300)'。 – horchler

+0

@horchler:我已将您的建议纳入我的答案。谢谢! – aksadv