如何在Matlab中矢量化'for'循环

时间:2014-02-11 23:02:31

标签: performance matlab vector vectorization

我正在编写一个计算某种矩阵的Matlab应用程序。我试图用基于矢量的计算替换程序中的for循环,但是,我被卡住了。

到目前为止,我已经想到了这个简单的代码部分代码:

kernel = zeros(5,5,5);
offset = 3;
sig=1;

for x=-2:2
    for y=-2:2
        for z=-2:2
            IN = x.^2/(sig^2) + y.^2/(sig^2) + z.^2/(sig^2); 
            kernel(offset+x, offset+y, offset+z) = exp(-IN/2);
        end
    end
end

可以用这样的结构代替:

[x,y,z] = ndgrid(-2:2,-2:2,-2:2);
IN = x.^2/(sig^2) + y.^2/(sig^2) + z.^2/(sig^2); 
kernel = exp(-IN/2);

并给出相同的结果。 但是,如果我需要进行一些小改动怎么办呢?

kernel = zeros(5,5,5);
offset = 3;   
sig=1;

%sample 3x3 matrix
R=magic(3)/10; 

for x=-2:2
    for y=-2:2
        for z=-2:2

            % calculation of new x, y, z
            point = [x,y,z]*R;   

            IN = (point(1)^2 )/(sig^2) + (point(2)^2)/(sig^2) + (point(3)^2)/(sig^2);
            kernel(offset+x, offset+y, offset+z) = exp(-IN/2);
        end
    end
end

如何加快这种结构?可以轻松地进行矢量化吗?我对Matlab很新,所以我很感激任何帮助。非常感谢!

1 个答案:

答案 0 :(得分:3)

一种选择是使用arrayfun

sig=1;

%sample 3x3 matrix
R=magic(3)/10;

[x,y,z] = ndgrid(-2:2,-2:2,-2:2);
kernel = arrayfun(@(x, y, z) exp(-(norm([x,y,z]*R/sig)^2)/2), x,y,z);

说明:

arrayfun采用一个函数作用于标量输入以产生标量输出,以及传递给函数的输入数组。然后它遍历输入数组,在每个数组上运行你的函数,并将每个输出放在输出矩阵(-es)中的相应条目中。所以arrayfun基本上是嵌套循环,这会减慢你的一切。

在这个例子中,我还使用anonymous function(也称为lambda函数)在最内层循环中完成工作。由于lambda函数需要在Matlab中是单个表达式,我不得不重写内部循环(使用简单的代数操作)。如果您需要将arrayfun与不易表示为lambda的函数一起使用,则可以始终在单独的.m文件中编写该函数并将其传递给arrayfun

编辑:请注意,您不必再预先分配kernel,也不需要offset