使用莫顿阶进行最近邻搜索的好处?

2024-01-25

在模拟粒子相互作用时,我偶然发现了莫顿阶(Z 阶)中的网格索引(维基百科链接 http://en.wikipedia.org/wiki/Z-order_%28curve%29)被认为提供了有效的最近邻小区搜索。我读到的主要原因是内存中空间上接近的单元几乎按顺序排列。

在第一次实现的过程中,我无法理解如何有效地实现最近邻居的算法,特别是与基本的统一网格相比。

  1. 给定一个单元格 (x,y),获取 8 个相邻单元格索引并计算相应的 z 索引很简单。尽管这提供了对元素的恒定访问时间,但必须计算 z-index 或在预定义表中查找(每个轴和 OR'ing 是分开的)。这怎么可能更有效率呢?按 A[0] -> A 的顺序访问数组 A 中的元素是真的吗1 http://en.wikipedia.org/wiki/Z-order_%28curve%29-> A[3] -> A[4] -> ... 比 A[1023] -> A[12] -> A[456] -> A[56] -> .. 的顺序更有效.?

  2. 我期望存在一种更简单的算法来查找 z 顺序中的最近邻居。大致意思是:找到邻居的第一个单元格,迭代。但这不可能是真的,因为这只能在 2^4 大小的块内有效。然而,存在两个问题:当单元格不在边界上时,我们可以轻松确定块的第一个单元格并迭代块中的单元格,但必须检查该单元格是否是最近邻居。当单元位于边界上时,情况会更糟,必须考虑 2^5 个单元。我在这里缺少什么?是否有一种相对简单且有效的算法可以满足我的需要?

第 1 点中的问题很容易测试,但我不太熟悉所描述的访问模式生成的底层指令,并且真的很想了解幕后发生的事情。

预先感谢您提供任何帮助、参考资料等...


EDIT:
Thank you for clarifying point 1! So, with Z-ordering, the cache hit rate is increased on average for neighbor cells, interesting. Is there a way to profile cache hit/miss rates?

关于第2点: 我应该补充一点,我了解如何为 R^d 中的点云构建莫顿有序数组,其中索引 i = f(x1, x2, ..., xd) 是通过按位交错等获得的。我尝试做的理解的是是否有比以下天真的 ansatz 更好的方法来获取最近的邻居(这里 d=2,“伪代码”):

// Get the z-indices of cells adjacent to the cell containing (x, y) 
// Accessing the contents of the cells is irrelevant here
(x, y) \elem R^2    
point = (x, y)
zindex = f(x, y)     
(zx, zy) = f^(-1)(zindex)          // grid coordinates 
nc = [(zx - 1, zy - 1), (zx - 1, zy), (zx - 1, zy + 1),  // neighbor grid 
      (zx    , zy - 1),               (zx,     zy + 1),  // coordinates
      (zx + 1, zy - 1), (zx + 1, zy), (zx + 1, zy + 1)]

ni= [f(x[0], x[1]) for x in nc]    // neighbor indices

在现代基于多级缓存的计算机系统中,空间局部性是优化数据元素访问时间的重要因素。

简而言之,这意味着如果您访问内存中的一个数据元素,那么访问内存中附近的另一个数据元素(具有接近第一个地址的地址)可能比访问内存中的数据元素便宜几个数量级。离这很远。

当按顺序访问一维数据时,例如简单的图像处理或声音处理,或者以相同的方式迭代处理每个元素的数据结构,然后按顺序排列内存中的数据元素往往会实现空间局部性 - 即,因为您访问元素N+1 在访问元素 N 后,这两个元素应该在内存中相邻放置。

标准 C 数组(以及许多其他数据结构)具有此属性。

Morton 排序的要点是支持访问数据的方案two维度上代替one维度上。换句话说,在访问元素 (x,y) 后,您可以继续访问 (x+1,y) 或 (x,y+1) 或类似的元素。

莫顿排序意味着 (x,y)、(x+1,y) 和 (x,y+1) 在内存中彼此接近。在标准的 c 多维数组中,情况不一定如此。例如,在数组 myArray[10000][10000] 中,(x,y) 和 (x,y+1) 相距 10000 个元素 - 相距太远而无法利用空间局部性。


在 Morton 排序中,标准的 c 数组仍然可以用作数据的存储,但是计算 (x,y) 的位置不再像 store[x+y*rowsize] 那么简单。

要使用 Morton 订购实现您的应用程序,您需要弄清楚如何将坐标 (x,y) 转换为商店中的地址。换句话说,你需要一个函数f(x,y)可用于访问商店,如下所示store[f(x,y)].

看起来您需要做更多研究 - 请点击维基百科页面上的链接,尤其是BIGMIN功能。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用莫顿阶进行最近邻搜索的好处? 的相关文章

  • 使用回溯(而不是 DFS)背后的直觉

    我正在解决单词搜索 https leetcode com problems word search description LeetCode com 上的问题 给定一个 2D 板和一个单词 查找该单词是否存在于网格中 该单词可以由顺序相邻单
  • 如何在 O(n) 时间内遍历二叉树而不需要额外的内存

    给定一棵带有整数 左指针和右指针的二叉树 如何在 O n 时间和 O 1 额外内存 无堆栈 队列 递归 内遍历该树 This guy http nandacumar blogspot com 2006 06 traversing tree
  • 使用Redis从有限范围内生成唯一ID

    我有一些数据库项目 除了主键之外 还需要项目所属组的唯一索引 我们来调用属性nbr 以及将项目分组在一起并定义唯一范围的属性nbr 我们会打电话group This nbr必须在 1 N 范围内 并且may从外部源导入项目时进行设置 由于所
  • 以与版本页面上相同的方式区分两个字符串的算法是什么?

    我正在尝试按短语区分两个字符串 类似于 StackOverflow 在版本编辑页面上区分两个字符串的方式 执行此操作的算法是什么 是否有 gems 或其他标准库可以实现此目的 编辑 我见过其他比较算法 Differ http github
  • 在 Python 中删除表达式树及其每个子表达式树中第一个元素周围的括号

    目标是实现简化操作 删除表达式树及其每个子表达式树中第一个元素周围的括号 其中表达式作为括在各个括号中的字符串输入给出 这必须适用于任意数量的括号 例如 12 3 45 6 gt 123 45 6 删除 12 周围的括号 然后删除 45 周
  • 用 ruby​​ 解决旅行商问题(50 多个位置)

    我在一家快递公司工作 目前 我们 手动 解决了 50 多个地点的路线 我一直在考虑使用 Google Maps API 来解决这个问题 但我读到有 24 点的限制 目前我们在服务器中使用 Rails 因此我正在考虑使用 ruby 脚本来获取
  • 如何检查一个盒子是否适合另一个盒子(允许任何旋转)

    假设我有两个盒子 每个盒子都是一个长方体 http en wikipedia org wiki Rectangular cuboid aka长方体 我需要编写一个函数来决定盒子是否具有尺寸 一 二 三 可以装入具有尺寸的盒子中 甲 乙 丙
  • 如何选择部分密集数据集的均匀分布子集?

    P是一个 n d 矩阵 持有nd 维样本 P某些地区的密度是其他地区的几倍 我想选择一个子集P其中任意样本对之间的距离大于d0 并且我需要将其传播到整个区域 所有样本都具有相同的优先级 无需优化任何内容 例如覆盖面积或成对距离之和 这是执行
  • C# 计算LRC(纵向冗余检查)

    我一直在到处研究这个问题 所有 LRC 实现似乎都没有给我正确的答案 花了几天时间后 我决定将我的代码放在这里 看看其他人是否可以发现问题 这是代码 C Input Data 31303030315E315E31303030325E315E
  • 如何使用KDTrees实现最近邻搜索?

    所以 我正在实施一个KD Tree http en wikipedia org wiki Kd tree进行最近邻搜索 我已经构建了树部分 但我认为我没有完全理解搜索部分 关于遍历树来搜索邻居 维基百科文章如下 Starting with
  • Bellman-Ford 算法检测什么?负重还是负循环?

    如果给定一个图 现在我们要从源头计算最短路径 现在 如果一条边具有负权重 但在到达目的地时有边到后边返回到该边 我的意思是如果没有循环 那么我们就没有负循环 但是here http en wikipedia org wiki Bellman
  • 如何计算两个ip之间的主机数量? C#

    我有两个ip 1 1 1 1 1 2 4 4 4 4 显然这只是一个例子 这是一个动态计算器 如果子网掩码不相关 我如何计算所述 ip 之间的主机数量 要计算 理论 IP 地址的数量 您需要将每个 IP 地址转换为其 32 位整数格式 这实
  • 合并字符数组中的最小重复次数

    假设我有两个数组 我想合并它们 以便合并后的数组具有最小重复次数 例如 x x 是重复 arr1 x d d m f m arr2 d d x f f m 唯一的条件是在合并数组中 元素来自arr1 and arr2必须出现在各自的订单中a
  • 反转二进制网络

    如何反转二元方程 以便找到哪些输入将产生给定的输出 Example Inputs i0 through i8 Outputs o0 through o8 Operators XOR AND 二元方程 1 i0 1 i1 0 i2 1 i3
  • 按百分比减少多边形面积

    我有一个由点 x y 组成的多边形 我想做的是将其减少一个百分比 请记住 我不想只是扩大规模 多边形应该有一种内部边界 其宽度取决于百分比 该内部边界被多边形切断 谁知道可以实现这一目标的算法 输入 点数组 百分比 输出 点数组 你所寻求的
  • Java:如何实现3和?

    我正在研究 3 Sum 来自己实现它 并遇到了以下规则的实现 给定一个由 n 个整数组成的数组 S S 中是否存在满足 a b c 0 的元素 a b c 查找数组中所有总和为零的唯一三元组 注意 三元组 a b c 中的元素必须按非降序排
  • 搜索/排序算法 - 是否有类似 GoF 的列表?

    我是一名自学成才的开发人员 坦率地说 我不太擅长找出在任何特定情况下使用哪种搜索或排序算法 我只是想知道是否有设计模式 esque 列出了以太坊中可用的常见算法 供我添加书签 就像是 算法名称 带有别名 如果有的话 它解决的问题 大O成本
  • 用 Java 创建迷宫求解算法

    我被分配了用 Java 创建迷宫求解器的任务 这是任务 Write an application that finds a path through a maze The maze should be read from a file A
  • cordova 使用什么 js“引擎”?

    Cordova 使用什么 JS 引擎 它是特定于平台的还是跨所有平台的一个标准 意味着 iOS 的 safari 和 Android 的 chrome 以及 Windows 可能的 IE 标准 或者跨所有平台的 Cordova JS 引擎
  • 如何查找给定字符串中仅出现一次的第一个字符[关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi

随机推荐