提高 MATLAB 中分段函数的速度
Improve Speed of Piecewise Function in MATLAB
我有一个小的分段函数,分析显示它占用了程序运行时间的 60%。它经常被调用,因为它包含在我的代码中经常执行的一些积分中。
根据分析,它被调用了 213560 次,总共耗时 47.786 秒,相当于每次调用约 220 微秒。
我想给它传递一个数组,它应该return一个数组,明智地操作元素。
我知道在 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
您可以使用 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
小评论
0e-3
在精确度方面没有任何意义。这与 0
基本相同,我已经在您的代码中进行了更改。
- 请注意,对于条件 #2 和 #4,我预先计算了一个
logical
数组,该数组指示我们需要在何处访问 z_array
中的相应值以简化操作并设置相同的位置在 bottleradius
中成为所需的计算输出。我不会对其他条件执行此操作,因为您只是将它们设置为一个常量。
- 幸运的是,您对条件 #2 和 #4 使用了逐元素运算符,因此无需更改这些条件的表达式。
我有一个小的分段函数,分析显示它占用了程序运行时间的 60%。它经常被调用,因为它包含在我的代码中经常执行的一些积分中。
根据分析,它被调用了 213560 次,总共耗时 47.786 秒,相当于每次调用约 220 微秒。
我想给它传递一个数组,它应该return一个数组,明智地操作元素。
我知道在 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
您可以使用 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
小评论
0e-3
在精确度方面没有任何意义。这与0
基本相同,我已经在您的代码中进行了更改。- 请注意,对于条件 #2 和 #4,我预先计算了一个
logical
数组,该数组指示我们需要在何处访问z_array
中的相应值以简化操作并设置相同的位置在bottleradius
中成为所需的计算输出。我不会对其他条件执行此操作,因为您只是将它们设置为一个常量。 - 幸运的是,您对条件 #2 和 #4 使用了逐元素运算符,因此无需更改这些条件的表达式。