Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在三维距离检查中,点A是否在点B附近_Algorithm_Performance_Distance - Fatal编程技术网

Algorithm 在三维距离检查中,点A是否在点B附近

Algorithm 在三维距离检查中,点A是否在点B附近,algorithm,performance,distance,Algorithm,Performance,Distance,我正在寻找有效的算法来检查一个点是否在3D中靠近另一个点 sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2) < radius sqrt((x2-x1)^2+(y2-y1)^2+(z2-z1)^2)

我正在寻找有效的算法来检查一个点是否在3D中靠近另一个点

sqrt((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2) < radius
sqrt((x2-x1)^2+(y2-y1)^2+(z2-z1)^2)

这似乎不是太快,实际上我不需要这么大的准确性。我还能怎么做呢?

将距离平方,然后放弃对
sqrt()
的调用,这要快得多:

(((x2-x1)^2 + (y2-y1)^2 + (z2-z1)^2 < radius * radius
((x2-x1)^2+(y2-y1)^2+(z2-z1)^2<半径*半径

当然,在许多情况下,至少可以提前计算出
半径*半径
,并将其存储为例如
squaredRadius

使用max(abs(x1-x2)、abs(y1-y2)、abs(z1-z2))

如果你满足于立方体距离而不是球面距离,那么一个非常简单的实现就是这样的:

Math.Abs(x2-x1) < radius && Math.Abs(y2-y1) < radius && Math.Abs(z2-z1) < radius 
Math.Abs(x2-x1)
如果Math.Abs被证明是一个瓶颈,您可以使用自己喜欢的优化Math.Abs的方法


我还应该补充一点,如果其中一个维度的变化通常小于其他维度,那么最后一个维度的变化将导致性能提高。例如,如果您主要处理“地面”上的对象x-y平面,然后最后检查z轴,因为您应该能够通过使用x和y检查排除前面的碰撞。

如果您不需要精度,您可以检查您是否在立方体而不是球体中

这里还有一些选项,您可以选择包围球体的立方体(无误报)、与球体体积相同的立方体(一些误报和误报,但最大误差最小化)、球体中包含的立方体(无误报)

这项技术也很好地扩展到更高的维度


如果您想让所有点靠近另一个点,也可以使用某种形式的空间索引(可能是kd树)

如果您不需要高精度,您可以检查第二个点是否在立方体(边长“2a”)内,而不是球体内,其中第一个点位于中心:

|x2-x1|<a && |y2-y1|<a && |z2-z1|<a

| x2-x1 |由于流水线处理器体系结构,如今,在大多数情况下,将FPU计算两次比分支一次更有效。如果分支预测错误,则会延迟很长时间(以cpu为单位)


<>所以,我宁愿走计算方式,而不是分支方式。

< P>如果你必须检查许多其他点,你可以考虑使用空间排序方法快速地找到靠近某个位置的点。看看这个链接:

在去掉平方根后,如果值变大,最好应用log。

如果我们要优化它,因为它要运行数十亿次,我会使用unwind的方法来解决这个问题,然后使用SIMD将其并行化。有几种不同的方法可以做到这一点。您可以简单地执行所有子任务一个运算中的动作(x2-x1,y2-y1,z2-z1),然后在一个运算中的乘法。这样,您就可以在方法内部并行化,而无需重新设计算法

或者您可以编写一个批量版本,在许多元素上计算(x2-x1)^2+(y2-y1)^2+(z2-z1)^2-r^2,并将结果存储在数组中。您可能会获得更好的吞吐量,但这意味着重新设计算法,这取决于测试的用途


如果您真的在一行中进行了大量测试,您还可以使用类似OpenMP的工具轻松优化此操作。

这会计算立方体距离,如果您进行了大量点,大多数时候它只进行第一次测试

close = (abs(x2-x1) < r && abs(y2-y1) < r && abs(z2-z1) < r);
close=(abs(x2-x1)
有了所有这些条件逻辑测试,这真的更快了吗?乘法在现代CPU上几乎没有效率。条件逻辑也几乎没有效率!实际上,由于分支预测失误,紧循环中的条件逻辑可能比只计算所有内容的效率低。您需要条件逻辑来实现
doub吗le abs(双倍)
双倍最大值(双倍,双倍)
无论如何?不确定。这不是一个标准的op IIRC,这使得假设优化是有风险的。你为什么不认为这很快?你有没有理由认为这段代码会成为一个问题,比如运行了十亿次?也许你需要的是将你的点存储在一个空间结构(如八叉树)中,以便能够拥有更少的点点与点之间的距离以框与框之间的距离为界。@darid:再做一次数学运算。√只要p,q是非负的,pabs(x)
(x*x)快,这将是一台不同寻常的机器,尤其是对于非整数。一般规则,知道哪一个算法更快,是测试它们,自己看。因为有一个C++标签,我觉得我应该提到,意思是‘XOR’,而不是“Palm”(我确信“巴隆已经知道:-”)对于与数学相关的主题,我们可能需要像Wikipedia中那样的LaTeX格式。在Wikipedia公式图像生成代码中合并应该不会太困难。当人们抱怨临近度测定太慢时,通常是因为进行了太多的运算。你能用空间分割(如octr)解决问题吗EE /四叉树或BSP?@ JAMESHopkin,因为他们说“比以前更好”——我现在删除了C++标签,因为这个问题很一般,而不是C++特定的:如果它在立方体中,仍然可以细化为球形DIST。