【问题标题】:optimizing string search for a single byte优化单个字节的字符串搜索
【发布时间】:2015-09-30 20:07:08
【问题描述】:

一般来说,字符串搜索算法(如 Boyer-Moore)针对 搜索字符串 较长的情况进行了优化。也就是说,Boyer-Moore 很棒,因为通过将搜索字符串与我们的文本对齐,如果搜索字符串的结尾与文本不匹配,我们可以跳过 N = len(search string) 字符。

但是如果我们的搜索字符串真的很短怎么办?像单个字节或字符?在这种情况下,Boyer-Moore 没有多大帮助。

那么,有哪些替代算法可以加快搜索速度?

我知道许多优化的库搜索例程(如 C 中的memchr),采用逐字读取输入字符串的策略,而不是逐字符读取。所以在 64 位机器上,一次可以检查 8 个字节,而不是单个字节。

我想知道这些优化的字符串/字节搜索实际上是如何工作的。那么实际的比较是如何进行的呢?我知道它显然必须涉及位掩码 - 但我看不出执行所有位掩码比简单地逐个字符搜索更好。

所以,假设我们的搜索字符是0xFF。忽略对齐问题,假设我们有一些输入缓冲区:void* buf。我们可以逐字阅读:

const unsigned char search_char = 0xFF;
unsigned char* bufptr = static_cast<unsigned char*>(buf);
unsigned char* bufend = bufptr + BUF_SIZE;

while (bufptr != bufend)
{
   // Ignore alignment concerns for now, assume BUF_SIZE % sizeof(uintptr_t) == 0
   //
   std::uinptr_t next_word = *reinterpret_cast<std::uintptr_t*>(bufptr);

   // ... but how do we compare next_word with our search char?

   bufptr += sizeof(std::uintptr_t);
}

我也意识到上面的代码不是严格可移植的,因为不能保证std::uintptr_t 实际上是字长。但是,为了这个问题,我们假设std::uinptr_t 等于处理器字长。 (实际实现可能需要特定于平台的宏来获取实际字长)

那么,我们如何实际检查字节 0xFF 是否出现在 next_word 的值中的任何位置?

我们当然可以使用OR 操作,但似乎我们仍然需要执行大量的 OR'ing 和位移来检查next_word 的每个字节,此时这种优化是否会成为问题实际上比简单地逐个字符扫描要好。

【问题讨论】:

  • 为了加快搜索速度,您需要更改数据结构,例如对其进行排序或使用链表或哈希生成器。有时,对于小数据,蛮力线性搜索是您最快的选择。一些处理器具有在内存中搜索字节的专门功能。
  • 如果要搜索的数据很大,可以考虑使用多线程进行搜索。这种技术的一个棘手问题是设置线程的开销。理想情况下,您可以将线程处理委托给内核,例如 GPU 或处理器中的内核。
  • 可能看到this page
  • 我知道加快搜索的所有问题 - 对于庞大的数据集,像后缀树这样的东西可能很有用。我只是专门询问使用一次阅读一个单词的优化单字符搜索。我只是想了解实际的比较是如何完成的——为了加快搜索速度,做了哪些按位逻辑?
  • @Hasturkun - 谢谢这正是我想要的。如果您将其发布为答案,我会接受它

标签: c++ string-search


【解决方案1】:

你可以使用this snippet from Bit Twiddling Hacks:

#define haszero(v) (((v) - 0x01010101UL) & ~(v) & 0x80808080UL)
#define hasvalue(x,n) \
(haszero((x) ^ (~0UL/255 * (n))))

它有效地将每个字节与要测试的字符进行异或,然后确定现在是否有任何字节为零。

此时您可以从表达式的返回值中获取匹配字节(或多个字节)的位置,例如如果最低有效字节与该值匹配,则该值将为 0x00000080。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-07-16
    • 1970-01-01
    • 2013-09-08
    • 1970-01-01
    • 2014-07-12
    • 2011-10-23
    • 1970-01-01
    • 2012-04-08
    相关资源
    最近更新 更多