执行某些数组操作的代码存在问题。它太慢了,因为我使用循环和输入数据都很大。对我来说这是最简单的方法,但现在我正在寻找比循环更快的东西。我试图优化或重写代码,但不成功。我真的很帮助你。
在我的代码中,我有三个数组x1
,y1
(网格中的点坐标),g1
(点中的值),例如它们的大小为300 x 300。我将每个矩阵视为9的组合,并计算中间点的点数。例如,我从g1(101,101)
开始,但我使用的是来自g1(1:201,1:201)=g2
的数据。我需要计算从g1(1:201,1:201)
到g1(101,101)
(ll
矩阵)的每个点的距离,然后我在代码中计算nn,然后我找到g1(101,101)
的值来自nn并将其放入N
数组中。然后我转到g1(101,102)
,依此类推,直到g1(200,200)
,最后一个案例g2=g1(99:300,99:300)
。
正如我所说,这段代码效率不高,即使我必须使用比我在示例中给出的更大的数组,也需要花费太多时间。我希望我能够清楚地解释我对代码的期望。我正在考虑使用arrayfun,但我从未使用过这个函数,因此我不知道应该如何使用它,但在我看来它无法处理。也许有其他解决方案,但我找不到合适的东西。
tic
x1=randn(300,300);
y1=randn(300,300);
g1=randn(300,300);
m=size(g1,1);
n=size(g1,2);
w=1/3*m;
k=1/3*n;
N=zeros(w,k);
for i=w+1:2*w
for j=k+1:2*k
x=x1(i,j);
y=y1(i,j);
x2=y1(i-k:i+k,j-w:j+w);
y2=y1(i-k:i+k,j-w:j+w);
g2=g1(i-k:i+k,j-w:j+w);
ll=1./sqrt((x2-x).^2+(y2-y).^2);
ll(isinf(ll))=0;
nn=ifft2(fft2(g2).*fft2(ll));
N(i-w,j-k)=nn(w+1,k+1);
end
end
czas=toc;
答案 0 :(得分:2)
对于它的价值,arrayfun()
只是for循环的包装器,因此它不会导致任何性能改进。此外,您可能在x2
的定义中有拼写错误,我假设它取决于x1
。否则它将是一个多余的变量。此外,您的i<->w/k
,j<->k/w
配对似乎不一致,您也应该检查一下。 另外,只是tic/toc
的时间安排很难准确。分析代码时,将其放在函数中并多次运行定时,并从时序中排除变量生成。更好的是:使用内置的分析器。
免责声明:由于内存需求巨大,此解决方案可能对您的实际问题无济于事。对于300x300矩阵的输入,这适用于尺寸为300x300x100x100的阵列,这通常是不合适的。不过,它在这里以较小的输入尺寸进行参考。我想添加一个基于nlfilter()的解决方案,但是你的问题似乎太复杂了,无法使用它。
与矢量化一样,如果你可以为它节省内存,你可以更快地完成它。您正在尝试使用每个[2*k+1,2*w+1]
索引的大小为[i,j]
的矩阵。这需要形状[2*k+1,2*w+1,w,k]
的4d数组。对于每个元素[i,j]
,您都有一个索引为[:,:,i,j]
的矩阵,以便与x1
和y1
的相应元素一起处理。它还有助于fft2
接受多维数组。
这就是我的意思:
tic
x1 = randn(30,30); %// smaller input for tractability
y1 = randn(30,30);
g1 = randn(30,30);
m = size(g1,1);
n = size(g1,2);
w = 1/3*m;
k = 1/3*n;
%// these will be indexed on the fly:
%//x = x1(w+1:2*w,k+1:2*k); %// size [w,k]
%//y = x1(w+1:2*w,k+1:2*k); %// size [w,k]
x2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
y2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
g2 = zeros(2*k+1,2*w+1,w,k); %// size [2*k+1,2*w+1,w,k]
%// manual definition for now, maybe could be done smarter:
for ii=w+1:2*w %// don't use i and j as variables
for jj=k+1:2*k %// don't use i and j as variables
x2(:,:,ii-w,jj-k) = x1(ii-k:ii+k,jj-w:jj+w); %// check w vs k here
y2(:,:,ii-w,jj-k) = y1(ii-k:ii+k,jj-w:jj+w); %// check w vs k here
g2(:,:,ii-w,jj-k) = g1(ii-k:ii+k,jj-w:jj+w); %// check w vs k here
end
end
%// use bsxfun to operate on [2*k+1,2*w+1,w,k] vs [w,k]-sized arrays
%// need to introduce leading singletons with permute() in the latter
%// in order to have shape [1,1,w,k] compatible with the first array
ll = 1./sqrt(bsxfun(@minus,x2,permute(x1(w+1:2*w,k+1:2*k),[3,4,1,2])).^2 ...
+ bsxfun(@minus,y2,permute(y1(w+1:2*w,k+1:2*k),[3,4,1,2])).^2);
ll(isinf(ll)) = 0;
%// compute fft2, operating on [2*k+1,2*w+1,w,k]
%// will return fft2 for each index in the [w,k] subspace
nn = ifft2(fft2(g2).*fft2(ll));
%// we need nn(w+1,k+1,:,:) which is exactly of size [w,k] as needed
N = reshape(nn(w+1,k+1,:,:),[w,k]); %// quicker than squeeze()
N = real(N); %// this solution leaves an imaginary part of around 1e-12
czas=toc;