【问题标题】:Searching for membership in array of ranges在范围数组中搜索成员资格
【发布时间】:2010-02-12 16:29:12
【问题描述】:

作为我们系统模拟的一部分,我正在使用稀疏内存数组对具有 64 位寻址的内存空间进行建模,并保留对象列表以跟踪在内存空间中分配的缓冲区。缓冲区是动态分配和取消分配的。

我有一个函数可以在分配的缓冲区中搜索给定的地址或地址范围,以查看对内存模型的访问是否在分配的空间中,我的第一个剪辑是“搜索所有缓冲区,直到找到匹配项“正在使我们的模拟速度减慢 10%。我们的 UUT 进行了大量的内存访问,这些访问必须经过模拟的审查。

所以,我正在尝试优化。内存缓冲区对象包含起始地址和长度。我正在考虑在对象创建时通过起始地址对对象数组进行排序,然后,当调用检查函数时,对数组进行二进制搜索以查看给定地址是否在开始/结束范围内。

有没有更好/更快的方法来做到这一点?肯定有一些更快/更酷的算法使用堆或哈希签名或类似的,对吧?

【问题讨论】:

    标签: algorithm search


    【解决方案1】:

    通过排序数组进行二分搜索可以工作,但会使分配/解除分配速度变慢。

    一个简单的例子就是做一个以起始地址为索引的有序二叉树(红黑树、AVR树等),这样插入(分配)、移除(deallocation)和查找都是O(log n )。大多数现代语言已经提供了这样的数据结构(例如 C++ 的std::map)。

    【讨论】:

      【解决方案2】:

      我的第一个想法也是二进制搜索,我认为这是一个好主意。您也应该能够快速插入和移除。使用哈希只会让您将地址放入存储桶(在我看来),然后您会快速找到正确的存储桶(然后必须搜索存储桶)。

      【讨论】:

        【解决方案3】:

        基本上你的问题是你有一个定义的“有效”内存间隔,这些间隔之外的内存是“无效的”,你想检查一个给定的地址是否在一个有效的内存块内。

        您绝对可以通过将所有已分配块的起始地址存储在二叉树中来做到这一点;然后搜索查询地址处或以下的最大地址,并验证该地址是否在有效地址的长度范围内。这为您提供 O(log n) 查询时间,其中 n = 分配的块数。当然,同样的查询也可以用于实际查找块本身,因此您还可以在给定地址读取块的内容,我猜您也需要。

        但是,这不是最有效的方案。相反,您可以使用额外的一维空间细分树来标记无效的内存区域。例如,使用分支因子为 256(对应 8 位)的树,将所有那些内部只有无效地址的 16kB 块映射到“1”,将其他块映射到“0”;这棵树只有两层,查询起来非常有效。当你看到一个地址时,首先从这棵树上询问它是否确实无效;只有当它不是时,才查询另一个。仅当您确实获得大量无效的内存引用时,这才会加快速度;如果所有内存引用实际上都是有效的并且您只是在断言,那么您将不会保存任何内容。但是你也可以翻转这个想法,对所有那些只有有效地址的 16kB 或 256B 块使用树形标记;树的大小取决于您模拟的内存分配器的工作方式。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-03-29
          • 1970-01-01
          相关资源
          最近更新 更多