【发布时间】:2014-03-15 08:52:29
【问题描述】:
我是 Matlab 的新手,我需要帮助来加快我的某些部分代码的速度。我正在编写一个执行 3D 矩阵卷积的 Matlab 应用程序,但与标准卷积不同,内核不是恒定的,需要针对图像的每个像素进行计算。
到目前为止,我已经完成了一个工作代码,但速度非常慢:
function result = calculateFilteredImages(images, T)
% images - matrix [480,360,10] of 10 grayscale images of height=480 and width=360
% reprezented as a value in a range [0..1]
% i.e. images(10,20,5) = 0.1231;
% T - some matrix [480,360,10, 3,3] of double values, calculated earlier
kerN = 5; %kernel size
mid=floor(kerN/2); %half the kernel size
offset=mid+1; %kernel offset
[h,w,n] = size(images);
%add padding so as not to get IndexOutOfBoundsEx during summation:
%[i.e. changes [1 2 3...10] to [0 0 1 2 ... 10 0 0]]
images = padarray(images,[mid, mid, mid]);
result(h,w,n)=0; %preallocate, faster than zeros(h,w,n)
kernel(kerN,kerN,kerN)=0; %preallocate
% the three parameters below are not important in this problem
% (are used to calculate sigma in x,y,z direction inside the loop)
sigMin=0.5;
sigMax=3;
d = 3;
for a=1:n;
tic;
for b=1:w;
for c=1:h;
M(:,:)=T(c,b,a,:,:); % M is now a 3x3 matrix
[R D] = eig(M); %get eigenvectors and eigenvalues - R and D are now 3x3 matrices
% eigenvalues
l1 = D(1,1);
l2 = D(2,2);
l3 = D(3,3);
sig1=sig( l1 , sigMin, sigMax, d);
sig2=sig( l2 , sigMin, sigMax, d);
sig3=sig( l3 , sigMin, sigMax, d);
% calculate kernel
for i=-mid:mid
for j=-mid:mid
for k=-mid:mid
x_new = [i,j,k] * R; %calculate new [i,j,k]
kernel(offset+i, offset+j, offset+k) = exp(- (((x_new(1))^2 )/(sig1^2) + ((x_new(2))^2)/(sig2^2) + ((x_new(3))^2)/(sig3^2)) /2);
end
end
end
% normalize
kernel=kernel/sum(kernel(:));
%perform summation
xm_sum=0;
for i=-mid:mid
for j=-mid:mid
for k=-mid:mid
xm_sum = xm_sum + kernel(offset+i, offset+j, offset+k) * images(c+mid+i, b+mid+j, a+mid+k);
end
end
end
result(c,b,a)=xm_sum;
end
end
toc;
end
end
我尝试用
替换“计算内核”部分sigma=[sig1 sig2 sig3]
[x,y,z] = ndgrid(-mid:mid,-mid:mid,-mid:mid);
k2 = arrayfun(@(x, y, z) exp(-(norm([x,y,z]*R./sigma)^2)/2), x,y,z);
但事实证明它比循环还要慢。我浏览了几篇关于矢量化的文章和教程,但我对这一篇非常坚持。 它可以被矢量化或以某种方式使用其他东西加速吗? 我是 Matlab 的新手,也许有一些内置函数可以在这种情况下提供帮助?
更新 分析结果:
分析期间使用的示例数据:
T.mat
grayImages.mat
【问题讨论】:
-
如果
arrayfun等矢量化函数不起作用,您可能需要考虑编写 MEX 文件。 -
除了一些罕见的例外,
arrayfun没有矢量化。这是一个迭代过程。 Arrayfun 通常比相应的循环慢:stackoverflow.com/questions/12522888/… -
@user3299285:请给出一些示例输入数据。
T是什么,images是什么?图像是一堆灰度图像?ker未定义。 -
@Daniel 你说得对,我读过那篇文章。我在代码中添加了一些新的 cmets 来解释什么是图像和 T,T 通常代表图像中每个像素的 3x3 矩阵。对不起
ker,应该是kernel,我也修好了... -
这是相当多的代码,你能分享分析器的结果,以便我们至少可以确认哪些行是慢的吗?之后,为那段代码提供一些示例输入,这样情况就可以重现了。
标签: performance matlab profiling vectorization nested-loops