向量化matlab代码
我有点新的矢量化。已经尝试过自己但不能。有人可以帮助我对这段代码进行矢量化,并简要说明如何做,以便我可以调整思维过程。谢谢。向量化matlab代码
function [result] = newHitTest (point,Polygon,r,tol,stepSize) %This function calculates whether a point is allowed.
%First is a quick test is done by calculating the distance from point to
%each point of the polygon. If that distance is smaller than range "r",
%the point is not allowed. This will slow down the algorithm at some
%points, but will greatly speed it up in others because less calls to the
%circleTest routine are needed.
polySize=size(Polygon,1);
testCounter=0;
for i=1:polySize
d = sqrt(sum((Polygon(i,:)-point).^2));
if d < tol*r
testCounter=1;
break
end
end
if testCounter == 0
circleTestResult = circleTest (point,Polygon,r,tol,stepSize);
testCounter = circleTestResult;
end
result = testCounter;
回答:
鉴于信息Polygon
是2维的,point
是行向量和其他变量是标量,这里是你的新功能的第一个版本(向下滚动看到,有很多方法对皮肤这个猫):
function [result] = newHitTest (point,Polygon,r,tol,stepSize) result = 0;
linDiff = Polygon-repmat(point,size(Polygon,1),1);
testLogicals = sqrt(sum((linDiff).^2 ,2)) < tol*r;
if any(testLogicals); result = circleTest (point,Polygon,r,tol,stepSize); end
在Matlab矢量化的思想过程涉及尝试使用单个命令操作尽可能多的数据。大多数基本的Matlab内置函数在多维数据上运行非常高效。使用for
循环与此相反,因为您正在将数据分解为更小的数据段进行处理,每个数据段都必须单独解释。通过使用for
循环进行数据分解,您可能会失去与Matlab内置函数背后的高度优化代码相关的一些大规模性能优势。
在您的示例中首先要考虑的是主循环中的条件中断。你无法从矢量化过程中解脱出来。相反,计算所有可能性,为每行数据创建一个结果数组,然后使用关键字any
来查看是否有任何行已发出信号表明circleTest
函数应该被调用。
注意:在Matlab中有效地有条件地打破计算并不容易。但是,由于您只是在循环中计算欧几里德距离,所以通过使用矢量化版本和计算所有可能性,您可能会看到性能提升。如果循环中的计算更加昂贵,输入数据很大,并且一旦遇到特定条件就想要分解,那么使用编译语言编写的matlab扩展可能比矢量化版本快得多你可能正在执行不必要的计算。然而,这是假设您知道如何编写与编译为本地代码的语言相匹配的Matlab内置函数性能的代码。
回到主题...
做的第一件事就是把Polygon
和你的行向量point
之间(在代码示例linDiff
)线性差。要以矢量化的方式进行此操作,2个变量的尺寸必须相同。达到此目的的一种方法是使用repmat
复制point
的每一行,使其与Polygon
的大小相同。然而,bsxfun
通常是一个更好的选择repmat(as described in this recent SO question),使得代码...
function [result] = newHitTest (point,Polygon,r,tol,stepSize) result = 0;
linDiff = bsxfun(@minus, Polygon, point);
testLogicals = sqrt(sum((linDiff).^2 ,2)) < tol*r;
if any(testLogicals); result = circleTest (point,Polygon,r,tol,stepSize); end
我通过在第二轴求和轧制您d
值成d
列(注意去除所述阵列的Polygon
的索引和在sum
命令中增加,2
)。然后,我进一步深入并评估逻辑阵列testLogicals
与距离测量的计算内嵌。您很快就会发现重矢量化的一个缺点就是它可以让那些不熟悉Matlab的人对代码的可读性降低,但性能提升是值得的。评论是非常必要的。
现在,如果你想完全疯狂,你可能会认为测试函数非常简单,因此它保证使用'匿名函数'或'lambda'而不是完整的函数定义。测试是否值得执行circleTest
不需要参数stepSize
,这也许是使用匿名函数的另一个原因。您可以将测试转换为匿名函数,然后在调用脚本中使用circleTest
,从而使代码在某种程度上自行记录。 。 。
doCircleTest = @(point,Polygon,r,tol) any(sqrt(sum(bsxfun(@minus, Polygon, point).^2, 2)) < tol*r); if doCircleTest(point,Polygon,r,tol)
result = circleTest (point,Polygon,r,tol,stepSize);
else
result = 0;
end
现在一切都是向量化的,使用函数句柄给了我另一个想法。 。 。
如果您计划在代码中的多个点执行此操作,那么if
语句的重复会变得有点难看。要保持dry,将条件函数的测试放入单个函数似乎是明智的,就像您在原始文章中所做的那样。但是,该函数的实用程序将非常狭窄 - 它只会测试circleTest
函数是否应该执行,然后在需要时执行它。
现在想象一下,过了一段时间,您还有其他一些条件函数,就像circleTest
一样,其自身等效于doCircleTest
。也许重用条件转换代码会很好。对于这一点,让喜欢你原来的一个函数,它的默认值,计算上廉价的测试功能的布尔结果,以及与其相关的参数的昂贵条件函数的功能手柄...
function result = conditionalFun(default, cheapFunResult, expensiveFun, varargin) if cheapFunResult
result = expensiveFun(varargin{:});
else
result = default;
end
end %//of function
你可以使用以下命令从主脚本调用此函数。 。 。
result = conditionalFun(0, doCircleTest(point,Polygon,r,tol), @circleTest, point,Polygon,r,tol,stepSize);
...它的美丽之处在于您可以使用任何测试,默认值和昂贵的功能。这个简单的例子可能有点矫枉过正,但是当我提出使用函数句柄的想法时,它就是我思绪徘徊的地方。
以上是 向量化matlab代码 的全部内容, 来源链接: utcz.com/qa/263027.html