在 Matlab 中进行更快的指数计算
Faster exponential calculation in Matlab
我有以下代码需要计算 3D 矩阵的指数。它工作正常,但我想知道是否有办法让它更快。 (目前它需要超过 2 秒。如果可能的话,我正在努力使其 运行 低于半秒。)
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
如有任何帮助,我们将不胜感激。
提前致谢。
首先,我不认为这个计算序列可以做得更快。以下可能会快一点,但肯定不是您要找的数量:
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 秒
也可以尝试其他随机数生成方案,例如shr3cong
,以进一步加快速度。
编辑 1:结束
另一种方法:
让我建议一种不同的方法,以不同的方式生成所需的输出,但它具有相同的统计属性
作为你的输出。
Result = sqrt(15) * (randn(200,50,300) + 1i*randn(200,50,300));
现在让我们尝试证明这一点。首先,我们可以争辩说,由于输出是 30 个随机过程的总和,根据中心极限定理 (CLT),输出将是高斯分布的。 CLT 在这里只适用于宽泛的意义上,因为 30 不是无限的并且进程不是相同分布的。但正如我们很快就会看到的,它仍然是一个非常好的近似值。此外,由于 30 个独立复数的总和,实部和虚部也是独立的。我不打算在这里证明这一点,但我们会做一些统计检查。
一旦我们确定了独立的高斯分布,分析就会变得简单得多。高斯分布可以仅由两个参数定义:均值和方差。让我们分别估算一下:
均值: 由于相位是随机分布的并且覆盖的区域比 2*pi
大得多,因此实部和虚部的均值均为 0.
方差:大随机相位分布sine/cosine的方差为0.5。所以 30 sines/cosines 之和的方差将为 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');
虚项的直方图(此处未显示)看起来也相同。该测试验证了均值为零、方差为 15 的高斯分布假设。
最后,让我们检查实部和虚部之间的独立性。
covar = cov(real(Result(:)), imag(Result(:)));
disp(covar);
% 14.9968 0.0036
% 0.0036 14.9936
可以注意到两件事:(1)如前所述,实部和虚部的方差各约为15。(2)实部和虚部之间的协方差与个体方差相比要小得多.这支持了他们独立的论点。
我有以下代码需要计算 3D 矩阵的指数。它工作正常,但我想知道是否有办法让它更快。 (目前它需要超过 2 秒。如果可能的话,我正在努力使其 运行 低于半秒。)
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
如有任何帮助,我们将不胜感激。 提前致谢。
首先,我不认为这个计算序列可以做得更快。以下可能会快一点,但肯定不是您要找的数量:
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 秒
也可以尝试其他随机数生成方案,例如shr3cong
,以进一步加快速度。
编辑 1:结束
另一种方法: 让我建议一种不同的方法,以不同的方式生成所需的输出,但它具有相同的统计属性 作为你的输出。
Result = sqrt(15) * (randn(200,50,300) + 1i*randn(200,50,300));
现在让我们尝试证明这一点。首先,我们可以争辩说,由于输出是 30 个随机过程的总和,根据中心极限定理 (CLT),输出将是高斯分布的。 CLT 在这里只适用于宽泛的意义上,因为 30 不是无限的并且进程不是相同分布的。但正如我们很快就会看到的,它仍然是一个非常好的近似值。此外,由于 30 个独立复数的总和,实部和虚部也是独立的。我不打算在这里证明这一点,但我们会做一些统计检查。
一旦我们确定了独立的高斯分布,分析就会变得简单得多。高斯分布可以仅由两个参数定义:均值和方差。让我们分别估算一下:
均值: 由于相位是随机分布的并且覆盖的区域比 2*pi
大得多,因此实部和虚部的均值均为 0.
方差:大随机相位分布sine/cosine的方差为0.5。所以 30 sines/cosines 之和的方差将为 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');
虚项的直方图(此处未显示)看起来也相同。该测试验证了均值为零、方差为 15 的高斯分布假设。
最后,让我们检查实部和虚部之间的独立性。
covar = cov(real(Result(:)), imag(Result(:)));
disp(covar);
% 14.9968 0.0036
% 0.0036 14.9936
可以注意到两件事:(1)如前所述,实部和虚部的方差各约为15。(2)实部和虚部之间的协方差与个体方差相比要小得多.这支持了他们独立的论点。