提高MATLAB中分段函数的速度

时间:2015-06-08 18:19:28

标签: matlab optimization vectorization

我有一个小的分段函数,分析显示占用程序运行时的60%。它经常被调用,因为它在我的代码中执行了很多的积分中。

根据剖析,它被称为213560次,共计47.786秒,相当于每次通话约220微秒。

我想传递一个数组,它应该返回一个数组,操作元素。

我知道在Matlab中使用循环非常慢并且应该避免,但我不确定如何将这种函数矢量化。

function bottleradius = aux_bottle_radius(z_array)
%AUXBOTTLERADIUS Radius of aux bottle
%   This returns the radius of the aux bottle as a function of z. It works for all
%   heights of aux bottle, just remember to integrate over the right height
%   range
    bottleradius = zeros(size(z_array));
    for i = 1 : max(size(z_array))
        if z_array(i)<-30e-3
            %door cavity
            bottleradius(i) = 34e-3;
        elseif z_array(i)>=-30e-3 && z_array(i)<-20e-3
            %radiussing door cavity
            bottleradius(i) = 34e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(i)+30e-3).^2);
        elseif z_array(i)>=-20e-3 && z_array(i)<-10e-3
            %aluminium plate
            bottleradius(i) = 46e-3;
        elseif z_array(i)>=-10e-3 && z_array(i)<0e-3
            %radiussing aluminium plate to main bottle
            bottleradius(i) = 46e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(i)+10e-3).^2);
        elseif z_array(i)>=0e-3
            %top of Al plate, bottom of main bottle
            bottleradius(i) = 185e-3;
        else
            bottleradius(i) = 0;
        end
    end
end

1 个答案:

答案 0 :(得分:4)

您可以使用logical运算符完全向量化。您基本上可以用以下代码替换该代码:

function bottleradius = aux_bottle_radius(z_array)

%// Declare initial output array of all zeroes
bottleradius = zeros(size(z_array));

%// Condition #1 - Check for all values < -30e-3 and set accordingly
bottleradius(z_array < -30e-3) = 34e-3;

%// Condition #2 - Check for all values >= -30e-3 and < -20e-3 and set accordingly
ind = z_array >= -30e-3 & z_array < -20e-3;
bottleradius(ind) = 34e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(ind)+30e-3).^2);

%// Condition #3 - Check for all values >= -20e-3 and < -10e-3 and set accordingly
bottleradius(z_array >=-20e-3 & z_array < -10e-3) = 46e-3;

%// Condition #4 - Check for all values >= -10e-3 and < 0 and set accordingly
ind = z_array >=-10e-3 & z_array < 0;
bottleradius(ind) = 46e-3 + 10e-3 - sqrt((10e-3).^2 - (z_array(ind)+10e-3).^2);

%// Condition #5 - Check for all values >= 0 and set accordingly
bottleradius(z_array >= 0) = 185e-3;
end

次要评论

  1. 0e-3没有任何明智的意义。这与0基本相同,我在您的代码中对其进行了更改。
  2. 请注意,对于条件#2和#4,我预先计算了一个logical数组,该数组指示我们需要访问z_array中相应值的位置,以便更轻松地设置bottleradius中的相同位置{1}}是所需的计算输出。我不会为其他条件执行此操作,因为您只是将它们设置为单个常量。
  3. 值得庆幸的是,您在条件#2和#4中使用了元素运算符,因此无需更改这些条件的表达式。