【发布时间】:2013-02-25 03:46:42
【问题描述】:
我编写了函数int compare_16bytes(__m128i lhs, __m128i rhs),以便使用 SSE 指令比较两个 16 字节数:该函数在执行比较后返回有多少字节相等。
现在我想使用上面的函数来比较任意长度的两个字节数组:长度可能不是 16 字节的倍数,所以我需要处理这个问题。我怎样才能完成下面功能的实现?如何改进下面的功能?
int fast_compare(const char* s, const char* t, int length)
{
int result = 0;
const char* sPtr = s;
const char* tPtr = t;
while(...)
{
const __m128i* lhs = (const __m128i*)sPtr;
const __m128i* rhs = (const __m128i*)tPtr;
// compare the next 16 bytes of s and t
result += compare_16bytes(*lhs,*rhs);
sPtr += 16;
tPtr += 16;
}
return result;
}
【问题讨论】:
-
使用 for 循环(长度 / 16 次),如果剩余字节数小于 16,则将零填充到 lhs 和 rhs。填充应该不同,以免错误计数填充相等。
-
while (length >= 16) { /* use your function */ length -= 16; } if (length) /* use a version that compares length (up to 15) bytes */; -
仅供参考,这通常称为Hamming distance——这可能作为搜索词有用。
-
C 库包括像
memset()这样的函数,可以处理任意数量的字节,但必须快速。为了速度,这些可以作为内联函数实现,因此您可以在包含文件中找到它们的源代码。研究它们是如何实现的可能会帮助您解决这个问题。另请查看 Agner Fog 的 asm 库:agner.org/optimize/#asmlib -
更好的方法是完全不使用您的
compare_16bytes函数并进行垂直比较/累加。然后在最后做一个减少。 (您还需要每 255 次迭代进行一次归约,以防止总和向量溢出。)