为什么脚本的这两个实例执行不同?



我有2个实例的算法,我正在实现,我希望它是尽可能快,因为它将是一个例行公事的一部分,我需要重复很多次。

思路如下:我有一个n × n × m矩阵(称为c),基于它,我必须创建一个m × n矩阵(称为z)。z的每一行都是前一行乘以对应的n,再乘以cn切片,并进行归一化的结果。

我有这样的想法,在matlab中,如果可能的话,最好对代码进行矢量化并避免循环,所以我认为第一种方法是我能想到的最快的方法。但事实证明,第二种实现大约快了15%。有人能解释一下吗?另外,你能告诉我,我是否能做得比第二种选择更好吗?

以下是两个脚本的虚拟版本(为了说明目的足够接近)

脚本1

clear all
x = -5:.02:5;
w = 1:.02:11;
t(1,1,:) = w;
n = length(x);
m = length(w);

z      = zeros(m,n);
z(1,:) = exp(-x.^2/2)/sqrt(2*pi);    
a = bsxfun(@times,x,t);
b = bsxfun(@minus,a,x');
c = exp(-bsxfun(@rdivide,b.^2,2*t));
for i = 2:m
    z(i,:) = z(i-1,:)*squeeze(c(:,:,i));
    z(i,:) = z(i,:)/trapz(x,z(i,:));
end
脚本2

clear all
x = -5:.02:5;
t = 1:.02:11;
n = length(x);
m = length(t);

z      = zeros(m,n);
z(1,:) = exp(-x.^2/2)/sqrt(2*pi);
for i=2:m
    c = exp(-(bsxfun(@minus,x*t(i),x')).^2/(2*t(i)));
    z(i,:) = z(i-1,:)*c;
    z(i,:) = z(i,:)/trapz(x,z(i,:));
end

我没想到脚本1中的这行

z(i,:) = z(i-1,:)*squeeze(c(:,:,i));

对ndim数组进行迭代索引可能会非常昂贵。因此,我们可以使用scratchpad变量来避免这种情况。因此,我们可以这样修改script #2:

z      = zeros(m,n);
tmp    = exp(-x.^2/2)/sqrt(2*pi);
z(1,:) = tmp;
for i=2:m
    tmp = tmp*exp(-(bsxfun(@minus,x*t(i),x')).^2/(2*t(i)));
    tmp = tmp/trapz(x,tmp);
    z(i,:) = tmp;
end

tmp变量就是这里使用的临时变量。此外,我们将之前存储为cbsxfun(@minus结果直接输入到下一步。

运行测试-

输入:

x = -5:.04:5;
t = 1:.04:11;

时间:

--------------------- With Script #2
Elapsed time is 0.571562 seconds.
--------------------- With Optimized Script
Elapsed time is 0.478028 seconds.

这里有一些细微的改进

相关内容

  • 没有找到相关文章