确定流中的所有字节是否相等

时间:2010-10-06 04:55:03

标签: algorithm language-agnostic

我正在寻找一种算法来检查流或缓冲区中的所有字节是否相等。是否有任何算法来测试?

我知道这个问题可以通过遍历流并将每个元素与第一个元素进行比较来解决,但我正在寻找更好的解决方案。流可以有数千个元素。

2 个答案:

答案 0 :(得分:2)

必须访问和检查每个字节,以便乐观的机会似乎有限。我可以想到两种可能性:

你对可变性的可能性有什么了解吗?例如,有理由认为差异更可能发生在缓冲区的一端或另一端。您可以统计检查一些样本数据输入,看看在一端或另一端开始比较是否有任何好处。

另一种可能性:你可以在整体或多头工作吗?在C中,您可以使用指针技巧将4个相邻字节视为int,然后进行int比较而不是字节比较。并不是很明显,这必须比4 x更快的字节比较更快,但可能就是这样。

这是少数几次即使手工组装也可能带来一些好处的场合之一。

答案 1 :(得分:0)

您能做的最好的事情就是进行线性比较。但是,您可以使用一些特定于体系结构的技巧来通过逐字而不是逐字节进行比较来大大加快比较速度。天真但可移植的方法可能看起来像这样:

bool all_bytes_equal(const char* buffer, size_t len) {
    char c = buffer[0];
    for(size_t i = 1; i < len; ++i)
        if(buffer[i] != c)
            return false;
    return true;
}

但是,如果您的体系结构支持轮换,则可以通过在32位体系结构上一次运行4个字节,或者在64位体系结构上一次运行8个字节来轻松地加快比较速度:

// For x86-64 architectures with ROTL/ROTR instruction support
bool all_bytes_equal(const char* buffer, size_t len) {
    const uint64_t* word_buf = (const uint64_t*) buffer;
    for(size_t i = 0; i < len / 8; ++i)
        if(word_buf[i] != _rotl64(word_buf[i], 8))
            return false;
    return true;
}

如果您的架构支持SSE / AVX,则可以通过对旋转移位进行矢量化来进一步加快速度(以下假设为AVX512,但是您可以将__m512替换为__m256__m128,并将_mm512_*函数族替换为_mm256_*_mm_*,并相应地替换循环增量):

bool all_bytes_equal(const char* buffer, size_t len) {
    for(size_t i = 0; i < len / 512; i += 512) {
        __m512 word = _mm512_load_epi64(buffer + i);
        if(_mm512_testn_epi64_mask(word, _mm512_rol_epi64(word, 8)))
            return false;
    }
    return true;
}

下面的两个示例对缓冲区的对齐方式进行了一些假设,但是您可以轻松地向其中添加代码以在缓冲区的开头/结尾处处理未对齐的字节。