【问题标题】:Fast hamming distance between 2 bitset2个位集之间的快速汉明距离
【发布时间】:2011-10-21 15:47:06
【问题描述】:

我正在编写一个严重依赖于 (1) 访问单个位和 (2) 2 个位集 A 和 B 之间的汉明距离计算(即 A 和 B 之间不同的位数)的软件。这些位集非常大,介于 10K 和 1M 位之间,我有一堆。由于在编译时不可能知道 bitset 的大小,我使用的是 vector < bool >,但我计划很快迁移到 boost::dynamic_bitset

以下是我的问题:

(1) 关于哪些实现具有最快的单位访问时间的任何想法?

(2) 要计算汉明距离,最简单的方法是循环单个位并计算 2 个位集之间的差异。但是,我的感觉是,循环遍历字节而不是位,执行 R = byteA XOR byteB,并在包含 255 个条目的表中查看与 R 关联的“本地”距离可能要快得多。另一种解决方案是存储255 x 255 矩阵,无需操作即可直接访问 byteA 和 byteB 之间的距离。所以我的问题是:知道如何从std::vector < bool > 或 boost::dynamic_bitset 实现它吗?换句话说,你知道是否有办法访问字节数组或者我必须从头开始重新编码所有内容?

【问题讨论】:

  • 您是否尝试过使用 dynamic_bitset 的 operator^count() 方法,并对其进行分析以查看性能是否足够?这可能是实现对您来说已经足够好了。
  • 鉴于各种答案,我刚刚使用 boost::dynamic_bitset & vector 和优化标志 -O2 进行了一些基本测试。两种实现之间的访问时间大致相同(差异的 3%)。更重要的是,如果您使用 operator^ 和 count() 来计算汉明距离,与幼稚的方法相比,您将运行时间除以 10!!!!哇哦,非常感谢!
  • @koskos 请发布基准测试代码。

标签: c++


【解决方案1】:

(1) 可能是vector<char>(甚至是vector<int>),但这在典型硬件上浪费了至少7/8 的空间。如果您使用一个或更多字节来存储它们,则不需要解压缩这些位。 vector<bool>dynamic_bitset 哪个更快,我不知道。这可能取决于 C++ 实现。

(2) boost::dynamic_bitsetoperator^ 和一个 count 成员,它们一起可用于以可能快速但浪费内存的方式计算汉明距离。您还可以使用to_block_range 访问底层缓冲区;要使用它,您需要将汉明距离计算器实现为 OutputIterator

【讨论】:

    【解决方案2】:

    如果您从头开始编写代码,则可能比一次一个字节做得更好:从每个位集中一次取一个字。 XOR 的成本应该非常低,然后使用特定于实现的内置函数 popcount,或者您可以找到的最快的位旋转 popcount(可能涉及也可能不涉及 256 项查找)。

    [编辑:看起来这可能适用于boost::dynamic_bitset::to_block_rangeBlock 选择为intlong。遗憾的是它写入 OutputIterator 而不是给您 InputIterator - 我无法立即看到如何使用它来一起迭代两个位集,除非使用额外的线程或将其中一个位集复制到一个int 数组优先。无论哪种方式,如果将程序控制权留给您,您将获得一些本来可以避免的复制开销。这个任务的线程相当复杂,当然也有它自己的开销,而且复制出数据可能并不比使用operator^count() 更好。]

    【讨论】:

      【解决方案3】:

      我知道这会因异端邪说而被否决,但就是这样:您可以使用 &vector[0]; 从向量中获取指向实际数据的指针; (对于向量 ymmv)。然后,您可以使用 c 风格的函数对其进行迭代;意思是,将您的指针转换为一个 int 指针或类似的东西,执行上述汉明算术,并一次移动指针一个字长。这只会起作用,因为您知道这些位是连续打包在一起的,并且很容易受到攻击(例如,如果向量被修改,它可能会移动内存位置)。

      【讨论】:

      • 与其说是异端,不如说vector<bool> 不是一个容器,它的operator[] 不返回对数据缓冲区的引用。为了节省内存,它是紧密封装的,但这样做的代价是单个位在 C++ 中没有地址。所以“YMMV”是一个非常重要的警告。
      • Doh。现在我明白了。不够聪明。听起来 vector 无论如何都是要避免的:informit.com/guides/content.aspx?g=cplusplus&seqNum=98
      猜你喜欢
      • 2016-12-16
      • 1970-01-01
      • 1970-01-01
      • 2015-12-20
      • 2020-12-18
      • 2014-09-25
      • 2015-03-21
      • 1970-01-01
      相关资源
      最近更新 更多