我有2个实例的算法,我正在实现,我希望它是尽可能快,因为它将是一个例行公事的一部分,我需要重复很多次。
思路如下:我有一个n
× n
× m
矩阵(称为c
),基于它,我必须创建一个m
× n
矩阵(称为z
)。z
的每一行都是前一行乘以对应的n
,再乘以c
的n
切片,并进行归一化的结果。
我有这样的想法,在matlab中,如果可能的话,最好对代码进行矢量化并避免循环,所以我认为第一种方法是我能想到的最快的方法。但事实证明,第二种实现大约快了15%。有人能解释一下吗?另外,你能告诉我,我是否能做得比第二种选择更好吗?
以下是两个脚本的虚拟版本(为了说明目的足够接近)
脚本1clear 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
变量就是这里使用的临时变量。此外,我们将之前存储为c
的bsxfun(@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.
这里有一些细微的改进