向量化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

回到顶部